Files
project-gitops/docs/architecture/secret-trust.md
T

128 lines
5.6 KiB
Markdown

# Secret trust boundaries
## Dev Vault
`dev-k3s`는 workload 클러스터 안의 단일 self-hosted Vault를 사용합니다.
별도 Transit Vault는 두지 않습니다. Vault는 다음 API 객체를 제공합니다.
- KV-v2 runtime secret path
- Kubernetes auth와 workload role
- Dynamic PostgreSQL credential
- 애플리케이션 JWT signing용 Transit key
Dev Vault는 Shamir 1-of-1로 한 번 초기화하고 재시작 때 명시적으로
unseal합니다. 이는 폐기 가능한 개발 환경 전용입니다. Production에서는
managed Vault 또는 독립 failure domain의 HA integrated-Raft와 KMS/HSM
auto-unseal이 필요합니다.
## Three Terraform states
```text
vault-foundation
-> mounts/auth configuration
-> delegated automation policies
-> optional, separated CI JWT login roles
vault-workloads
-> workload policies and Kubernetes auth roles
-> project-auth-jwt Transit key
vault-database
-> auth-system PostgreSQL connection
-> auth-db-migration-dev dynamic role
```
`vault-foundation`은 routine runner가 아니라 bootstrap 또는 승인된 보안
관리자가 실행합니다. 이 state가 workloads/database automation policy를
만들고, OIDC/JWT trust가 설정됐을 때만 두 login role을 분리해 만듭니다.
Workloads/database exact claim map은 최소 한 공통 discriminator key에서
다른 값을 가져야 합니다. 실제 issuer가 그 repository/ref/job claim을
신뢰할 수 있게 발행하는지 확인하지 못하면 CI JWT auth를 활성화하지
않습니다. Delegated state는 자신에게 권한을 추가할 수 없고 맡은 정확한
Vault API path만 변경합니다.
Exact API path 허용이 runner를 완전한 sandbox로 만들지는 않습니다.
`vault-workloads` runner가 허용된 ACL policy 내용이나 Kubernetes auth role
payload를 악의적으로 바꾸면 더 강한 policy를 연결하는 권한 상승이
가능합니다. 따라서 이 runner는 신뢰된 security automation으로 취급하고,
protected branch, policy lint, saved-plan 승인과 Vault audit log를 함께
trust boundary로 사용합니다.
세 state는 `terraform_remote_state`로 연결하지 않습니다. Policy/role 이름은
checked-in contract로 공유하고 runbook 또는 CI stage가 실행 순서를
보장합니다.
Provider token과 PostgreSQL password는 ephemeral/write-only 입력으로만
전달합니다. KV payload는 Terraform resource/data source로 읽거나 쓰지
않습니다.
## KV ownership paths
Secret path는 repository taxonomy와 같은 owner를 표현합니다.
| Consumer | Vault CLI path |
|---|---|
| PostgreSQL bootstrap | `kv/dev/systems/auth-system/postgres/superuser` |
| Auth database bootstrap/runtime | `kv/dev/systems/auth-system/postgres/auth-server` |
| Keycloak database | `kv/dev/systems/auth-system/postgres/keycloak` |
| Keycloak bootstrap admin | `kv/dev/systems/auth-system/keycloak/bootstrap-admin` |
| Auth-server Keycloak client | `kv/dev/workloads/auth-server/keycloak-client` |
Vault ACL과 Agent annotation은 KV-v2 API path인 `kv/data/...`를 사용합니다.
CLI의 `vault kv put``kv/dev/...`를 사용합니다. 이전
`kv/dev/platform/...` 값은 migration source이며 새 policy가 계속
허용하면 안 됩니다.
## Workload authentication
Workload는 audience `vault`, TTL 1시간의 projected ServiceAccount token으로
Vault Kubernetes auth에 로그인합니다. Token은 Vault Agent가 사용하며
application container에 Kubernetes bearer token을 직접 노출하지 않습니다.
Role은 ServiceAccount, namespace, audience, token policy와 TTL을 정확히
묶습니다. 현재 role은 Project Auth backing service의 `auth-system-dev`
Vault를 사용하는 `auth-dev` ServiceAccount에만 존재합니다. `api-dev`에는
Vault role도 Vault NetworkPolicy ingress도 없으며 필요가 생기기 전에는
권한을 추가하지 않습니다.
Secret 값은 승인된 운영자가 Vault에 직접 기록합니다. 값은 Git, Gitea
Actions log, Terraform state, Kubernetes manifest에 남기지 않습니다.
## Bootstrap material
Vault init output은 기본적으로 `.local/vault/dev-k3s-init.json`에 mode
`0600`으로 생성됩니다. Encrypted custody로 이동한 뒤 working copy를
제거합니다.
Initial root token은 다음 작업에만 사용합니다.
1. `vault-foundation` apply
2. OIDC/JWT가 없는 빈 lab의 짧은 TTL bootstrap token 발급과 capability
검증
3. 최초 runtime secret seed
4. 필요한 break-glass/recovery 절차 확인
`vault-database` 적용까지 끝나면 replacement token의 대표 update
capability와 root policy 부재를 확인한 뒤 initial root와 bootstrap token을
폐기합니다. 상시 cluster ServiceAccount에 broad `platform-admin` 정책을
연결하지 않습니다. `vault-workloads``vault-database`의 routine 실행은
각각 짧은 TTL identity를 사용합니다.
Initial root 폐기 뒤에는 상시 foundation administrator가 없습니다. Future
foundation 변경은 encrypted unseal custody의 승인을 받아 Vault
generated-root ceremony를 수행하고, 승인된 plan 적용 뒤 생성한 root를
즉시 폐기해야 합니다.
Sealed Secrets는 private GHCR pull credential에만 사용합니다. Controller
private key는 Git과 분리된 recovery custody에 백업합니다.
## Dev limitations
- Vault, PostgreSQL, ingress가 TLS를 사용하지 않음
- Single-node Vault와 PostgreSQL
- Kubernetes API egress CIDR가 현재 dev cluster에 종속
- 정적 bootstrap secret은 coordinated rotation 필요
- Namespace/path migration이 아직 실제 cluster에 적용되지 않음
이 제약은 production에서 허용되지 않습니다.