Vault
HashiCorp Vault
HashiCorp의 비밀 관리 도구. API 키, 비밀번호, 인증서 등을 안전하게 저장하고, 동적 비밀 생성, 데이터 암호화, 세밀한 접근 제어를 제공하는 중앙 집중형 보안 솔루션입니다.
HashiCorp Vault
HashiCorp의 비밀 관리 도구. API 키, 비밀번호, 인증서 등을 안전하게 저장하고, 동적 비밀 생성, 데이터 암호화, 세밀한 접근 제어를 제공하는 중앙 집중형 보안 솔루션입니다.
HashiCorp Vault는 비밀(Secrets)을 안전하게 저장하고 관리하기 위한 오픈소스 도구입니다. API 키, 비밀번호, 인증서, 암호화 키 등 민감한 데이터를 중앙에서 관리하고, 필요할 때만 안전하게 접근할 수 있도록 합니다.
현대 클라우드 네이티브 환경에서는 수많은 서비스가 데이터베이스, 외부 API, 다른 서비스에 접근하기 위해 비밀이 필요합니다. Vault는 이런 비밀들을 코드나 설정 파일에 하드코딩하는 대신, 중앙화된 안전한 저장소에서 관리하고, 감사 로그를 통해 모든 접근을 추적할 수 있게 합니다.
API 키, 비밀번호 등을 키-값 형태로 안전하게 저장. 버전 관리로 변경 이력 추적 가능.
요청 시 임시 데이터베이스 자격증명 생성. 사용 후 자동 폐기로 보안 강화.
데이터를 암호화/복호화하는 API 제공. 앱이 직접 키를 관리할 필요 없음.
내부 CA 운영. TLS 인증서 자동 발급 및 갱신으로 mTLS 구현 용이.
정책 기반 권한 관리. 누가 어떤 비밀에 접근할 수 있는지 세밀하게 제어.
모든 접근과 작업을 기록. 규정 준수(SOC2, HIPAA 등) 요구사항 충족.
| 기능 | HashiCorp Vault | AWS Secrets Manager | Azure Key Vault |
|---|---|---|---|
| 배포 방식 | Self-hosted / Cloud | Managed (AWS only) | Managed (Azure only) |
| 동적 비밀 | DB, AWS, GCP, Azure 등 | RDS만 지원 | 제한적 |
| 멀티 클라우드 | 완전 지원 | AWS 전용 | Azure 전용 |
| 암호화 서비스 | Transit Engine | KMS 별도 | 지원 |
| PKI/인증서 | 내장 CA | ACM 별도 | 지원 |
| 비용 | OSS 무료 / Enterprise 유료 | 비밀당 과금 | 작업당 과금 |
# Vault CLI 기본 사용법 # 1. Vault 서버 주소 설정 export VAULT_ADDR='https://vault.example.com:8200' # 2. 로그인 (토큰 방식) vault login $VAULT_TOKEN # LDAP 로그인 vault login -method=ldap username=myuser # 3. 비밀 저장 (KV v2) vault kv put secret/myapp/config \ db_host="db.example.com" \ db_user="admin" \ db_pass="supersecret123" # 4. 비밀 읽기 vault kv get secret/myapp/config # JSON 출력 vault kv get -format=json secret/myapp/config # 특정 필드만 추출 vault kv get -field=db_pass secret/myapp/config # 5. 동적 데이터베이스 자격증명 생성 # (사전에 database secret engine 설정 필요) vault read database/creds/readonly # 출력 예시: # lease_id database/creds/readonly/abc123 # lease_duration 1h # username v-token-readonly-xyz789 # password A1b2C3d4E5f6! # 6. Transit으로 데이터 암호화 vault write transit/encrypt/my-key \ plaintext=$(echo "secret data" | base64) # 7. 정책 확인 vault policy list vault policy read myapp-policy
# Python에서 Vault 사용 (hvac 라이브러리) import hvac import os # 1. Vault 클라이언트 초기화 client = hvac.Client( url=os.environ['VAULT_ADDR'], token=os.environ.get('VAULT_TOKEN') ) # Kubernetes 인증 (Pod 내에서) def login_with_kubernetes(): with open('/var/run/secrets/kubernetes.io/serviceaccount/token') as f: jwt = f.read() client.auth.kubernetes.login( role='myapp-role', jwt=jwt, mount_point='kubernetes' ) return client # 2. 비밀 읽기 (KV v2) def get_database_config(): secret = client.secrets.kv.v2.read_secret_version( path='myapp/config', mount_point='secret' ) return secret['data']['data'] config = get_database_config() db_host = config['db_host'] db_pass = config['db_pass'] # 3. 동적 데이터베이스 자격증명 def get_db_credentials(): creds = client.secrets.database.generate_credentials( name='readonly', mount_point='database' ) return { 'username': creds['data']['username'], 'password': creds['data']['password'], 'lease_id': creds['lease_id'], 'lease_duration': creds['lease_duration'] } # 4. Transit 암호화 def encrypt_data(plaintext: str) -> str: import base64 encoded = base64.b64encode(plaintext.encode()).decode() result = client.secrets.transit.encrypt_data( name='my-key', plaintext=encoded, mount_point='transit' ) return result['data']['ciphertext'] def decrypt_data(ciphertext: str) -> str: import base64 result = client.secrets.transit.decrypt_data( name='my-key', ciphertext=ciphertext, mount_point='transit' ) return base64.b64decode(result['data']['plaintext']).decode()
# External Secrets Operator로 Vault 연동 # Kubernetes Secret을 Vault에서 자동 동기화 # 1. SecretStore 정의 (Vault 연결 설정) apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: vault-backend namespace: default spec: provider: vault: server: "https://vault.example.com:8200" path: "secret" version: "v2" auth: kubernetes: mountPath: "kubernetes" role: "myapp-role" serviceAccountRef: name: "vault-auth" --- # 2. ExternalSecret 정의 (동기화할 비밀 지정) apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: myapp-secrets namespace: default spec: refreshInterval: "1h" # 1시간마다 갱신 secretStoreRef: name: vault-backend kind: SecretStore target: name: myapp-secrets # 생성될 K8s Secret 이름 creationPolicy: Owner data: - secretKey: DB_HOST remoteRef: key: myapp/config property: db_host - secretKey: DB_PASSWORD remoteRef: key: myapp/config property: db_pass --- # 3. Pod에서 Secret 사용 apiVersion: v1 kind: Pod metadata: name: myapp spec: containers: - name: app image: myapp:latest envFrom: - secretRef: name: myapp-secrets # 자동 동기화된 Secret
초기 설정 후 Root 토큰은 반드시 폐기하세요. 모든 권한을 가진 토큰이 유출되면 전체 비밀이 노출됩니다. 일반 운영에는 최소 권한을 가진 정책 기반 토큰을 사용하세요.
Shamir 방식 사용 시 Unseal 키를 안전하게 분산 보관하세요. 여러 담당자에게 분산하거나, AWS KMS 같은 Auto-Unseal을 사용하는 것을 권장합니다. 키 분실 시 데이터 복구가 불가능합니다.
프로덕션 환경에서는 반드시 감사 로그를 활성화하세요. 모든 접근과 변경을 기록해야 보안 사고 발생 시 추적이 가능하고, 규정 준수 요구사항도 충족할 수 있습니다.
Vault가 중단되면 애플리케이션이 비밀에 접근할 수 없습니다. 프로덕션에서는 반드시 HA 클러스터로 구성하고, 애플리케이션에 비밀 캐싱 전략을 적용하세요.
20개 이상의 마이크로서비스가 있는 환경에서, 각 서비스마다 환경변수로 비밀을 관리하던 것을 Vault + External Secrets Operator로 전환했습니다. 배포 시 수동 설정이 사라지고, 비밀 교체도 자동화되었습니다.
💡 결과: 배포 시간 50% 단축, 비밀 교체 시간 수시간 → 수분
PCI-DSS 준수를 위해 DB 자격증명의 수명을 1시간으로 제한해야 했습니다. Vault의 동적 비밀 기능으로 요청 시 임시 계정을 생성하고 자동 폐기하여, 감사 요구사항을 충족하면서도 개발자 경험을 저하시키지 않았습니다.
💡 결과: PCI-DSS 인증 획득, 자격증명 유출 위험 95% 감소
AWS, GCP, 온프레미스에 분산된 인프라에서 각 클라우드의 비밀 관리 도구를 개별적으로 사용하던 것을 Vault로 통합했습니다. 단일 정책과 감사 로그로 모든 환경의 비밀을 일관되게 관리할 수 있게 되었습니다.
💡 결과: 관리 복잡도 70% 감소, 통합 감사 리포트 자동화
Vault의 "동적 비밀(Dynamic Secrets)" 기능의 주요 장점은 무엇인가요?