본문으로 건너뛰기

Ops Master Admin 비상 복구 runbook

ops 콘솔 (apps/ops) 은 구글 OAuth 단독 인증 (2026-04-29 폐기 이전 이메일/패스워드, ADR 0030 follow-up). 구글 계정 잠금·접근 불가 상황에서 ops 진입 회복하는 절차.

1. 정책 요약

  • 인증: 구글 OAuth 단일 (signInWithPopup + GoogleAuthProvider)
  • 권한 게이트: 구글 인증 후 masterAdmins/{email} Firestore 화이트리스트 매칭 — 화이트리스트 외 계정은 로그인 후에도 AuthProvider 가 진입 차단
  • 이메일/패스워드 인증: ops 측 폐기됨 (2026-04-29). web 측 사용자(변호사) 용 Firebase Auth email/password provider 는 별개

2. 비상 시나리오

2.1 구글 계정 잠금 (사용자 본인)

증상: ops 로그인 페이지에서 "Google 로 계속" 클릭했으나 구글 OAuth 가 잠금/MFA 실패 등으로 진입 불가.

Step 1 — 구글 계정 자체 복구

먼저 https://accounts.google.com/signin/recovery 에서 계정 복구. 구글 자체 잠금은 ops 측 우회 불가.

Step 2 — 구글 복구 불가 시: 임시 새 admin 추가

다른 구글 계정 (예: 본인 보조 이메일 또는 Chair 의 구글 이메일) 을 임시 master admin 으로 추가:

NODE_PATH=apps/web/node_modules npx tsx -e "
const { db } = require('./scripts/lib/admin');
db.collection('masterAdmins').doc('your-backup@gmail.com').set({
email: 'your-backup@gmail.com',
role: 'super_admin',
createdAt: new Date().toISOString(),
reason: '비상 복구',
}).then(() => console.log('done'));
"

Step 3 — 주 계정 복구 후 임시 admin 제거

NODE_PATH=apps/web/node_modules npx tsx -e "
const { db } = require('./scripts/lib/admin');
db.collection('masterAdmins').doc('your-backup@gmail.com').delete().then(() => console.log('done'));
"

2.2 service account 키도 분실

증상: Step 2 의 service account 자체가 없음 (Firestore 직접 접근 불가).

  • 현 정책상 발생 불가 — scripts/lib/admin.ts 의 인증 우선순위:
    1. FIREBASE_SERVICE_ACCOUNT env (CI 자동화)
    2. service-account-key.json (프로젝트 루트)
    3. ADC (gcloud auth application-default login)
  • 셋 다 실패 시: GCP Console → IAM → Service Accounts 에서 새 service account 생성 + Firestore Admin role 부여 → 키 발급 후 재실행
  • GCP Console 자체 접근 불가: GCP organization owner 가 직접 GCP Console 에서 masterAdmins/{your-email} 문서 추가

2.3 ops 자체가 깨져있는 상황

증상: ops UI 가 빈 화면·build 실패·Firebase 미초기화 등.

  • ADR 0029 fail-loud 정책에 따라 apps/ops/__tests__/firebase-init.test.ts 가 NEXT_PUBLIC_FIREBASE_* 환경변수 회귀 검증
  • pnpm --filter=@neohollo/ops build 로컬 검증
  • ADR 0030 T4 production smoke 가 매일 06:00 KST 5 화면 검증 (web 만, ops 는 후속)
  • 그래도 깨진 경우 service account 로 firestore 직접 read/write — ops UI 우회

3. 신규 Master Admin 추가 (정상 절차)

3.1 신규 admin 의 구글 이메일 화이트리스트 등록

기존 master admin 이 ops 콘솔 에서 추가하거나, scripts 로:

NODE_PATH=apps/web/node_modules npx tsx -e "
const { db } = require('./scripts/lib/admin');
db.collection('masterAdmins').doc('new-admin@gmail.com').set({
email: 'new-admin@gmail.com',
role: 'admin',
createdAt: new Date().toISOString(),
}).then(() => console.log('done'));
"

role 옵션: super_admin · admin · viewer.

3.2 신규 admin 이 구글 계정 보유 + 2FA 설정 권장

  • Google Workspace 또는 일반 gmail 모두 OK
  • 2FA 강제 권장 — Master Admin 권한 수준 (cross-tenant mutation) 에 부합
  • 가능하면 hardware security key (YubiKey 등) 등록

4. 정책 근거

  • ADR 0029: Firebase 초기화 fail-loud — silent skip 패턴 차단
  • ADR 0030: P0 클러스터 회고 — "성공한 척 + 다른 layer 에서 깨짐" 패턴 차단
  • ops 구글 단독화 (2026-04-29 follow-up): phishing 사고 시 cross-tenant 데이터 노출 위험 차단. 패스워드 reset/forgot 흐름 폐기로 운영 단순. Google 2FA + hardware key 가 최소 안전선

5. 모니터링·감사

  • ops 진입 시 touchLastLoginAction()masterAdmins/{email}.lastLoginAt 업데이트 — 의심스러운 로그인 시점 audit
  • 신규 admin 추가는 audit 컬렉션 보존 권장 (정통망법 §50 ⑥ 정합)

6. 후속 검토 항목

  • ops 도 web 처럼 production smoke (5 화면) 추가 — ADR 0030 T4 phase 1 외 ops 용
  • masterAdmins 추가/삭제 audit 로그 컬렉션 (현재는 lastLoginAt 만)
  • HSM/2FA 강제 정책 자동 검증 (Google Workspace 단계 — 단일 사용자 시 의미 적음)

관련 문서