보안과 현재 격차¶
이 페이지는 기준 커밋에서 확인되는 통제를 구현됨과 미구현/현재 격차로 구분합니다. 설정 파일에 “운영에서 주입”이라고 적혀 있는 것과 실제 배포 템플릿이 값을 주입하는 것은 같지 않습니다.
구현됨¶
- 비밀번호는 신규 저장 시 Argon2id를 사용하고 레거시 bcrypt 검증을 지원합니다.
- 로그인 JWT subject에는 이메일 대신 회원 UUID를 넣습니다.
- refresh token과 API key는 원문 대신 SHA-256 해시를 저장합니다.
- refresh token은 재발급 때 기존 토큰을 폐기하고 회전합니다.
- PII 컬럼은 AES-GCM 암호화와 별도 HMAC blind index 패턴을 사용합니다.
- client-secret은 로그인 HMAC 키와 분리된 Ed25519 키로 서명합니다.
- 워크스페이스 API key는 발급 응답에서만 원문을 노출합니다.
- 운영 프로파일은 Swagger/OpenAPI를 비활성화하고 Actuator 상세를 숨깁니다.
- 배포 프로파일은 Actuator를 9090으로 분리하고 Service/NEG에는 8080만 노출합니다.
- DB 무결성 오류 응답에는 SQL, 제약명, 컬럼값, 드라이버 원문을 노출하지 않습니다.
- 음성 프록시는 테넌트 검증, 접근 감사,
private, no-store응답을 사용합니다.
미구현/현재 배포 격차¶
1. 운영 JWT·PII 시크릿 배선이 완결되지 않음¶
애플리케이션은 JWT_SECRET, ENCRYPTION_SECRET, BLINDINDEX_SECRET이 없으면 개발용
기본값으로 시작할 수 있습니다. 그러나 GKE에서 externalSecret.enabled=true인 현재 Helm
경로는 ExternalSecret에 DB 비밀번호와 client-secret 서명키만 매핑하고, 위 세 환경변수는
매핑하지 않습니다. 직접 K8s Secret을 쓰는 분기는 존재하지만 ESO 분기에서는 실행되지 않습니다.
영향: 별도 클러스터 수준 주입이 없다면 운영에서도 JWT 서명, PII 암호화, blind index가 저장소의 fallback 값에 의존할 수 있습니다. 이는 운영 키 분리·회전·비밀성 보장을 깨뜨립니다.
필요 조치: 세 값을 Secret Manager → ESO → K8s Secret → 파드 환경변수로 명시 배선하고, 운영 프로파일에서는 fallback으로 기동하지 못하도록 fail-fast 검증을 추가해야 합니다. 비밀의 실제 값은 문서·Git·로그에 기록하지 않습니다.
2. 더미·기본 시나리오 permitAll 범위¶
/v1/dummy-scenarios/**와 /v1/base-scenarios/**는 wildcard permitAll입니다.
현재 더미 시나리오에는 조회뿐 아니라 POST, PUT, DELETE와 원격 검증 호출이 있어 무인증 사용자가
데이터를 변경하거나 Graph Builder 호출을 유발할 수 있습니다. 기본 시나리오는 현재 GET만
있지만 wildcard는 미래에 추가되는 mutation도 자동 공개할 위험이 있습니다.
필요 조치: 공개가 필요한 GET만 메서드 단위로 열고, 더미 mutation과 검증은 관리자 인증, 내부망 또는 제거 정책 중 하나로 닫아야 합니다.
3. Actuator 무인증이 네트워크 격리에 의존¶
/actuator/**는 애플리케이션 보안 설정에서 permitAll입니다. 배포에서는 9090 관리 포트를
Service/NEG에 넣지 않는 네트워크 격리로 보호합니다. 즉 애플리케이션 자체 인증은 없으며,
클러스터 내부에서 9090에 도달할 수 있는 주체는 엔드포인트를 읽을 수 있습니다.
필요 조치: 9090 비노출 회귀 테스트와 네트워크 정책을 유지하고, 내부 위협 모델상 필요하면 관리 포트 인증 또는 mTLS를 추가해야 합니다. 9090을 Service·Ingress·NEG에 추가해서는 안 됩니다.
추가 구현상 주의¶
- client-secret은 무상태이며 일회용이 아닙니다. 탈취되면 만료까지 재사용될 수 있습니다.
- JWT 대화 목록·상세는 헤더가 없을 때 테넌트 컨텍스트 없이 진행될 수 있지만 음성 프록시는 헤더를 강제합니다. 테넌시 문서의 실제 범위를 따르세요.
- 요청 로깅 필터는 현재 요청 헤더 전체를 수집합니다. 운영 로그에서
Authorization, cookie, API key 같은 credential을 마스킹하는지 배포 전 별도 검증이 필요합니다. - access JWT의 즉시 폐기 목록은 없습니다. 회원 탈퇴가 refresh를 폐기해도 기존 access token은 만료 전까지 암호학적으로 유효합니다.