HashiCorp Vault 란?
Vault는 API 키, DB 비밀번호, 인증서 같은 시크릿(secret)을 중앙에서 안전하게 보관·발급·감사하는 도구입니다. 코드에 비밀번호를 하드코딩하거나 환경변수 파일을 여기저기 뿌리는 방식의 근본적 위험을 해결합니다.
Vault의 강력한 차별점은 **동적 시크릿(dynamic secrets)**입니다. 정적 비밀번호를 저장만 하는 게 아니라, 애플리케이션이 요청할 때마다 짧은 수명의 DB 계정을 즉석에서 생성하고 TTL이 지나면 자동 폐기합니다. 비밀번호가 유출되어도 수명이 짧아 피해가 제한되고, 자격증명이 누구에게 언제 발급됐는지 모두 감사 로그에 남습니다.
이 가이드는 단일 노드 개발/스테이징 환경 기준으로 Vault의 핵심 개념과 주요 워크플로(KV 시크릿, DB 동적 자격증명, AppRole)를 다룹니다.
이 문서의 vault server -dev는 학습용입니다. 메모리에만 데이터를 두고 자동 unseal되며 TLS도 없습니다. 운영에는 절대 사용하지 마세요. 운영은 영속 스토리지(Integrated Storage/Raft) + TLS + 분산 unseal 키 구성이 필요합니다.
핵심 개념
| 개념 | 설명 |
|---|---|
| Seal / Unseal | Vault는 시작 시 암호화된 봉인 상태. 마스터 키 조각으로 unseal해야 데이터 접근 가능 |
| Unseal Key (Shamir) | 마스터 키를 N개 조각으로 분할, K개 모여야 복호화(예: 5개 중 3개) |
| Root Token | 모든 권한을 가진 초기 토큰. 작업 후 폐기 권장 |
| Token | 모든 요청은 토큰으로 인증. TTL과 정책이 부여됨 |
| Policy | HCL로 작성하는 경로별 권한(capabilities) |
| Secrets Engine | 시크릿을 다루는 플러그인(kv, database, pki 등) |
| Auth Method | 사용자/앱 인증 방식(token, approle, userpass, kubernetes) |
서버 기동과 unseal
학습용 dev 서버:
vault server -dev -dev-root-token-id="root"
# 출력된 VAULT_ADDR, Root Token을 메모운영형 기동(Raft 스토리지)은 config 파일을 사용합니다.
# /etc/vault.d/vault.hcl
storage "raft" {
path = "/opt/vault/data"
node_id = "node1"
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_cert_file = "/etc/vault.d/tls/vault.crt"
tls_key_file = "/etc/vault.d/tls/vault.key"
}
api_addr = "https://vault.example.com:8200"
ui = trueexport VAULT_ADDR='https://vault.example.com:8200'
vault operator init # unseal 키 5개 + root 토큰 발급 (안전 보관!)
vault operator unseal # 키 3개를 각각 입력
vault status # Sealed: false 확인vault operator init 출력(unseal 키, root 토큰)은 단 한 번만 표시됩니다. 분실하면 데이터를 영구히 잃습니다. 키 조각은 서로 다른 담당자/금고에 분산 보관하세요.
CLI 로그인
export VAULT_ADDR='http://127.0.0.1:8200'
vault login # 토큰 입력 (dev면 root)
vault token lookup # 현재 토큰 정보·TTL·정책 확인KV v2 — 정적 시크릿
가장 기본적인 시크릿 저장소입니다. v2는 버전 관리와 소프트 삭제를 지원합니다.
# KV v2 엔진 활성화
vault secrets enable -path=secret kv-v2
# 시크릿 저장
vault kv put secret/myapp/db username="appuser" password="s3cr3t"
# 조회
vault kv get secret/myapp/db
vault kv get -field=password secret/myapp/db # 값만 추출
# 버전 관리
vault kv get -version=1 secret/myapp/db
vault kv metadata get secret/myapp/db # 버전 이력
# 소프트 삭제 / 복구 / 완전 삭제
vault kv delete secret/myapp/db
vault kv undelete -versions=2 secret/myapp/db
vault kv destroy -versions=1 secret/myapp/dbKV v2는 API 경로에 /data/가 끼어든다는 점에 유의해야 합니다(정책 작성 시 중요).
정책(Policy)
권한은 경로별 capabilities로 정의합니다.
# myapp-policy.hcl
# KV v2이므로 실제 경로는 secret/data/...
path "secret/data/myapp/*" {
capabilities = ["read", "list"]
}
path "secret/metadata/myapp/*" {
capabilities = ["list", "read"]
}vault policy write myapp myapp-policy.hcl
vault policy read myappcapabilities는 create, read, update, delete, list, sudo, deny가 있으며 최소 권한 원칙으로 부여합니다.
동적 자격증명 — Database 시크릿 엔진
Vault가 PostgreSQL에 접속해 요청 시마다 임시 계정을 만들어주는 구성입니다.
# 엔진 활성화
vault secrets enable database
# DB 연결 설정 (Vault가 사용할 관리자 계정)
vault write database/config/postgres \
plugin_name=postgresql-database-plugin \
allowed_roles="readonly" \
connection_url="postgresql://{{username}}:{{password}}@db.example.com:5432/app?sslmode=require" \
username="vault_admin" \
password="adminpass"
# 역할 정의: 발급 시 실행할 SQL과 TTL
vault write database/roles/readonly \
db_name=postgres \
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"이제 자격증명을 요청하면:
vault read database/creds/readonly
# Key Value
# lease_id database/creds/readonly/abc123
# lease_duration 1h
# username v-token-readonly-x9f2...
# password A1b2-randomgenerated발급된 계정은 1시간 뒤 자동 폐기됩니다. 즉시 회수하려면:
vault lease revoke database/creds/readonly/abc123동적 자격증명을 쓰려면 Vault 관리자 계정이 DB에서 CREATEROLE 권한을 가져야 합니다. 이 관리자 계정 자체도 vault write database/rotate-root/postgres로 주기 교체하세요.
AppRole — 애플리케이션 인증
사람이 아닌 애플리케이션/CI가 Vault에 인증하는 표준 방식입니다.
vault auth enable approle
vault write auth/approle/role/myapp \
token_policies="myapp" \
token_ttl=1h token_max_ttl=4h \
secret_id_ttl=24h
# RoleID(공개) + SecretID(비밀) 발급
vault read auth/approle/role/myapp/role-id
vault write -f auth/approle/role/myapp/secret-id
# 두 값으로 로그인 → 단기 토큰 획득
vault write auth/approle/login \
role_id="<role_id>" secret_id="<secret_id>"RoleID는 빌드에 박아두고 SecretID는 런타임에 안전하게 주입하는 패턴(예: CI 시크릿)을 씁니다.
감사 로그
vault audit enable file file_path=/var/log/vault/audit.log모든 요청·응답이 해시된 형태로 기록됩니다. 컴플라이언스 대응의 핵심입니다.
정리
| 항목 | 핵심 |
|---|---|
| Seal/Unseal | 시작 시 봉인, Shamir 키 K-of-N으로 해제 |
| KV v2 | 정적 시크릿, 버전·소프트삭제, 경로에 /data/ |
| Policy | 경로별 capabilities, 최소 권한 |
| Database 엔진 | 요청 시 임시 계정 생성, TTL 후 자동 폐기 |
| AppRole | RoleID + SecretID로 앱 인증 |
| 감사 | vault audit enable로 전체 요청 기록 |
Vault의 진가는 정적 시크릿 보관을 넘어 동적·단기 자격증명에 있습니다. "비밀번호를 저장하지 말고 필요할 때 짧게 발급하라"가 핵심 사고방식입니다.
이 가이드는 AI 도구를 활용해 초안을 구성하고 사람이 명령어·문맥을 검토해 발행했습니다. 운영체제와 도구 버전에 따라 결과가 달라질 수 있으므로 적용 전 공식 문서를 함께 확인하세요. 오류를 발견하시면 이메일로 제보해 주세요.
질문 & 답변 (Q&A)
이 가이드에 대해 궁금한 점을 질문해보세요. 확인 후 답변드립니다.