HashiCorp Vault 시크릿 관리: 안전한 실습에서 운영 설계까지

반응형

가시다님의 CI/CD 스터디에서 다룬 내용을 바탕으로 Vault를 추가 실습하며 정리했다. 처음에는 key-value 값을 저장하고 Pod에 주입하는 흐름이 단순해 보였지만, 운영 기준으로 보면 인증, 권한, secret 수명, audit와 Vault 자체 복구까지 함께 설계해야 했다.

관련 스터디 자료는 gasida GitHub에서 확인할 수 있다.

Vault가 해결하는 문제

source code, image, CI log와 Kubernetes manifest에 credential을 직접 넣으면 복제 범위와 폐기 비용이 커진다. Vault는 secret을 중앙에서 보관하는 것뿐 아니라 다음 기능을 묶어 제공한다.

  • identity에 따른 authentication
  • path와 capability 기반 authorization
  • lease·TTL과 revocation
  • dynamic credential 발급
  • secret version 관리
  • audit device를 통한 request 기록

반대로 Vault를 설치했다고 application의 모든 secret이 자동으로 안전해지는 것은 아니다.

  • root 또는 과도한 policy
  • 장기 token
  • TLS 검증 우회
  • application log에 노출된 값
  • file 주입 뒤 reload되지 않는 process
  • backup 없는 Vault storage

이 문제는 여전히 운영자가 책임져야 한다.

Dev server는 학습 도구다

Vault dev server는 local 실습을 빠르게 시작하도록 일부러 안전하지 않은 기본값을 사용한다.

  • in-memory storage
  • 자동 initialize·unseal
  • loopback의 HTTP listener
  • 출력에 표시되는 root token
  • 기본 KV v2 mount

공식 문서도 production에 사용하지 말라고 명확히 경고한다. dev mode를 NodePort나 public interface로 노출하거나, dev root token을 고정 문자열로 만들어 팀이 공유하면 안 된다.

local 실습에서도 terminal scrollback과 shell history, screen sharing에 token이 남을 수 있다. 출력된 credential은 lab 종료와 함께 폐기하고 다른 환경에서 재사용하지 않는다.

설치보다 먼저 chart를 검토한다

Kubernetes에 바로 설치하기보다 사용할 chart version과 rendered manifest를 먼저 본다. 아래 예시는 이미 official HashiCorp chart repository가 등록돼 있다는 전제의 read-only review 흐름이다.

helm search repo hashicorp/vault --versions

CHART_VERSION='reviewed-version'
helm show chart hashicorp/vault --version "$CHART_VERSION"
helm show values hashicorp/vault --version "$CHART_VERSION" | less
helm template vault hashicorp/vault \
  --namespace vault \
  --version "$CHART_VERSION" \
  --values values-review.yaml | less

reviewed-version에는 실제로 검토하고 pin한 version을 넣는다. rendered output을 file로 저장하거나 공유할 때는 민감한 configuration과 reference가 없는지 먼저 확인한다.

검토 항목은 다음과 같다.

  • image tag뿐 아니라 digest를 고정할지
  • Service·Ingress·Gateway 노출 범위
  • TLS certificate와 trust chain
  • storage backend와 persistent volume
  • Pod security context와 service account
  • network policy
  • resource request·limit, anti-affinity와 disruption budget
  • injector webhook의 failure policy와 timeout

실제 install·upgrade는 별도 change review, staging 검증과 rollback runbook을 거친다. blog의 단축 명령을 production에 그대로 실행하는 방식은 피한다.

KV v2는 version이 있는 secret store다

KV v2는 secret data version을 저장하고 soft delete·undelete, version destroy와 check-and-set를 지원한다. API path에는 data와 metadata가 분리되므로 KV v1과 path를 혼동하지 않아야 한다.

version이 있다고 backup이 되는 것은 아니다. storage 자체가 손상되거나 cluster를 잃으면 KV history도 함께 잃을 수 있다. integrated storage를 쓴다면 Raft snapshot과 restore를 별도로 시험한다.

실제 credential 값을 command argument로 넘기면 shell history와 process list에 남을 수 있다. 실습 값도 실제 secret과 구분되는 dummy data를 쓰고, 운영 입력은 승인된 automation과 secret-safe input 경로를 사용한다.

Kubernetes authentication은 Pod identity를 Vault identity로 바꾼다

Kubernetes auth method의 큰 흐름은 다음과 같다.

Pod projected service-account token
          │
          ▼
Vault Kubernetes auth role
          │ verifies namespace, service account, audience
          ▼
short-lived Vault token + attached policies

모든 Pod가 쓰는 default service account를 넓게 bind하지 않는다. workload별 service account를 만들고 namespace, service-account name과 token audience를 제한한다.

Vault policy도 필요한 path와 operation만 허용한다.

path "kv/data/payments/checkout" {
  capabilities = ["read"]
}

이 예시는 checkout workload가 한 path를 읽는 최소 형태다. broad wildcard와 write·delete capability가 정말 필요한지 따로 검토한다. policy name만 보고 안전하다고 판단하지 말고 실제 path와 capability를 review한다.

Kubernetes service-account token과 Vault token의 TTL, renewal과 revocation도 연결해야 한다. 장기 token을 Kubernetes Secret에 저장해 재사용하면 identity 연동의 장점이 줄어든다.

Pod에 secret을 전달하는 세 가지 방식

Vault Agent Injector

Injector는 mutating admission webhook으로 Pod spec에 init container와 sidecar를 추가한다. Agent가 Vault에 인증하고 shared memory volume의 /vault/secrets 아래에 template 결과를 쓴다.

장점은 application이 Vault API를 직접 구현하지 않아도 file을 읽을 수 있다는 것이다. 주의할 점도 있다.

  • webhook 장애가 Pod 생성에 미치는 영향
  • init-only인지 sidecar renewal인지
  • rendered file permission
  • application이 file 변경을 자동 reload하는지
  • annotation이 허용된 namespace와 workload

Agent가 file을 갱신해도 application process가 이미 읽은 environment variable이나 memory 값은 자동으로 바뀌지 않는다. reload signal, file watch 또는 restart policy를 application과 합의한다.

Secrets Store CSI Provider

CSI 방식은 volume으로 secret을 mount한다. 기존 file 기반 application과 연결하기 쉽지만 node plugin·provider 운영, rotation 반영과 optional Kubernetes Secret sync의 보안 영향을 검토해야 한다.

Kubernetes Secret으로 sync하면 etcd encryption, RBAC, backup과 watcher를 포함해 Secret의 노출 경계가 다시 생긴다.

Vault Secrets Operator

Operator는 Vault secret을 Kubernetes resource lifecycle과 맞춰 sync할 수 있다. declarative 관리에는 편하지만 controller 권한과 destination Secret의 수명, reconciliation failure를 운영해야 한다.

방식 application 변경 Kubernetes Secret 생성 주요 운영 포인트
Agent Injector file read 지원 기본적으로 불필요 webhook, sidecar, reload
CSI mounted file 선택적 node plugin, rotation
Operator Secret reference 주로 생성 controller RBAC, sync 상태

어떤 방식이 항상 우월한 것이 아니라 application의 reload 능력, secret 수명과 platform 운영 범위로 고른다.

운영 Vault는 중앙 의존성이다

Vault 장애가 여러 application의 deploy·startup·credential renewal을 동시에 막을 수 있다. 운영 설계에서는 다음을 다룬다.

Availability와 storage

  • integrated storage Raft의 node·failure-domain 배치
  • quorum과 autopilot 상태
  • snapshot 생성·보관·restore 연습
  • seal·unseal 또는 auto-unseal dependency
  • upgrade compatibility와 rollback

TLS와 network

  • client부터 Vault까지 TLS
  • hostname과 SAN이 맞는 certificate
  • trust bundle 배포와 rotation
  • network policy·firewall로 source 제한
  • certificate 검증을 끄는 우회 금지

privilege와 recovery

  • 일상 작업에 root token을 쓰지 않음
  • break-glass 발급·보관·만료·감사
  • recovery key와 unseal material의 분리 보관
  • auth role·policy·token accessor의 owner

audit와 privacy

Vault audit device는 누가 어느 path에 요청했는지 조사하는 핵심 자료다. audit destination의 가용성과 용량을 monitoring하고, 운영자가 raw log에 접근하는 권한도 제한한다. request metadata에 민감 정보가 섞일 가능성을 검토한다.

실습에서 운영으로 넘어가는 점검표

  • dev server와 production topology가 명확히 분리됐는가?
  • chart·image version을 검토하고 pin했는가?
  • TLS certificate 검증을 모든 client에서 유지하는가?
  • workload별 service account와 audience를 쓰는가?
  • policy가 path·capability 최소 권한인가?
  • token TTL·renewal·revocation owner가 있는가?
  • Agent·CSI·Operator 중 application reload에 맞는 방식을 골랐는가?
  • storage snapshot과 restore를 실제로 시험했는가?
  • audit device의 장애·용량·접근 권한을 monitoring하는가?
  • root·recovery credential의 break-glass 절차가 있는가?
  • secret이 manifest, command history, log와 trace에 남지 않는가?

Vault의 핵심 가치는 secret 값을 한곳에 모으는 데서 끝나지 않는다. workload identity에 최소 권한과 짧은 수명을 연결하고, 발급부터 폐기까지 감사 가능한 흐름을 만드는 것에 있다.

Argo CD 접근 제어 설계는 GitOps 권한과 credential lifecycle을 연결한다. Jenkins·Argo CD·Keycloak·OpenLDAP SSO는 application authentication과 authorization을 분리해 보는 다음 글이다.

참고 자료

반응형
KEEP READING
카테고리 전체 보기 →

댓글