봉투 암호화 KEK 회전 및 복구 절차
이 문서는 Directory Service의 사용자 식별정보와 감사 로그를 보호하는 AES-256-GCM 봉투 암호화 KEK의 교체 절차를 정의합니다. KEK 원문은 문서, 데이터베이스, 감사 로그, 관리자 화면에 기록하지 않습니다. 활성 키는 PORTAL_CONSOLE_ENVELOPE_MASTER_KEY, 이전 키의 제한된 임시 보관은 PORTAL_CONSOLE_ENVELOPE_LEGACY_MASTER_KEYS에서만 수행합니다.
| 단계 | 운영 작업 | 성공 기준 |
|---|---|---|
| 1 | 승인된 비밀값 관리 시스템에서 32바이트 Base64 신규 KEK를 생성하고 PORTAL_CONSOLE_ENVELOPE_MASTER_KEY에 등록합니다. | 관리자 보안 화면의 키 식별자가 변경되며 원문은 표시되지 않습니다. |
| 2 | 직전 KEK를 쉼표 구분 PORTAL_CONSOLE_ENVELOPE_LEGACY_MASTER_KEYS에 일시적으로만 등록합니다. | 기존 사용자·감사 로그를 읽고 로그인할 수 있습니다. |
| 4 | 승인된 변경 창에서 같은 스크립트를 --dry-run 없이 실행합니다. | userPlaintext, userPreviousKey, userStaleIndex, auditPlaintext, auditPreviousKey가 모두 0입니다. |
| 5 | 중앙 로그인, 사용자 검색, 최근 감사 로그 조회를 별도 운영 계정으로 점검합니다. | 인증·검색·감사 조회가 모두 성공합니다. |
| 6 | 검증 기록을 남긴 뒤 PORTAL_CONSOLE_ENVELOPE_LEGACY_MASTER_KEYS를 비우고 재배포합니다. | 보안 화면의 LEGACY KEYS가 0이며, 이전 키로 암호화된 레코드가 없습니다. |
PORTAL_CONSOLE_ENVELOPE_LEGACY_MASTER_KEYS가 설정된 동안에는 활성 KEK와 레거시 KEK 모두 복호화에만 허용됩니다. 새 사용자, 수정 사용자, 새 감사 로그, 새 블라인드 인덱스는 항상 활성 KEK로 생성됩니다.
장애 복구
재암호화 중 오류가 발생하거나 검증값이 0이 아닌 경우에는 레거시 키를 폐기하지 않습니다. 실행을 중단하고, 활성 KEK를 직전 KEK로 되돌린 뒤 이전 키를 레거시 목록에 유지한 상태에서 중앙 로그인과 감사 로그 조회를 우선 복구합니다. 데이터베이스 백업 복원보다 이 절차가 우선이며, 그 후 별도의 변경 창에서 원인을 분석하고 재시도합니다.
키 원문 분실 또는 노출 의심 상황에서는 보안 책임자의 사고 대응 절차를 시작하고, 영향을 받은 KEK를 새 KEK로 교체합니다. 이전 키가 없으면 해당 키로 보호한 암호문을 복호화할 수 없으므로, 레거시 키 제거 전의 검증은 필수입니다.
스크립트 사용 예시
# 관리형 원장: 영향 수만 점검
node scripts/encrypt-directory-user-identities.mjs --dry-run
# 관리형 클라우드 directory_dev: 비파괴 점검
# 승인된 변경 창에서 실제 재래핑스크립트는 directory_dev 이외의 관리형 클라우드 대상 실행을 거부하며, 사용자 원장의 Login ID·성명·이메일·직급과 감사 로그의 변경 전·후 스냅샷을 재래핑합니다. 출력에는 키 원문과 개인정보를 포함하지 않습니다.
관리형 클라우드 운영 환경 필수 확인
관리형 클라우드는 이전 배포의 보안 비밀값을 자동으로 상속하지 않습니다. 따라서 배포한 Directory Service가 이미 암호화된 사용자 원장을 읽으려면, 배포 서비스의 Environment에 PORTAL_CONSOLE_ENVELOPE_MASTER_KEY를 등록해야 합니다. 값은 기존 원장을 암호화한 키와 완전히 동일해야 하며, 새 값 생성·문자 수정·공백 추가를 해서는 안 됩니다.
키가 없거나 다르면 사용자 복호화가 실패합니다. 현재 관리자 개요는 부서와 활성 사용자를 함께 조회하므로, 이 실패가 부서 목록까지 비어 보이는 현상으로 이어질 수 있습니다. 이 경우 데이터가 삭제된 것이 아니며, 동일 KEK 설정 후 재배포하면 기존 원장을 다시 읽을 수 있습니다.
| 배포 환경변수 | 필요 시점 | 주의사항 |
|---|---|---|
DATABASE_URL | 항상 | 단일 운영 원장인 directory_dev를 가리킵니다. |
PORTAL_CONSOLE_ENVELOPE_MASTER_KEY | 사용자·감사 로그 암호화 사용 시 | 기존 원장을 암호화한 키와 동일해야 합니다. |
JWT_SECRET | 관리자 ID·비밀번호 로그인 사용 시 | 관리자 세션 서명용입니다. |
PORTAL_JWT_SECRET | 연결 포털 사용자 인증 사용 시 | 포털 사용자 토큰 검증용입니다. |
PORTAL_CONSOLE_ADMIN_BOOTSTRAP_TOKEN | 초기 등록·복구 사용 시 | 일반 목록 조회에는 필요하지 않습니다. |
PORTAL_CONSOLE_ADMIN_API_KEYS_JSON | 관리자 API Key 로그인 사용 시 | ID·비밀번호 로그인과 목록 조회에는 필요하지 않습니다. |
PORTAL_API_KEYS_JSON | 포털 서버 API 사용 시 | 포털 간 서버 인증에만 필요합니다. |
DATABASE_URL, VITE_*, OWNER_*는 개발·분석 또는 프런트엔드 보조 목적의 값이므로, 일반적인 배포 런타임에 복사하지 않습니다.