feat: 가상화 문서들 추가
This commit is contained in:
+18
-22
@@ -1,5 +1,5 @@
|
||||
---
|
||||
id:
|
||||
id: 036563a1-3a43-4931-a017-0e693b591e89
|
||||
kind: REFERENCE
|
||||
slug: runtime-verification-safe-order
|
||||
title: 패턴 검증을 실제로 돌릴 때의 안전한 순서
|
||||
@@ -7,7 +7,7 @@ topic: oauth-oidc-auth-boundary
|
||||
topicName: OAuth/OIDC 인증 경계
|
||||
project: KeyCloak Patterns
|
||||
status: 게시 전
|
||||
studio: ""
|
||||
studio: "https://hyeonworks.com/studio/documents/036563a1-3a43-4931-a017-0e693b591e89/edit"
|
||||
sourceRevision: keycloak-patterns-lab@2026-08
|
||||
source:
|
||||
- final/document.md#결정이-지켜지는지-확인하는-방법-실제-runtime-검증을-수행할-때의-안전한-순서
|
||||
@@ -17,52 +17,48 @@ source:
|
||||
|
||||
네 패턴의 경계가 실제로 성립하는지 보려면 스택을 띄우고 브라우저로 로그인까지 해 봐야 하는데, 패턴별 검증 절차는 스택을 다시 만들기 전에 볼륨을 초기화한다. 보존해야 할 realm이나 데이터베이스가 같은 Compose 프로젝트에 있으면 검증을 돌리는 사이에 그 데이터를 잃는다.
|
||||
|
||||
대상 환경이 일회용인지 확정한 다음에 첫 검사를 돌리고, 마지막에는 테스트용 스택을 내리고 원래 환경을 복구해 다시 확인하는 것으로 닫는다. 중간에 하나라도 어긋나면 나머지를 계속 돌려 전체 통과를 만들지 않는다.
|
||||
그래서 대상 환경이 일회용인지 확정한 다음에 첫 검사를 돌리고, 마지막에는 테스트용 스택을 내린 뒤 원래 환경을 복구해 다시 확인한다. 중간에 하나라도 어긋나면 나머지를 계속 돌려 전체 통과를 만들지 않는다.
|
||||
|
||||
## 관계
|
||||
|
||||
- **Forward-Auth에서 Client가 보낸 Identity Header를 신뢰하면 안 되는 이유**
|
||||
이 절차로 확인하는 경계 가운데 하나이고, 위조 헤더를 보내 보는 것이 5번 규칙의 부정 입력에 해당한다.
|
||||
이 절차로 확인하는 경계 가운데 하나다. 위조 헤더를 보내 보는 것이 5번 규칙의 부정 입력이다.
|
||||
- **OAuth/OIDC 인증 패턴 선택 기준**
|
||||
어느 구조를 고를지 정하는 기준과, 고른 구조가 코드에서 실제로 성립하는지 확인하는 절차는 같이 쓴다.
|
||||
어느 구조를 고를지는 그 기준으로 정하고, 고른 구조가 실제로 그렇게 동작하는지는 이 절차로 확인한다.
|
||||
|
||||
## 목적
|
||||
|
||||
이 절차가 막으려는 것은 두 가지다. 하나는 지워서는 안 될 데이터를 지우는 일이다. 검증 절차에 볼륨 초기화가 들어 있으므로, 실행 순서를 정하기 전에 대상이 지워도 되는 환경인지부터 확정해야 한다.
|
||||
|
||||
다른 하나는 앞 단계가 어긋났는데도 나머지를 계속 돌려 마지막에 전체 통과를 남기는 일이다.
|
||||
이 절차는 두 가지를 막는다. 보존해야 할 realm과 데이터베이스를 검증 도중에 지우는 일과, 앞 단계가 어긋났는데도 나머지를 계속 돌려 마지막에 전체 통과를 남기는 일이다.
|
||||
|
||||
## 규칙
|
||||
|
||||
### 1. 대상이 일회용 환경인지 확정한 뒤에 시작한다
|
||||
|
||||
보존해야 할 Keycloak realm과 사용자, PostgreSQL 데이터가 같은 Compose 프로젝트에 있으면 안 된다. 볼륨의 소유와 용도를 확정하지 못했다면 검증을 미룬다.
|
||||
보존해야 할 Keycloak realm과 사용자, PostgreSQL 데이터가 같은 Compose 프로젝트에 있으면 안 된다. 볼륨의 소유와 용도를 확정하지 못했다면 검증을 미룬다. 지금 쓰는 볼륨이 계속 필요하다면 별도 프로젝트로 복제하거나, 백업이나 스냅숏을 만들어 둔 뒤에 진행한다.
|
||||
|
||||
지금 쓰는 볼륨이 계속 필요하다면 별도 프로젝트로 복제하거나 백업이나 스냅숏을 만들어 둔 뒤에 진행한다.
|
||||
### 2. 비밀값은 환경변수로 주입하고 출력에 남기지 않는다
|
||||
|
||||
### 2. 비밀값은 환경으로 주입하고 출력에 남기지 않는다
|
||||
|
||||
secret과 테스트 사용자 비밀번호는 환경변수로 주입하고 출력 로그에 값을 찍지 않는다. 커맨드라인 인자나 브라우저 출력, 버전 관리되는 파일에 값이 들어갔다면 그때 검증을 멈춘다.
|
||||
secret과 테스트 사용자 비밀번호는 환경변수로 주입하고 출력 로그에 값을 찍지 않는다. 커맨드라인 인자나 브라우저 출력, 버전 관리되는 파일에 값이 들어갔다면 검증을 멈춘다.
|
||||
|
||||
### 3. 한 번에 한 패턴만 올린다
|
||||
|
||||
한 번에 한 패턴만 대상으로 고르고, 여러 패턴 스택을 같은 포트에 동시에 올리지 않는다. 포트가 겹치면 어느 스택이 응답한 것인지 구분되지 않아서 관측값이 어디에서 나온 것인지 알 수 없다.
|
||||
한 번에 한 패턴만 대상으로 고르고, 여러 패턴 스택을 같은 포트에 동시에 올리지 않는다. 검증은 고른 경계의 입력과 출력에 직접 연결되어야 하므로, 관측한 상태 코드와 쿠키가 어느 패턴에서 나온 값인지 분명해야 한다.
|
||||
|
||||
### 4. 정적 검사를 먼저 돌리고 실패하면 다음으로 가지 않는다
|
||||
|
||||
정적 realm 검증과 단위 테스트를 먼저 실행하고, 여기서 client 종류나 redirect URI, audience mapper, controller 계약이 어긋나면 브라우저 E2E로 진행하지 않는다.
|
||||
정적 realm 검증과 단위 테스트를 먼저 실행하고, 여기서 클라이언트 종류나 redirect URI, audience mapper, 컨트롤러 계약이 어긋나면 브라우저 E2E로 진행하지 않는다.
|
||||
|
||||
두 검사가 통과하면 일회용 볼륨이 맞는지 다시 확인한 뒤에 패턴 스택을 빌드한다. 빌드한 뒤에도 순서는 같아서, health check가 안정되지 않으면 로그인 테스트를 시작하지 않는다.
|
||||
두 검사가 통과하면 일회용 볼륨이 맞는지 다시 확인한 뒤에 패턴 스택을 빌드한다. 빌드한 뒤에는 health check가 안정될 때까지 로그인 테스트를 시작하지 않는다.
|
||||
|
||||
### 5. 부정 입력까지 관측한 뒤에 경계가 유지된다고 판단한다
|
||||
|
||||
브라우저 E2E에서는 엔드포인트별 상태 코드와 쿠키 속성, 브라우저가 실제로 보낸 네트워크 요청, 응답 payload의 키를 함께 확인한다. 리프레시 토큰이 브라우저에 노출된 채로도 화면은 열리고, 브라우저에 토큰이 없다고 알려 주는 응답의 숫자는 서버가 적어 넣은 값이라 네트워크와 저장소를 따로 봐야 확인된다.
|
||||
성공 기준을 「로그인이 성공한다」로 두면 네 패턴 모두에서 너무 넓다. 리프레시 토큰이 브라우저에 노출된 채로도 화면은 열리고, 위조한 identity 헤더가 통과하는 구성에서도 정상 사용자는 자기 이름을 그대로 본다. 그래서 브라우저 E2E에서는 엔드포인트별 상태 코드와 쿠키 속성, 브라우저가 실제로 보낸 네트워크 요청, 응답 payload의 키를 함께 확인한다. 브라우저에 토큰이 없다고 알려 주는 응답 값도 서버가 적어 넣은 숫자라, 네트워크와 저장소를 따로 봐야 확인된다.
|
||||
|
||||
그다음에 패턴마다 다른 부정 입력을 넣는다. 위조 헤더를 보냈을 때 프록시가 값을 덮어쓰는지, 잘못된 issuer와 audience를 가진 토큰이 거부되는지, CSRF(Cross-Site Request Forgery, 교차 사이트 요청 위조) 헤더가 없는 요청이 막히는지를 각각 관측하고,
|
||||
그다음에 패턴마다 다른 부정 입력을 넣는다. 위조 헤더를 보냈을 때 프록시가 값을 덮어쓰는지, 잘못된 issuer와 audience를 가진 토큰이 거부되는지, CSRF(Cross-Site Request Forgery, 교차 사이트 요청 위조) 헤더가 없는 요청이 막히는지를 각각 관측한다.
|
||||
|
||||
위조 헤더를 넣은 요청이 200으로 돌아오는 것은 로그인 세션 자체가 유효하기 때문이다. 여기서 볼 값은 상태 코드가 아니라 응답에 남은 사용자 이름이고, 그 이름이 위조한 값이 아니라 원래 사용자면 덮어쓰기가 작동한 것이다.
|
||||
위조 헤더를 넣어도 로그인 세션 자체는 유효하기 때문에 요청은 200으로 돌아온다. 판정은 응답에 남은 사용자 이름으로 한다. 그 이름이 위조한 값이 아니라 원래 사용자면 프록시가 헤더를 덮어쓴 것이다.
|
||||
|
||||
여기 넣는 부정 입력에 서명이 깨진 토큰과 만료된 토큰은 들어 있지 않다. 단위 테스트에서 합성 JWT를 주입해 컨트롤러가 200을 주는 것을 본 것도 실제 서명 검증과 issuer 검증을 통과했다는 증거는 아니다.
|
||||
여기서 관측할 값과 넣을 부정 입력은 커밋된 자동 테스트가 확인하도록 정의한 계약에서 온 것이고, 최신 실행 성적표가 아니다. 그래서 여기 넣는 부정 입력에 서명이 깨진 토큰과 만료된 토큰은 들어 있지 않다. 단위 테스트에서 합성 JWT를 주입해 컨트롤러가 200을 주는 것을 확인했더라도, 실제 서명 검증과 issuer 검증을 통과했다는 증거는 아니다.
|
||||
|
||||
### 6. 중단 조건에 걸리면 멈추고 그 지점을 보존한다
|
||||
|
||||
@@ -73,11 +69,11 @@ secret과 테스트 사용자 비밀번호는 환경변수로 주입하고 출
|
||||
- secret이 커맨드라인이나 브라우저 출력, 버전 관리 파일에 노출됨
|
||||
- health check와 기대한 401·403, 헤더 덮어쓰기 중 하나라도 불일치
|
||||
|
||||
멈춘 뒤에 가장 먼저 하는 일은 실패한 홉의 실제 입력과 출력을 보존하는 것이다. 로그만 남기고 스택을 내리면 그 상태를 다시 만들 수 없다. 보존이 끝나면 설정과 네트워크, 애플리케이션 가운데 어느 경계가 깨졌는지 나눠서 진단한다.
|
||||
멈추면 실패한 홉의 실제 입력과 출력부터 보존한다. 검증 절차는 스택을 다시 세우기 전에 볼륨을 지우므로, 그대로 다시 돌리면 그 상태가 남지 않는다. 보존이 끝나면 설정과 네트워크, 애플리케이션 가운데 어느 경계가 깨졌는지 나눠서 진단한다.
|
||||
|
||||
### 7. 끝나면 원래 환경으로 되돌리고 다시 확인한다
|
||||
|
||||
검증이 끝나면 테스트용 스택을 내린다. 백업이 필요했던 환경이라면 원래 프로젝트와 볼륨을 복구한 뒤 health와 로그인이 되는지 다시 확인한다.
|
||||
검증이 끝나면 테스트용 스택을 내린다. 백업이 필요했던 환경이라면 원래 프로젝트와 볼륨을 복구한 뒤 health와 로그인을 다시 확인한다.
|
||||
|
||||
## 적용 조건
|
||||
|
||||
|
||||
Reference in New Issue
Block a user