1
0
forked from baron/baron-sso
Files
baron-sso/docs/personnel-dataset-backup-staging-restore-design-2026-06-22.md

12 KiB

Production Personnel Dataset Backup and Staging Restore Design

Estimate Time

Estimate Time: 2.5d

목적

프로덕션의 "인력정보" 관련 데이터만 주기적으로 백업하고, 스테이징에 복구해 운영 데이터에 가까운 검증 환경을 구축한다. 이 기능은 재해 복구용 full backup이 아니라 staging rehearsal용 논리 데이터셋 이관 기능이다.

기존 make dump/make restore는 저장소 단위 full backup을 목표로 한다. 이번 기능은 Hydra와 RP 정보를 제외해야 하므로 저장소 단위 필터인 DUMP_SERVICES=postgres,ory-postgres만으로는 충분하지 않다. 별도의 dataset profile을 두어 테이블/행/민감값을 명시적으로 제한해야 한다.

정책 전제

  • Ory Stack은 identity, authorization, OAuth/OIDC 상태의 SoT다.
  • Backend DB의 users는 Ory에 저장되지 않거나 Ory API만으로 조회하기 어려운 Baron 운영 read model이다.
  • Hydra client, consent, token/session state와 Baron RP metadata는 이번 데이터셋 대상이 아니다.
  • staging restore는 운영 복구가 아니므로 production credential/session을 그대로 들고 오지 않는다.
  • Wiki는 사용 중이지만, 정책 업데이트 초안은 docs/ 문서로 남기고 사람이 검토 후 Wiki에 반영한다.

제안 인터페이스

기존 백업 명령을 유지하면서 dataset profile을 추가한다.

make dump DUMP_SERVICES=postgres,ory-postgres DUMP_DATASET=personnel DUMP_MODE=maintenance
make restore RESTORE_SERVICES=postgres,ory-postgres RESTORE_DATASET=personnel CONFIRM_RESTORE=baron-sso
make restore-plan RESTORE_DATASET=personnel BACKUP=backups/baron-sso-backup-YYYYMMDD-HHMMSSZ

운영 자동화에서는 production에서 full backup만 만들고, staging에서 받은 full backup을 personnel dataset으로 필터링한 뒤 복구한다.

# Production
make dump DUMP_SERVICES=all DUMP_MODE=maintenance

# Staging
make filter-personnel-dump \
  BACKUP=backups/prod-full-backup-YYYYMMDD-HHMMSSZ \
  OUTPUT_BACKUP=backups/prod-personnel-filtered-YYYYMMDD-HHMMSSZ

make restore \
  BACKUP=backups/prod-personnel-filtered-YYYYMMDD-HHMMSSZ \
  RESTORE_DATASET=personnel \
  RESTORE_SERVICES=postgres \
  CONFIRM_RESTORE=baron-sso

filter-personnel-dump는 full backup의 baron.dump, ory_kratos.dump, ory_keto.dump를 staging scratch DB에 일시 복원한 뒤 personnel JSONL dataset을 생성한다. Hydra dump와 RP metadata는 filtered backup에 복사하지 않는다.

추가 환경 변수:

변수 기본값 의미
DUMP_DATASET full full은 기존 동작, personnel은 인력정보 논리 데이터셋
RESTORE_DATASET manifest 기준 복구할 dataset profile
FILTER_SERVICES postgres,ory-postgres full backup에서 personnel dataset으로 필터링할 서비스 범위
OUTPUT_BACKUP empty filter-personnel-dump의 personnel dataset 출력 경로
PERSONNEL_TENANT_ROOT_SLUGS empty 비어 있으면 전체 인력정보, 값이 있으면 지정 tenant root 하위만
PERSONNEL_INCLUDE_KRATOS_IDENTITIES true staging 로그인/subject 일치 검증이 필요할 때 Kratos identity subset 포함
PERSONNEL_RESET_CREDENTIALS true Kratos credential/session을 production 그대로 복구하지 않도록 강제
PERSONNEL_INCLUDE_WORKSMOBILE_MAPPING true WORKS externalKey 비교와 조직도 검증용 mapping 포함
PERSONNEL_INCLUDE_OUTBOX false queue state는 기본 제외, 장애 재현 시에만 별도 허용

DUMP_DATASET=personnelDUMP_SERVICES=all에서도 Hydra DB와 RP metadata를 포함하지 않도록 내부적으로 차단한다. 사용자가 DUMP_DATASET=personnel DUMP_SERVICES=ory-postgres를 지정해도 ory_hydra dump는 생성하지 않는다.

백업 산출물 구조

baron-sso-backup-YYYYMMDD-HHMMSSZ/
  manifest.json
  checksums.sha256
  datasets/
    personnel/
      dataset-manifest.json
      postgres/
        users.jsonl
        user_login_ids.jsonl
        tenants.jsonl
        tenant_domains.jsonl
        user_groups.jsonl
        worksmobile_resource_mappings.jsonl
      ory_kratos/
        identities.jsonl
        identity_credentials.reset-plan.jsonl
      ory_keto/
        relation_tuples.jsonl
      reports/
        row-counts.json
        exclusions.json
        restore-plan.md

personnel dataset은 pg_dump -Fc만으로 만들지 않는다. 행 필터, 민감값 제거, RP/Hydra 제외를 안전하게 보장하려면 COPY (SELECT ...) TO STDOUT 또는 psql JSONL export를 사용한다. full backup은 기존 postgres/baron.dump, postgres/ory_*.dump 형식을 그대로 유지한다.

포함 범위

Baron Postgres 포함

테이블/데이터 포함 이유 처리
users 인력 기본 정보, 상태, 조직 표시 read model 포함. relying_party_id는 null 처리 또는 제외 검증
user_login_ids 사번/로그인 ID 등 인력 식별자 포함
tenants 회사/조직/사용자 그룹 계층 COMPANY_GROUP, COMPANY, ORGANIZATION, USER_GROUP 중심 포함
tenant_domains 회사 도메인 기반 소속 판단 포함
user_groups 조직도/부서 계층 포함
worksmobile_resource_mappings WORKS externalKey 기반 비교/동기화 기준 USER, ORGUNIT만 포함

Ory Kratos 포함

PERSONNEL_INCLUDE_KRATOS_IDENTITIES=true일 때만 포함한다.

  • identities: subject UUID와 traits 기반 식별을 위해 포함한다.
  • credential/session/recovery/verifiable address는 production 값을 그대로 복구하지 않는다.
  • restore 단계에서 staging용 임시 credential 정책 또는 password reset-required 상태를 만든다.
  • Kratos DB 직접 조작은 일반 write path가 아니므로 maintenance guard와 별도 확인값을 요구한다.

Ory Keto 포함

  • 사용자, tenant, user group membership/ownership 관계 tuple만 포함한다.
  • RP namespace 또는 RP object를 참조하는 tuple은 제외한다.
  • restore 후 Keto relation tuple subject/object가 복구된 user/tenant/group만 참조하는지 검증한다.

제외 범위

제외 대상 이유
Hydra DB 전체 OAuth2 client, consent, token/session은 staging RP 상태를 오염시킬 수 있음
Baron RP metadata 사용자가 명시한 비대상이며 staging RP 설정은 별도 관리 대상
rp_user_metadata RP별 custom claim 데이터라 personnel 공통 데이터가 아님
client_consents Hydra/RP consent read model 성격
API key/client secret류 staging secret과 충돌 위험
audit/clickhouse logs 인력정보 환경 구축의 필수 원장이 아님
worksmobile_outbox 큐 처리 상태라 반복 restore 시 중복 작업 위험
Redis 휘발성 cache/session

Restore 전략

staging restore는 DB 전체 drop/restore가 아니라 scoped replace 방식으로 설계한다.

  1. restore 전 restore-plan을 생성해 포함/제외 테이블, row count, tenant scope, Hydra/RP exclusion을 표시한다.
  2. backend worker, WORKS relay, Keto outbox relay를 중지한다.
  3. dataset을 staging scratch schema 또는 임시 DB에 적재한다.
  4. row count, foreign key, soft-delete, tenant hierarchy, user-login collision을 검증한다.
  5. staging의 Hydra/RP 관련 테이블과 설정은 건드리지 않는다.
  6. Baron personnel tables를 dependency order에 따라 replace/upsert한다.
  7. Kratos identity subset을 포함한 경우 production credential/session을 제거하고 staging credential policy를 적용한다.
  8. Keto personnel tuple만 replace/upsert하고 RP tuple은 보존한다.
  9. restore-verify에서 다음 항목을 검증한다.

검증 항목:

  • users.id와 Kratos identities.id 일치 여부
  • user_login_ids.user_id, tenant_id 참조 무결성
  • tenants.parent_id, user_groups.parent_id 계층 무결성
  • users.relying_party_id가 남아 있지 않은지
  • rp_user_metadata, Hydra dump 파일, Hydra restore step이 생성되지 않았는지
  • Keto tuple이 복구 대상 user/tenant/group만 참조하는지
  • WORKS mapping의 Baron resource 참조가 존재하는지

구현 위치

제안 파일:

  • scripts/backup/lib/dataset.sh: dataset profile validation과 공통 manifest helper
  • scripts/backup/lib/personnel_dataset.sh: personnel export/import SQL, exclusion guard
  • scripts/backup/dump.sh: DUMP_DATASET 분기 추가
  • scripts/backup/restore.sh: RESTORE_DATASET 분기와 scoped restore 추가
  • scripts/backup/restore-plan.sh: dataset restore plan 출력
  • scripts/backup/lib/report.sh: dataset row-count/exclusion report 표시
  • Makefile: DUMP_DATASET, RESTORE_DATASET, PERSONNEL_* 변수 전달

테스트 계획

구현 전 RED 테스트를 먼저 추가한다.

  1. test/personnel_dataset_backup_policy_test.sh

    • DUMP_DATASET=personnel dry-run 또는 fixture run에서 Hydra dump가 계획되지 않는지 확인한다.
    • rp_user_metadata, client_consents, relying_parties 계열 데이터가 dataset manifest에 포함되지 않는지 확인한다.
    • unknown dataset profile을 거부하는지 확인한다.
  2. test/personnel_dataset_restore_policy_test.sh

    • RESTORE_DATASET=personnelCONFIRM_RESTORE=baron-sso 없이 실패하는지 확인한다.
    • restore-plan에 포함/제외 테이블과 credential reset policy가 표시되는지 확인한다.
    • non-empty target guard와 scoped restore guard가 동시에 동작하는지 확인한다.
  3. scripts/backup/lib/personnel_dataset.sh 단위 shell test

    • tenant root scope가 있을 때 users/tenants/user_groups 쿼리가 같은 scope로 제한되는지 확인한다.
    • PERSONNEL_INCLUDE_OUTBOX=false 기본값에서 outbox가 제외되는지 확인한다.
  4. 통합 테스트

    • fixture Postgres에 users/tenants/RP/Hydra 유사 데이터를 넣는다.
    • personnel dataset dump를 실행한다.
    • 빈 staging fixture DB에 restore한다.
    • 인력정보는 들어오고 Hydra/RP/consent/custom claim 데이터는 남지 않는지 검증한다.
  5. E2E 또는 smoke

    • staging restore 후 AdminFront/User list와 OrgFront 조직도 조회가 정상인지 확인한다.
    • 화면 변화가 있는 기능은 아니므로 스냅샷 업로드는 구현 범위에서 제외한다. 단, 복구 후 조직도 화면 검증이 필요하면 별도 E2E 이슈로 분리한다.

위험과 결정 필요 사항

  1. Kratos identity 포함 여부

    • 포함하면 staging에서 production과 같은 subject UUID로 검증할 수 있다.
    • 대신 credential/session 민감값 제거가 필수이고, Kratos DB maintenance 예외 정책을 문서화해야 한다.
    • 제외하면 인력/조직 화면은 검증 가능하지만 실제 로그인 subject 일치 검증은 제한된다.
  2. restore 방식

    • table replace는 단순하지만 staging 고유 사용자와 충돌할 수 있다.
    • upsert는 staging 고유 데이터 보존에 유리하지만 삭제/퇴사 반영 정책이 복잡해진다.
    • 기본안은 PERSONNEL_RESTORE_MODE=replace-scoped로 두고, staging 고유 tenant slug allowlist는 보호한다.
  3. WORKS mapping 포함 여부

    • externalKey 비교를 위해 포함하는 것이 좋다.
    • outbox는 중복 실행 위험이 있어 기본 제외가 맞다.

구현 순서

  1. Gitea 이슈에 본 설계와 테스트 RED 계획을 등록한다.
  2. RED 테스트를 먼저 추가하고 실패를 확인한다.
  3. dataset profile validation과 manifest/exclusion guard를 구현한다.
  4. Baron Postgres personnel export/import를 구현한다.
  5. Kratos/Keto subset 처리는 guard와 reset policy를 먼저 구현한 뒤 활성화한다.
  6. make restore-plan, report, verification을 보강한다.
  7. 테스트 통과 후 문서와 Wiki 반영 필요 여부를 검토한다.