# Baron SSO 전체 시스템 백업 및 복구 설계 ## 목적 Baron SSO의 전체 시스템 백업/복구는 CSV export/import의 확장판이 아니라, 서비스 저장소 전체를 일관된 시점으로 보존하고 복원하는 재해 복구 기능이다. 핵심 목표는 다음과 같다. - 사용자, 조직, 권한, RP, WORKS 연동 참조에 쓰이는 UUID를 그대로 보존한다. - Kratos identity subject와 Baron local user ID가 어긋나지 않게 복구한다. - Hydra/Keto/Oathkeeper 기반 인증/인가 상태를 서비스 가능한 수준으로 복원한다. - 복구 후 WORKS externalKey 기반 비교/동기화가 기존 연동과 이어지도록 한다. - 백업 산출물의 무결성, 보안, 복구 가능성을 검증 가능한 절차로 만든다. ## 배경과 결론 사용자 CSV는 `user_id`를 포함해 내보낼 수 있지만, 실제 사용자 계정의 주체 ID는 Kratos identity ID다. Kratos Admin API의 identity 생성 요청은 `id` 필드를 받지 않으므로, CSV import만으로 기존 사용자 UUID를 보장할 수 없다. 따라서 사용자 UUID 보존이 필요한 복구는 반드시 Kratos DB까지 포함한 full backup/restore로 처리해야 한다. CSV import는 운영 편의 기능으로 유지하되, 재해 복구나 WORKS 연동 보존 목적의 원장 복구 수단으로 간주하지 않는다. ## 백업 대상 ### 필수 저장소 | 대상 | 저장소 | 포함 이유 | 복구 필수 여부 | | --- | --- | --- | --- | | Baron 애플리케이션 DB | `baron_postgres` | users, tenants, user_login_ids, user_groups, api_keys, outbox, WORKS mapping, RP metadata 등 | 필수 | | Kratos DB | `ory_postgres`의 `ory_kratos` | identity UUID, credentials, verifiable/recovery addresses, sessions | 필수 | | Hydra DB | `ory_postgres`의 `ory_hydra` | OAuth2 clients, consent, token/session 관련 상태 | 필수 | | Keto DB | `ory_postgres`의 `ory_keto` | ReBAC relation tuple 원장 | 필수 | | Baron ClickHouse | `baron_clickhouse` | 감사 로그, 운영 추적 데이터 | 운영 정책상 필수 | | Ory ClickHouse | `ory_clickhouse` | Ory/Oathkeeper/Vector 계열 로그 | 운영 정책상 필수 | | 설정/비밀값 | `.env`, generated Ory config, WORKS private key, gateway/Oathkeeper config | 동일 환경 재기동과 외부 연동에 필요 | 필수 | ### 선택 저장소 | 대상 | 처리 원칙 | | --- | --- | | Redis | 로그인 pending state, cache, short code 등 휘발성 데이터다. full restore에서는 원칙적으로 제외하고 재시작 시 비운다. 무중단 이전 시나리오에서만 snapshot을 검토한다. | | 프론트 빌드 산출물 | 소스/이미지 태그로 재생성한다. 별도 보관은 배포 재현성을 위한 선택 항목이다. | | 로컬 개발 산출물 | reports, coverage, test-results 등은 백업 대상에서 제외한다. | ## 백업 산출물 형식 백업 단위는 압축된 디렉터리 또는 object storage prefix로 관리한다. ```text baron-sso-backup-YYYYMMDD-HHMMSSZ/ manifest.json checksums.sha256 postgres/ baron.dump ory_kratos.dump ory_hydra.dump ory_keto.dump globals.sql clickhouse/ baron_clickhouse/ ory_clickhouse/ config/ env.redacted env.encrypted ory/ gateway/ reports/ row-counts.json restore-readiness.json ``` `manifest.json`에는 최소한 다음 정보를 기록한다. - backup format version - 생성 시각, git commit, 이미지 태그 - 서비스별 DB schema/migration version - 각 dump 파일의 checksum, 크기, 생성 명령 버전 - 백업 모드: `offline`, `maintenance`, `online-best-effort` - 암호화 방식과 key id - 복구 대상 환경 제한: `same-env-only`, `staging-rehearsal`, `cross-env` ## 백업 모드 ### 1. Offline backup 가장 안전한 모드다. 모든 writer를 중지한 뒤 dump한다. 순서: 1. gateway 또는 Oathkeeper에서 maintenance mode 활성화 2. backend, relay worker, vector 등 write producer 중지 3. Kratos/Hydra/Keto public/admin 요청 차단 또는 컨테이너 중지 4. Baron Postgres dump 5. Ory Postgres의 Kratos/Hydra/Keto DB dump 6. ClickHouse backup 7. 설정/비밀값 백업 8. checksum과 row count 생성 9. 서비스 재개 이 모드는 사용자 UUID, WORKS mapping, Keto relation, OAuth consent 상태의 일관성이 가장 좋다. ### 2. Maintenance backup 짧은 점검 모드에서 writer만 막고 read는 제한적으로 허용한다. 운영 기본 모드로 권장한다. 필수 조건: - 사용자 생성/삭제/수정 차단 - 테넌트/조직 변경 차단 - WORKS outbox relay 중지 - Keto outbox relay 중지 - OAuth client 변경 차단 ### 3. Online best-effort backup 무중단 스냅샷이다. 저장소가 여러 개라 cross-store 일관성을 보장할 수 없다. 감사 로그나 분석용 백업에는 가능하지만, 재해 복구용 원본으로는 사용하지 않는다. ## Postgres 백업 전략 Postgres는 논리 dump를 기본으로 한다. - `pg_dump -Fc` 형식 사용 - DB별 dump 파일 분리 - `pg_dumpall --globals-only`로 role/extension/권한 정보 별도 보관 - 백업 전후 row count와 핵심 UUID sample 기록 대상 DB: - Baron DB: `DB_NAME` - Kratos DB: `ory_kratos` - Hydra DB: `ory_hydra` - Keto DB: `ory_keto` 복구는 빈 DB에 `pg_restore --clean --if-exists`로 수행한다. 기존 운영 DB에 덮어쓰는 in-place restore는 금지한다. ## ClickHouse 백업 전략 ClickHouse는 감사 로그 성격이 강하므로 정책을 분리한다. - 재해 복구: ClickHouse native backup 또는 volume snapshot 사용 - 장기 보관: 파티션 단위 export 또는 object storage backup - 복구 검증: 날짜 파티션별 row count와 min/max timestamp 비교 ClickHouse 백업 실패가 인증 기능 복구를 막지는 않지만, 감사 로그 보존 정책상 별도 실패로 취급한다. ## Redis 처리 원칙 Redis는 기본적으로 백업하지 않는다. 복구 후 영향: - 로그인 pending flow 만료 - short code/link login flow 재시작 필요 - headless JWKS cache 재생성 - 세션 cache miss 발생 가능 Kratos/Hydra 자체 session/token 원장은 Postgres 쪽에 있으므로 Redis가 비어 있어도 서비스는 재수렴해야 한다. ## 설정과 비밀값 DB dump만으로는 복구가 불완전하다. 다음 항목은 암호화해서 함께 보관한다. - `.env` 또는 배포 환경 변수 - Ory generated config - Hydra system secret, cookie secret - Kratos courier/config secret - Keto config - Oathkeeper rules/config - WORKS Admin OAuth client private key - API gateway 설정 - object storage backup key id `env.redacted`는 검토용이고, 실제 복구에는 `env.encrypted`만 사용한다. ## 복구 절차 ### Full restore 기본 절차 1. 대상 환경을 새로 준비한다. 2. 모든 애플리케이션 서비스를 중지한다. 3. 기존 DB가 있으면 별도 보관 후 빈 DB를 만든다. 4. Postgres globals를 복구한다. 5. Baron DB를 복구한다. 6. Kratos/Hydra/Keto DB를 복구한다. 7. ClickHouse를 복구한다. 8. 설정/비밀값을 복호화해 배치한다. 9. migration은 자동 실행하지 않고 현재 dump의 schema version을 확인한다. 10. Ory Stack을 기동한다. 11. backend를 기동한다. 12. relay worker는 아직 켜지 않는다. 13. post-restore verification을 수행한다. 14. WORKS comparison dry-run을 수행한다. 15. 문제가 없을 때 relay worker와 외부 동기화를 재개한다. ### Post-restore verification 필수 검증: - Kratos identity 수와 Baron users 수 비교 - Baron `users.id`가 Kratos `identities.id`에 존재하는지 확인 - tenant parent tree 참조 무결성 확인 - `user_login_ids.user_id`, `user_login_ids.tenant_id` 참조 무결성 확인 - Keto relation subject/object가 복구된 사용자/테넌트를 참조하는지 확인 - Hydra client와 Baron RP metadata 참조 확인 - WORKS mapping의 BaronResourceID가 복구된 사용자/테넌트를 참조하는지 확인 - super admin 로그인 확인 - 일반 사용자 로그인 확인 - 대표 RP OIDC login/consent 확인 - WORKS comparison dry-run에서 externalKey 기준 대량 삭제/생성 후보가 없는지 확인 ## WORKS 연동 복구 정책 WORKS 자체 데이터는 Baron 백업으로 복구하지 않는다. Baron이 보존해야 하는 것은 WORKS와 연결되는 참조 키다. 필수 보존: - 사용자 UUID - 테넌트 UUID - WORKS resource mapping - WORKS outbox 처리 상태 - WORKS domain mapping/config 복구 직후 정책: - relay worker 자동 실행 금지 - comparison dry-run 먼저 실행 - externalKey 기준으로 Baron/WORKS가 매칭되는지 확인 - 대량 delete/upsert가 감지되면 동기화 중단 - 확인 후 필요한 사용자/조직만 재동기화 outbox는 복구 모드에 따라 처리한다. | 복구 모드 | outbox 정책 | | --- | --- | | 같은 운영 환경 재해 복구 | outbox 상태 보존, 단 relay 재개 전 dry-run 필수 | | staging rehearsal | outbox relay 비활성화, 외부 WORKS 호출 금지 | | cross-env migration | outbox는 보존하되 실행하지 않고 별도 remap 정책 필요 | ## CSV export/import의 위치 CSV는 다음 목적으로만 사용한다. - 운영자가 사용자/조직을 일괄 등록하거나 보정 - 일부 필드를 검토하기 위한 추출 - dry-run 입력 보조 자료 CSV는 다음 목적에 사용하지 않는다. - Kratos identity UUID 보존 복구 - 비밀번호/credential 복구 - OAuth consent/token/session 복구 - Keto relation 원장 복구 - WORKS mapping 원장 복구 ## 구현 계획 ### Phase 1: 백업/복구 스크립트와 문서화 Estimate Time: 3~5d - `scripts/backup/full-backup.sh` - `scripts/backup/full-restore.sh` - `scripts/backup/verify-backup.sh` - `scripts/backup/verify-restore.sh` - `manifest.json` 생성기 - checksum 생성 - row count report 생성 ### Phase 2: staging restore rehearsal Estimate Time: 3~5d - 백업 파일로 격리된 staging stack 복구 - Ory/Baron/Postgres/ClickHouse 복구 검증 - 로그인/OIDC/관리자 화면 smoke test - WORKS 외부 호출 차단 상태에서 comparison dry-run ### Phase 3: 운영 자동화 Estimate Time: 5~8d - 정기 백업 스케줄링 - 암호화 및 object storage 업로드 - retention 정책 - 실패 알림 - restore rehearsal 주기화 ### Phase 4: 관리 UI Estimate Time: 5~8d - backup 목록 조회 - backup 생성 요청 - restore readiness report 조회 - staging rehearsal 결과 조회 - 운영 restore는 UI에서 직접 실행하지 않고 승인 절차와 runbook으로 제한 ## 테스트 전략 ### 단위 테스트 - manifest 생성 검증 - checksum 검증 - row count report 비교 - restore readiness parser 검증 ### 통합 테스트 - fixture DB 생성 - full backup 실행 - 빈 DB로 restore - 핵심 테이블 row count 비교 - 사용자/테넌트 UUID 동일성 비교 - Kratos identity와 Baron user ID 일치 검증 ### E2E 테스트 - super admin 로그인 - 일반 사용자 로그인 - AdminFront 사용자 목록 조회 - UserFront 로그인 - 대표 RP OIDC 로그인 - WORKS comparison dry-run ### 실패 테스트 - 누락된 dump 파일 - checksum 불일치 - schema version 불일치 - 일부 DB만 복구된 상태 - Kratos identity는 있는데 Baron user가 없는 상태 - Baron user는 있는데 Kratos identity가 없는 상태 - WORKS mapping이 복구되지 않은 상태 ## 운영 정책 - 백업은 암호화하지 않은 상태로 저장하지 않는다. - 운영 restore는 빈 환경 또는 새 볼륨에만 수행한다. - restore 전 현재 운영 DB는 별도 snapshot으로 보존한다. - restore 후 WORKS relay는 수동 승인 전까지 비활성화한다. - 월 1회 이상 staging restore rehearsal을 수행한다. - schema migration 직전 수동 backup을 강제한다. ## 남은 결정 사항 - RPO/RTO 목표값 - 백업 저장 위치와 암호화 key 관리 방식 - ClickHouse 장기 보관 기간 - WORKS outbox replay 정책의 운영 기본값 - 운영 restore 승인자와 절차 - restore rehearsal 자동 실행 주기