refactor: 문서 개선 중

This commit is contained in:
donghyeon-ka
2026-09-21 14:30:55 +09:00
parent c93cdea150
commit 805a18f486
1497 changed files with 525837 additions and 59152 deletions
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="680" height="690" viewBox="0 0 680 690" role="img" aria-labelledby="diagram-title diagram-description">
<title id="diagram-title">지우지 않으면 통과한</title>
<desc id="diagram-description">nginx 는 자기가 proxy_set_header 로 설정한 헤더만 덮어쓴다. 설정하지 않은 이름은 클라이언트가 보낸 값이 그대로 지나간다. 그래서 X-Auth-Request-Roles 같은 헤더를 앱이 믿으려면 프록시가 그 이름을 먼저 빈 값으로 지워야 한다. 그리고 IdP 에서 클레임을 바꿔도 반영되지 않는다. 12회 요청 6초 동안 옛 값이 갔고 세션을 지워 재인증한 뒤에야 새 값이 왔다. 세션은 로그인 시점의 스냅샷이다.</desc>
<metadata>{&quot;techviz&quot;:{&quot;spec_version&quot;:&quot;1.1&quot;,&quot;id&quot;:&quot;b4-header-trust-boundary&quot;,&quot;profile&quot;:&quot;component-flow&quot;},&quot;source_context&quot;:{&quot;document&quot;:&quot;docs/keycloak-session-store/final/document.md&quot;,&quot;document_sha256&quot;:&quot;1d44cba1905544d92f1d26ae36a8deb64a3db3914d6b488fd30d6ae7f8cfbabe&quot;,&quot;anchor&quot;:{&quot;kind&quot;:&quot;heading&quot;,&quot;value&quot;:&quot;B-4 · Edge 인가의 범위 (Q4)&quot;,&quot;line&quot;:401}},&quot;evidence_policy&quot;:&quot;Each factual element cites source lines or is marked assumption.&quot;,&quot;diagram_only&quot;:true}</metadata>
<svg xmlns="http://www.w3.org/2000/svg" width="999" height="319" viewBox="0 0 999 319" role="img" aria-labelledby="diagram-title diagram-description">
<title id="diagram-title">헤더 도착과 인가 우회는 다르</title>
<desc id="diagram-description">위조 헤더는 app1.hyeonworks.com/api 의 permitAll echo 앱까지 그대로 도착했다. 같은 헤더로 JWT 를 요구하는 /api/me 와 /api/protected 를 호출하면 401이었다. 따라서 헤더 도착과 인가 우회는 다른 사건이다. proxy_set_header 로 먼저 지우는 것은 문서에 적힌 처방이지만 이 실험대에서는 적용하지 않아 미검증이다.</desc>
<metadata>{&quot;techviz&quot;:{&quot;spec_version&quot;:&quot;1.1&quot;,&quot;id&quot;:&quot;b4-header-trust-boundary&quot;,&quot;profile&quot;:&quot;component-flow&quot;},&quot;source_context&quot;:{&quot;document&quot;:&quot;docs/keycloak-session-store/final/document.md&quot;,&quot;document_sha256&quot;:&quot;28aef96a2bbb94fbb10ade26a71238fee62a5a4d9fa6e7749ae98cfd0a65e560&quot;,&quot;anchor&quot;:{&quot;kind&quot;:&quot;heading&quot;,&quot;value&quot;:&quot;B-4 · Edge 인가의 범위 (Q4)&quot;,&quot;line&quot;:821}},&quot;evidence_policy&quot;:&quot;Each factual element cites source lines or is marked assumption.&quot;,&quot;diagram_only&quot;:true}</metadata>
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" />
@@ -49,36 +49,36 @@
.timeline-detail { font-size: 11px; fill: #4b5563; text-anchor: middle; }
</style>
</defs>
<rect class="canvas" width="680" height="690" />
<polyline class="edge kind-request style-solid emphasis-normal" points="167.5,144.0 167.5,192.0 167.5,192.0 167.5,240.0" data-evidence="393-400" />
<rect class="edge-label-bg" x="165.8" y="178.0" width="51.5" height="22" rx="3" />
<text class="edge-label" x="191.5" y="193.0">위조 헤더</text>
<polyline class="edge kind-request style-solid emphasis-normal" points="167.5,311.0 167.5,359.0 167.5,359.0 167.5,407.0" data-evidence="393-400" />
<rect class="edge-label-bg" x="155.7" y="345.0" width="71.6" height="22" rx="3" />
<text class="edge-label" x="191.5" y="360.0">미삭제 시 통과</text>
<polyline class="edge kind-request style-solid emphasis-normal" points="167.5,478.0 167.5,526.0 167.5,526.0 167.5,574.0" data-evidence="393-408" />
<rect class="edge-label-bg" x="165.8" y="512.0" width="51.5" height="22" rx="3" />
<text class="edge-label" x="191.5" y="527.0">인가 헤더</text>
<rect class="canvas" width="999" height="319" />
<polyline class="edge kind-request style-solid emphasis-normal" points="240.0,167.0 320.0,167.0 320.0,167.0 400.0,167.0" data-evidence="823-830" />
<rect class="edge-label-bg" x="294.2" y="125.0" width="51.5" height="22" rx="3" />
<text class="edge-label" x="320.0" y="140.0">위조 헤더</text>
<polyline class="edge kind-request style-solid emphasis-normal" points="550.0,158.0 647.5,158.0 647.5,95.5 745.0,95.5" data-evidence="825-840" />
<rect class="edge-label-bg" x="642.4" y="112.8" width="58.2" height="22" rx="3" />
<text class="edge-label" x="671.5" y="127.8">그대로 전달</text>
<polyline class="edge kind-request style-solid emphasis-normal" points="550.0,176.0 630.0,176.0 630.0,238.5 710.0,238.5" data-evidence="832-840" />
<rect class="edge-label-bg" x="628.2" y="193.2" width="51.5" height="22" rx="3" />
<text class="edge-label" x="654.0" y="208.2">같은 헤더</text>
<g id="node-attacker">
<g class="actor-symbol emphasis-warning" data-evidence="393-400"><circle cx="167.5" cy="80.0" r="11.0" /><line x1="167.5" y1="96.0" x2="167.5" y2="105.0" /><line x1="149.5" y1="106.0" x2="185.5" y2="106.0" /><line x1="167.5" y1="105.0" x2="152.5" y2="122.0" /><line x1="167.5" y1="105.0" x2="182.5" y2="122.0" /></g>
<text class="node-label" x="167.5" y="137.0">외부 위조 헤더</text>
<g class="actor-symbol emphasis-warning" data-evidence="823-830"><circle cx="155.0" cy="145.0" r="11.0" /><line x1="155.0" y1="161.0" x2="155.0" y2="180.0" /><line x1="137.0" y1="171.0" x2="173.0" y2="171.0" /><line x1="155.0" y1="180.0" x2="140.0" y2="197.0" /><line x1="155.0" y1="180.0" x2="170.0" y2="197.0" /></g>
<text class="node-label" x="155.0" y="202.0">외부 위조 헤더</text>
</g>
<g id="node-nginx">
<polygon class="node-shape kind-gateway emphasis-warning role-control" data-evidence="393-400" points="167.5,240.0 265.0,275.5 167.5,311.0 70.0,275.5" />
<text class="node-label" x="167.5" y="267.0">nginx</text>
<line class="node-detail-divider" x1="84.0" y1="288.0" x2="251.0" y2="288.0" />
<text class="node-detail" x="86.0" y="305.0">proxy_set_header ... &quot;&quot;</text>
<polygon class="node-shape kind-gateway emphasis-warning role-control" data-evidence="829-830" points="475.0,131.5 550.0,167.0 475.0,202.5 400.0,167.0" />
<text class="node-label" x="475.0" y="158.5">nginx</text>
<line class="node-detail-divider" x1="414.0" y1="179.5" x2="536.0" y2="179.5" />
<text class="node-detail" x="416.0" y="196.5">동명 헤더 미삭제</text>
</g>
<g id="node-proxy">
<polygon class="node-shape kind-gateway emphasis-normal role-control" data-evidence="393-400" points="167.5,407.0 247.5,442.5 167.5,478.0 87.5,442.5" />
<text class="node-label" x="167.5" y="434.0">oauth2-proxy</text>
<line class="node-detail-divider" x1="101.5" y1="455.0" x2="233.5" y2="455.0" />
<text class="node-detail" x="103.5" y="472.0">--set-xauthrequest</text>
<g id="node-echo">
<rect class="node-shape kind-service emphasis-normal role-target" data-evidence="825-840" x="745.0" y="60.0" width="174.0" height="71.0" rx="7" />
<text class="node-label" x="832.0" y="87.0">permitAll echo</text>
<line class="node-detail-divider" x1="759.0" y1="108.0" x2="905.0" y2="108.0" />
<text class="node-detail" x="761.0" y="125.0">/api/echo · HTTP 200</text>
</g>
<g id="node-app">
<rect class="node-shape kind-service emphasis-primary role-target" data-evidence="401-408" x="92.5" y="574.0" width="150.0" height="71.0" rx="7" />
<text class="node-label" x="167.5" y="601.0"></text>
<line class="node-detail-divider" x1="106.5" y1="622.0" x2="228.5" y2="622.0" />
<text class="node-detail" x="108.5" y="639.0">로그인 시점 스냅샷</text>
<g id="node-protected">
<rect class="node-shape kind-service emphasis-primary role-target" data-evidence="832-840" x="710.0" y="203.0" width="244.0" height="71.0" rx="7" />
<text class="node-label" x="832.0" y="230.0">JWT 보호 경로</text>
<line class="node-detail-divider" x1="724.0" y1="251.0" x2="940.0" y2="251.0" />
<text class="node-detail" x="726.0" y="268.0">/api/me · /api/protected · 401</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB