Moment Note

배포 시크릿 관리: Vault vs SOPS vs 클라우드 KMS

CI/CD & DevOps ·

CI/CD 파이프라인이 성숙해질수록 반드시 마주치는 문제가 시크릿 관리입니다. DB 비밀번호, API 키, TLS 인증서, 클라우드 자격 증명 — 이런 값들을 어떻게 저장하고, 어떻게 배포 시점에 안전하게 주입할 것인가는 보안과 운영 편의가 정면으로 부딪히는 지점입니다. Git에 평문으로 커밋하는 것은 논외지만, 그렇다고 모든 팀이 무거운 시크릿 인프라를 운영할 여력이 있는 것도 아닙니다.

이 글에서는 대표적인 세 접근 — HashiCorp Vault(동적 시크릿 엔진), SOPS(Git에 암호화된 파일을 커밋), 클라우드 KMS/Secrets Manager(관리형 서비스) — 를 비교합니다. 각 방식의 실제 명령·설정을 보여주고, 어떤 규모·요구에 어떤 선택이 맞는지 트레이드오프 중심으로 정리하겠습니다.

세 접근의 근본적 차이

먼저 세 방식이 “무엇을 다르게 하는가”를 정리하면 선택이 쉬워집니다.

  • SOPS: 시크릿을 파일에 암호화해 Git에 함께 저장합니다. GitOps 워크플로와 궁합이 좋고, 별도 서버가 필요 없습니다. 대신 회전(rotation)·감사(audit)·동적 발급은 기본 제공하지 않습니다.
  • Vault: 시크릿을 중앙 서버에서 관리하며, 짧은 수명의 동적 시크릿 발급, 세밀한 정책, 감사 로그를 제공합니다. 강력하지만 운영 부담이 큽니다.
  • 클라우드 KMS/Secrets Manager: 클라우드 제공자의 관리형 서비스에 위임합니다. IAM과 통합되어 편리하지만 특정 클라우드에 종속됩니다.

SOPS: GitOps에 자연스럽게 녹는 암호화 파일

SOPS(Secrets OPerationS)는 YAML/JSON/ENV 파일의 값만 암호화하고 키는 평문으로 남겨, diff가 읽히면서도 시크릿은 보호되는 방식입니다. 암호화 키로는 age, PGP, 또는 클라우드 KMS를 백엔드로 쓸 수 있습니다. age 키를 쓰는 예시입니다.

# age 키 생성
age-keygen -o keys.txt
# 출력된 public key: age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8k

# .sops.yaml 로 암호화 규칙 정의 (리포 루트)
cat > .sops.yaml <<'EOF'
creation_rules:
  - path_regex: secrets/.*\.yaml$
    age: age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8k
EOF

이제 시크릿 파일을 암호화하면 값만 암호문으로 바뀝니다.

# 평문 secrets/db.yaml
#   db_password: super-secret-value
#   api_key: sk-live-abc123

# 제자리 암호화
sops --encrypt --in-place secrets/db.yaml

# 결과: db_password: ENC[AES256_GCM,data:...,type:str]
# 키(db_password)는 평문, 값만 암호화 → git diff 가독성 유지

배포 시점에는 복호화 키(개인 age 키)를 가진 주체만 값을 풀 수 있습니다. CI 러너에는 이 키를 환경 변수나 마운트로 주입합니다.

# CI에서 복호화하여 사용 (SOPS_AGE_KEY_FILE 로 개인키 지정)
export SOPS_AGE_KEY_FILE=/etc/age/keys.txt
sops --decrypt secrets/db.yaml > /tmp/db.yaml

# 또는 Kubernetes 라면 helm-secrets, sops-operator 등과 연동

SOPS의 강점은 인프라가 거의 필요 없고 GitOps와 완벽히 맞는다는 점입니다. 약점은 회전과 감사입니다. 시크릿을 바꾸면 파일을 다시 암호화·커밋해야 하고, 누가 언제 시크릿에 접근했는지 추적이 어렵습니다. 소규모~중규모 팀, 특히 Argo CD/Flux 기반 GitOps에 잘 맞습니다.

Vault: 동적 시크릿과 짧은 수명

Vault의 핵심 가치는 동적 시크릿입니다. 정적 비밀번호를 저장·배포하는 대신, 애플리케이션이 필요할 때 짧은 수명의 자격 증명을 발급받고, TTL이 지나면 자동 폐기됩니다. 유출되더라도 노출 창이 좁아집니다.

# 개발 모드로 빠르게 기동 (프로덕션에서는 사용 금지)
vault server -dev
export VAULT_ADDR='http://127.0.0.1:8200'
export VAULT_TOKEN='...(dev root token)...'

# KV v2 시크릿 저장/조회
vault kv put secret/myapp/db password="s3cr3t"
vault kv get secret/myapp/db

진짜 강점은 database 시크릿 엔진 같은 동적 발급입니다. PostgreSQL에 대해 요청 시마다 임시 사용자를 만들고 TTL이 끝나면 삭제하도록 구성할 수 있습니다.

# database 엔진 활성화 + 연결 설정
vault secrets enable database

vault write database/config/mydb \
  plugin_name=postgresql-database-plugin \
  allowed_roles="app-role" \
  connection_url="postgresql://{{username}}:{{password}}@db:5432/app?sslmode=require" \
  username="vault_admin" password="admin-pass"

# 동적 역할 정의: 요청 시 1시간 TTL 임시 계정 발급
vault write database/roles/app-role \
  db_name=mydb \
  creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
  default_ttl="1h" max_ttl="24h"

# 애플리케이션이 임시 DB 자격 증명 발급받기
vault read database/creds/app-role

Vault는 세밀한 정책(policy), 감사 로그, AppRole/Kubernetes 인증 등 강력한 기능을 제공합니다. 대가는 운영 복잡도입니다. HA 구성, unseal 키 관리, 스토리지 백엔드(Consul/Raft) 운영이 필요하며, “Vault 자체가 죽으면 배포가 멈추는” 단일 의존점이 생깁니다. 규제 산업이나 대규모 조직에서 그 가치가 커집니다.

클라우드 KMS / Secrets Manager: IAM에 위임

이미 특정 클라우드에 올라가 있다면, 관리형 시크릿 서비스가 가장 마찰이 적을 수 있습니다. IAM 권한으로 접근을 통제하고, 회전·감사·암호화를 서비스가 대신 처리합니다. AWS Secrets Manager 예시입니다.

# 시크릿 저장
aws secretsmanager create-secret \
  --name prod/myapp/db \
  --secret-string '{"username":"app","password":"s3cr3t"}'

# 배포 시점에 조회 (IAM 역할이 secretsmanager:GetSecretValue 권한 보유)
aws secretsmanager get-secret-value \
  --secret-id prod/myapp/db \
  --query SecretString --output text

회전은 Lambda 회전 함수와 연동해 자동화할 수 있고, RDS 같은 서비스는 관리형 회전을 지원합니다. 큰 장점은 별도 인프라를 운영하지 않는다는 것이지만, 명백한 단점은 클라우드 종속과 호출 비용·요청 한도입니다. 멀티클라우드나 온프렘 혼합 환경에서는 이 종속성이 문제가 됩니다.

참고로 SOPS는 이 KMS를 암호화 백엔드로 쓸 수도 있어, “Git에 암호화 파일을 두되 키 관리는 클라우드 KMS에 맡기는” 하이브리드 구성도 가능합니다.

# SOPS가 AWS KMS를 백엔드로 사용
sops --encrypt --kms 'arn:aws:kms:ap-northeast-2:111122223333:key/abcd-...' \
  --in-place secrets/prod.yaml

선택 가이드와 공통 원칙

세 방식은 배타적이지 않고 조합할 수 있습니다. 대략적인 결정 기준은 다음과 같습니다.

  • SOPS: GitOps 중심, 소~중규모, 인프라 최소화가 목표일 때. 회전·감사 요구가 낮을 때.
  • Vault: 동적 시크릿·짧은 TTL·세밀한 정책·감사가 필수인 대규모/규제 환경. 전담 인력이 있을 때.
  • 클라우드 KMS/Secrets Manager: 단일 클라우드에 락인되어 있고, 관리형의 편의를 원하며, 종속성을 감수할 수 있을 때.

어떤 방식을 택하든 지켜야 할 공통 원칙이 있습니다. 시크릿을 절대 평문으로 커밋하지 않기, 최소 권한 원칙으로 접근 통제, 정기 회전, 접근 감사 로그 남기기, 그리고 실수로 커밋된 시크릿을 잡아내는 gitleaks/trufflehog 같은 스캐너를 파이프라인에 넣는 것입니다.

# CI 파이프라인에 커밋 시크릿 스캐너 추가 (예: gitleaks)
gitleaks detect --source . --redact --exit-code 1

마무리

시크릿 관리는 “완벽한 도구”를 찾는 문제가 아니라, 우리 팀의 규모·컴플라이언스 요구·운영 역량에 맞는 균형을 잡는 문제입니다. SOPS는 GitOps에 자연스럽게 녹아드는 경량 선택, Vault는 동적 시크릿과 감사가 필요한 대규모의 정답, 클라우드 KMS는 단일 클라우드에서의 편의라는 뚜렷한 색을 가집니다. 도구 선택보다 중요한 것은 평문 금지·최소 권한·회전·감사라는 기본 원칙을 파이프라인에 강제하는 일입니다.