Kubernetes(K8s) 환경에서 HashiCorp Vault를 사용할 때 보안 접근 방식은 전통적인 "Perimeter Security(경계 기반 보안)"에서 벗어나 Zero-Trust 모델로 이동하는 것이 현재의 Best Practice입니다.
여기서 자주 나오는 표현이 "Never Trust, Always Verify" 입니다.
이 문장을 Vault + Kubernetes 관점에서 자세히 풀어보겠습니다.
| 원칙 | 전통적 신뢰 모델 | Zero-Trust (Never Trust) 방식 in K8s + Vault |
|---|---|---|
| 신원 인증 | 노드/IP가 클러스터 안에 있으면 신뢰 | Pod의 실제 신원(ServiceAccount + JWT)을 매번 검증 |
| 권한 부여 | 네트워크/VPC 안에 있으면 접근 허용 | 최소 권한(Least Privilege)으로 Vault Policy를 엄격히 적용 |
| 암호화 | 전송계층(TLS)만 암호화 | 데이터 자체도 항상 암호화 (Vault Transit, Dynamic Secrets) |
| 신뢰 지속 기간 | 한 번 로그인하면 세션 유지 | 모든 요청마다 재인증 (짧은 TTL, 30초~몇 분짜리 credential) |
→ 즉 "클러스터 안에 있다 = 안전하다"는 가정을 완전히 버리는 것이 Zero-Trust입니다.
| 구성 요소 | Never Trust 구현 방법 |
|---|---|
| Pod → Vault 인증 | Kubernetes Auth Method 사용 – Pod는 ServiceAccount JWT를 Signed해서 Vault에 제출 – Vault는 K8s API 서버에 직접 JWT 유효성 검증 (매 요청마다) → Pod가 노드에 있든, IP가 내부든 상관없이 JWT가 유효해야만 로그인 가능 |
| Vault Token TTL | 기본적으로 매우 짧게 설정 (예: 5~30분) → 토큰이 유출되어도 오래 사용 못함 |
| Dynamic Secrets | DB Credential, SSH Key, AWS IAM Role 등 필요할 때마다 생성 후 바로 폐기 → 장기 유출 가능한 정적 시크릿 사용 금지 |
| Bound ServiceAccount | Vault Role에 bound_service_account_names, bound_service_account_namespaces 강제 바인딩→ 다른 SA로는 해당 Role 사용 불가 |
| Token Bound CIDR (옵션) | 과거에는 Pod IP 범위로 제한했으나, 현재는 deprecate → 이제는 JWT 검증만 믿음 (더 강력한 Zero-Trust) |
| AppRole + Pull Authentication | 대신 AppRole을 쓸 때도 HMAC 기반 Pull 방식이나, EKS/IRSA 같은 워크로드 아이덴티티 사용 추천 |
| Vault Identity & Entity | Pod뿐만 아니라 인간 사용자, CI/CD 파이프라인까지 모두 Entity로 관리 → 모든 주체를 동일한 Zero-Trust 정책 적용 |
# Vault에서 Kubernetes Auth Method 활성화
vault auth enable kubernetes
# Vault가 K8s API로 JWT 검증할 수 있게 설정
vault write auth/kubernetes/config \
token_reviewer_jwt="<SA JWT>" \
kubernetes_host="https://kubernetes.default.svc:443" \
kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
# 특정 Namespace + ServiceAccount만 허용하는 Role
vault write auth/kubernetes/role/myapp-role \
bound_service_account_names=myapp-sa \
bound_service_account_namespaces=prod \
policies=myapp-policy \
ttl=10m
→ 이 설정에서는
myapp-sa가 아니면 절대 로그인 불가prod 네임스페이스가 아니면 불가이게 바로 "Never Trust, Always Verify" 의 실체입니다.
| 항목 | 전통적 신뢰 (Trust but Verify) | Zero-Trust (Never Trust, Always Verify) |
|---|---|---|
| Pod가 클러스터 안에 있으면? | → 기본적으로 신뢰 | → 여전히 검증 필요 (JWT + Bound SA) |
| Vault Agent Injector | 사이드카가 시크릿 주입 | 사이드카조차 Pod의 신원(JWT)으로 Vault에 매번 인증해서 시크릿 받아옴 |
| 정적 시크릿 (kubernetes secret) | 많이 사용 | 사용 금지, 또는 최소화 (Dynamic Secrets + Vault Agent 권장) |
| 네트워크 정책 | 중요하지만 보조적 | 필수지만, 여전히 신원 기반 인증이 주된 방어선 |
결론:
Kubernetes + Vault 환경에서 Zero-Trust는 "어떤 Pod도, 어떤 네트워크에 있든, 어떤 IP를 가지든 무조건 신원(JWT)을 증명하고, 최소 권한만 주며, 짧은 시간만 유효한 credential만 사용한다"는 원칙으로 구현됩니다.
이것이 바로 "Never Trust, Always Verify"의 실체입니다.