Add platform infrastructure configuration
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
# k3s Secret 암호화 복구 drill
|
||||
|
||||
이 문서는 승인된 k3s Secret hardening의 post recovery bundle을 실제 복구할 수 있는지
|
||||
검증하고, 파기 확인 뒤 운영 host에 비민감 evidence를 등록하는 수동 진입점이다. 운영
|
||||
server에서 restore를 실행하는 runbook이 아니며 서비스, datastore, backup 또는 Secret을
|
||||
자동으로 변경하지 않는다.
|
||||
|
||||
## 승인과 책임 경계
|
||||
|
||||
- 운영 장애 복구와 drill은 서로 다른 변경 승인으로 다룬다.
|
||||
- SQLite와 embedded etcd restore 명령은 이 저장소의 자동 실행 스크립트로 제공하지 않는다.
|
||||
- drill은 운영 host와 network, datastore, hostname이 격리된 일회용 VM/host에서 post bundle
|
||||
복사본으로만 한다.
|
||||
- recovery bundle에는 복구·복호화에 필요한 자료가 함께 있으므로 bundle 전체를 Secret으로
|
||||
취급한다. 경로, token/config 내용, payload, hash와 escrow 위치를 terminal 결과나 원장에
|
||||
기록하지 않는다.
|
||||
- result만 반출하고 일회용 환경과 bundle 복사본을 파기한 뒤 운영 host에서 evidence를
|
||||
등록한다.
|
||||
|
||||
## backend별 수동 복구 기준
|
||||
|
||||
SQLite 장애 복구 순서는 k3s 중지, 현재 DB의 timestamp quarantine 이동, 같은 server
|
||||
token·config와 검증된 backup DB 복원, k3s 시작이다. 현재 DB를 즉시 삭제하거나 backup으로
|
||||
덮어쓰지 않는다. 모든 단계는 별도 승인된 장애 runbook에서 사람이 대상과 rollback 지점을
|
||||
확인한다.
|
||||
|
||||
embedded etcd는 현재 K3s 공식
|
||||
[`--cluster-reset-restore-path` snapshot 복구 절차](https://docs.k3s.io/cli/etcd-snapshot#restoring-snapshots)를
|
||||
사용한다. 단일 server와 다중 server 절차, token/config 일치 조건, reset 후 정상 시작 조건을
|
||||
실행 시점의 공식 문서와 다시 대조한다. 보조 tutorial을 복구 권위로 사용하지 않는다.
|
||||
|
||||
## 일회용 환경의 격리 조건
|
||||
|
||||
복구 전에 다음 조건을 모두 만족시킨다.
|
||||
|
||||
- 운영 server와 다른 hostname, network와 datastore를 사용한다.
|
||||
- hypervisor private switch 또는 network namespace에 default route와 upstream DNS가 없다.
|
||||
- 원본 운영 API/datastore로 향하는 route가 없다.
|
||||
- host firewall egress가 default-deny다.
|
||||
- LAN, Internet, Slack, AIStor와 운영 API 연결 시험이 모두 실패한다.
|
||||
- 복구된 workload/controller가 격리망 밖으로 통신할 수 없고 외부 host port를 열 수 없다.
|
||||
- 운영과 같은 정확한 k3s version, server token과 config를 post bundle 복사본에서 사용한다.
|
||||
|
||||
복구 뒤에는 다음을 확인한다.
|
||||
|
||||
- k3s API ready
|
||||
- node Ready
|
||||
- encryption status가 `Enabled/reencrypt_finished`
|
||||
- server hash와 local integrity가 모두 일치
|
||||
- `kubectl get secrets --all-namespaces -o json` 조회가 오류 없이 완료
|
||||
- bundle metadata의 복구 전 전체 Secret object count와 복구 후 count가 일치
|
||||
- 위 격리 연결 시험을 다시 실행해 모두 실패
|
||||
|
||||
격리 조건과 live 검사가 모두 끝나기 전에는 result의 `isolation=pass`를 만들지 않는다.
|
||||
|
||||
## 세 mode 사용
|
||||
|
||||
모든 mode는 먼저 일반 사용자의 현재 kube context를 확정한다. 전체 script를 `sudo`로
|
||||
실행하지 않는다. root 권한은 운영 host의 권위 파일 stat/read/install에만 좁게 사용되므로
|
||||
필요하면 같은 terminal에서 사전에 sudo credential을 갱신한다.
|
||||
|
||||
격리 복구 host에서 post metadata와 결과 출력 위치를 직접 지정한다. 출력은 기존 파일을
|
||||
덮어쓰지 않는다.
|
||||
|
||||
```sh
|
||||
bash scripts/validate/k3s-secret-encryption-restore-evidence.sh \
|
||||
--emit-result --bundle-metadata BUNDLE_METADATA_FILE --output RESULT_FILE
|
||||
```
|
||||
|
||||
script는 live API ready, node Ready, `Enabled/reencrypt_finished`, server hash, local integrity,
|
||||
version/backend와 Secret object count를 직접 검사한다. 수동 격리 시험을 마친 현재 context를
|
||||
추가 확인한 뒤에만 result를 만든다. result에는 credential, 경로, 민감 filename이나 hash가
|
||||
없고 `destroyed`도 없다.
|
||||
|
||||
결과 파일을 운영 host로 반입한 뒤 일회용 환경과 bundle 복사본을 먼저 파기한다. 그 다음
|
||||
운영 host에서 등록한다.
|
||||
|
||||
```sh
|
||||
bash scripts/validate/k3s-secret-encryption-restore-evidence.sh \
|
||||
--record --bundle-metadata BUNDLE_METADATA_FILE --result-file RESULT_FILE
|
||||
```
|
||||
|
||||
`--record`는 post phase, metadata/result의 bundle-id·version·backend, 24시간 age와 운영
|
||||
host 권위 post metadata의 일곱 field 전체를 확인한다. evidence 대상이 이미 있으면 중단한다.
|
||||
prompt에는 정확히 `DESTROYED default`를 입력한다. 파기하지 않았거나 확인할 수 없으면
|
||||
등록하지 않는다.
|
||||
|
||||
Phase 4의 읽기 전용 gate는 다음과 같다.
|
||||
|
||||
```sh
|
||||
bash scripts/validate/k3s-secret-encryption-restore-evidence.sh --check
|
||||
```
|
||||
|
||||
`--check`는 exact evidence field, 현재 권위 bundle-id/version/backend, live
|
||||
`reencrypt_finished`와 local integrity, 30일 age, `destroyed=confirmed`를 모두 요구한다.
|
||||
2026-08-09 live 전환은 `Enabled/reencrypt_finished`, hash·integrity·API·node 검사,
|
||||
post bundle 기록과 최신 marker 검증까지 통과했다. 그러나 격리 restore·파기 evidence가
|
||||
아직 없고 lifecycle 자동화, off-host 복제와 암호화 escrow 검증도 미완료다. 따라서 실제
|
||||
운영 `--check`는 아직 성공으로 기록하지 않으며, 이 gate들이 완료되기 전에는 관측성
|
||||
Phase 4를 열지 않는다.
|
||||
|
||||
## 입력 파일 보안
|
||||
|
||||
외부 metadata/result는 현재 사용자 소유 regular non-symlink, mode `0600`, non-empty여야
|
||||
한다. parser는 exact allowlist `KEY=VALUE` 한 줄만 받아들이며 duplicate/unknown/empty key,
|
||||
control character, malformed line, trailing data, `$(`와 backtick을 거부한다. 파일을 shell로
|
||||
source하거나 `eval`하지 않는다. 입력 실패는 어떤 privileged install도 수행하기 전에
|
||||
종료한다.
|
||||
|
||||
result와 evidence는 같은 directory의 mode `0600` temporary file을 완성하고 exact field를
|
||||
다시 검사한 뒤 기존 target을 덮어쓰지 않는 atomic install로 만든다.
|
||||
|
||||
## 실행 원장
|
||||
|
||||
완료된 live hardening의 비민감 정정은
|
||||
[2026-08-08 복구 명령 원장](/home/donghyeon/workspace/docs/platform/runbooks/2026-08-08-k3s-local-recovery-command-log.md)의
|
||||
2026-08-09 addendum과
|
||||
[2026-08-09 로컬 정책 기록](/home/donghyeon/workspace/docs/platform/runbooks/2026-08-09-k3s-secret-encryption-local-policy.md)에
|
||||
있다. 아래 표는 아직 수행하지 않은 격리 restore drill의 실행 원장 형식이며, 완료된
|
||||
live hardening에 별도 Task 6 실행 runbook은 만들지 않았고, 이를 암시하지 않는다.
|
||||
|
||||
| 시각 | 사전 상태 | backend | backup 검증 | 명령 | 종료 코드 | 후속 상태 |
|
||||
|---|---|---|---|---|---:|---|
|
||||
|
||||
backup 위치, token/hash payload, 민감 파일 hash, encryption config 내용과 escrow 위치는
|
||||
`검증 완료` 또는 `미완료`로만 쓴다. bundle-id, restore drill 시각과 pass/fail은 비밀값이
|
||||
아니므로 기록할 수 있다.
|
||||
Reference in New Issue
Block a user