학습 내용은 CloudNet@ 가시다님이 진행하는 CI/CD스터디를 참고하였습니다.
사전 보안 지식
액세스 제어 3단계(AAA)
- 인증(Who are you?)
- 인가(What can you do?)
- 감사(what did you do?)
Vault가 필요한 이유
- IT아키텍처 진화에 따른 보안 복잡성
- 제로 트러스트 보안 모델의 대두
- 기존: "저 서비스는 내부망에 있으니깐 DB에 접근해도 돼." (위치 기반 신뢰)
- 제로 트러스트: "저 서비스가 정말 '주문 서비스'가 맞는지 신원(Identity)을 확인하고, DB의 '주문 테이블'에만 SELECT할 수 있는 최소한의 권한을 5분 동안만 부여하겠어." (신원 기반 + 최소 권한 + 동적 접근)
Vault ?
Hashcorp에서 개발한 시크릿 중앙 관리 솔루션으로, 신원 기반(Identity-based)의 시크릿 및 암호화 관리 시스템입니다.

- 1. 시크릿 스프롤(분산) 문제 해결 → 시크릿 중앙 저장소
- 2. 동적 인프라 문제 해결 → 동적 시크릿 (Dynamic Secrets)
- 3. 제로 트러스트(신원 확인) 문제 해결 → 신원 기반 접근 (Identity-Based Access)
- 4. 감사 및 통제 문제 해결 → 감사 로그 (Audit Logs)
Vault 기본 구조 및 동작 방식 이해
- 인증/인가를 통해 필요한 자격 증명을 동적으로 발급

모든 인증의 목적은 토큰을 얻기 위한 행위입니다.
Vault에서는 인증/인가를 위해 외부 IDP를 연동하고, 엔티티를 기준으로 인증 방법/정책/엔진 접근을 관리합니다.

Vault On Kuberentes 설치
Kind 환경 구성
# kind k8s 배포
kind create cluster --name myk8s --image kindest/node:v1.32.8 --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 30000 # Vault UI
hostPort: 30000
- containerPort: 30001 # Jenkins UI
hostPort: 30001
- containerPort: 30002 # DB 배포(PostgreSQL 또는 MySQL)
hostPort: 30002
- containerPort: 30003 # # Sample App
hostPort: 30003
EOF
Dev Mode 설치(학습용)
- In-Memory Storage: 데이터를 메모리에 저장하므로 재시작 시 데이터가 초기화됩니다.
- Auto Unseal: 자동으로 봉인이 해제된 상태로 시작됩니다.
- Root Token: 초기 루트 토큰이 지정된 값(여기서는 root)으로 고정됩니다.

HELM 설정
# Create a Kubernetes namespace.
kubectl create namespace vault
# View all resources in a namespace.
kubectl get all --namespace vault
# Setup Helm repo
helm repo add hashicorp https://helm.releases.hashicorp.com
# Check that you have access to the chart.
helm search repo hashicorp/vault
NAME CHART VERSION APP VERSION DESCRIPTION
hashicorp/vault 0.31.0 1.20.4 Official HashiCorp Vault Chart
hashicorp/vault-secrets-gateway 0.0.2 0.1.0 A Helm chart for Kubernetes
hashicorp/vault-secrets-operator 1.0.1 1.0.1 Official Vault Secrets Operator Chart
Valut value 구성
cat <<EOF > vault-values-dev.yaml
global:
enabled: true
tlsDisable: true
injector:
enabled: true
# Sidecar Injection을 위해 필요한 설정
server:
dev: # Dev Mode 허용
enabled: true
devRootToken: "root" # 학습 편의를 위해 Root Token을 'root'로 고정
# 데이터 영구 저장이 필요 없으므로 비활성화 (Dev모드는 메모리 사용)
dataStorage:
enabled: false
# UI 활성화 및 NodePort 노출
service:
type: "NodePort"
nodePort: 30000
# 외부 접근을 위해 허용
ui:
enabled: true
EOF
Vault 배포
# Helm Install 실행
helm upgrade vault hashicorp/vault -n vault -f vault-values-dev.yaml --install
# 자원 확인
kubectl get pods,svc,pvc -n vault
NAME READY STATUS RESTARTS AGE
pod/vault-0 1/1 Running 0 72s
pod/vault-agent-injector-556c5dd8fb-pk6qw 1/1 Running 0 72s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/vault NodePort 10.96.23.194 <none> 8200:30000/TCP,8201:32590/TCP 72s
service/vault-agent-injector-svc ClusterIP 10.96.150.240 <none> 443/TCP 72s
service/vault-internal ClusterIP None <none> 8200/TCP,8201/TCP 72s
(참고) Shamir 방식의 봉인 해제 : 볼트 초기화시, 초기 UnSeal 필요하나 dev모드로 봉인 해제되어 있음
kubectl exec -ti vault-0 -n vault -- vault status
Key Value
--- -----
Seal Type shamir
Initialized true
Sealed false # 봉인 안됨
Total Shares 1
Threshold 1
Version 1.20.4
Build Date 2025-09-23T13:22:38Z
Storage Type inmem
Cluster Name vault-cluster-41f08771
Cluster ID f97ecd4e-85f3-adf5-5c6d-9bcc719f53b7
HA Enabled false
암호학자 아디 샤미르(Adi Shamir)의 이름에서 따온 이 시크릿 공유 알고리즘은 개인이 특정 시크릿 정보를 보유하지 않고 결합 될 때에야 암호화 된 루트 키를 해제할 수 있는 단일 키로 조합되는 방식이다.
아래 그림처럼 관리자에게 초기 비밀번호를 5개로 분류하고 3개이상의 관리자 키를 통해서만 봉인 해제가 가능함

[그림] Shamir 방식의 봉인 해제
- Vault CLI 설정 및 콘솔 확인
brew tap hashicorp/tap
brew install hashicorp/tap/vault
vault --version # 설치 확인
# NodePort로 공개한 30000 Port로 설정
export VAULT_ADDR='http://localhost:30000'
# vault 상태확인
vault status
# Root Token으로 로그인
vault login
# 아래, root 입력
Token (will be hidden):
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.
Key Value
--- -----
token root
token_accessor JieAzXpXlILfJxTsgBe3cIZC
token_duration ∞
token_renewable false
token_policies ["root"]
identity_policies []
policies ["root"]
open http://localhost:30000

→ root 토큰은 초기화 이후 없애는 것을 권고
- KV 시크릿 엔진 활성화(정적 시크릿)
Version1 : KV 버전관리 불가 / Version2 : KV 버전관리 가능 [Docs]
→ Version에 버전 관리 메타데이터가 추가되어 속도는 Version 1이 더 빠르나 차이는 없음(다량의 트랜젝션이 필요한 경우 Version 1 고려)
→ 실습에서는 Version 2로 실습
# 활성화된 시크렛 엔진 목록 조회
vault secrets list
Path Type Accessor Description
---- ---- -------- -----------
cubbyhole/ cubbyhole cubbyhole_92a571f7 per-token private secret storage
identity/ identity identity_464bc39a identity store
secret/ kv kv_737df813 key/value secret storage
sys/ system system_699be8c4 system endpoints used for control, policy and debugging
# KV v2 형태로 엔진 활성화하기 위한 명령은 다음과 같지만 Dev 모드에서 활성화 되어있음.
# vault secrets enable -path=secret kv-v2
# 샘플 시크릿 저장 (경로: secret/sampleapp/config)
vault kv put secret/sampleapp/config \
username="demo" \
password="p@ssw0rd"
# 입력된 데이터 확인
vault kv get secret/sampleapp/config

Vault Agent
애플리케이션에서 Vault 연동이 어려움(언어마다 다르며, 보안 인프라 로직 필요)
→ Vault Agent는 이 문제를 사이드카(Sidecar) 기반 표준 패턴으로 깔끔하게 해결해준다

- Vault Agent가 Vault 인증을 대신 수행하기에 Application에서는 수정할 것이 최소화됨(TTL, 인증)
Agent 구성을 위해 Vault AppRole 인증 구성을 먼저합니다.
→ Approle이란 애플리케이션이 Vault에 접근할 때 쓸 수 있도록 만든 인증 메커니즘으로 쿠버네티스에서 Vault에 접근하기위해 구성합니다.

# 정책 생성
vault auth enable approle || echo "AppRole already enabled"
vault auth list
---
Success! Enabled approle auth method at: approle/
Path Type Accessor Description Version
---- ---- -------- ----------- -------
approle/ approle auth_approle_700b3381 n/a n/a
token/ token auth_token_98fb68f1 token based credentials n/a
# 위 생성한 Role 에 정책 연결
vault write auth/approle/role/sampleapp-role \
token_policies="sampleapp-policy" \
secret_id_ttl="1h" \
token_ttl="1h" \
token_max_ttl="4h"
# Role ID 및 Secret ID 추출 및 저장
ROLE_ID=$(vault read -field=role_id auth/approle/role/sampleapp-role/role-id)
SECRET_ID=$(vault write -f -field=secret_id auth/approle/role/sampleapp-role/secret-id)
echo "ROLE_ID: $ROLE_ID"
echo "SECRET_ID: $SECRET_ID"
# 접근 키 저장
mkdir -p approle-creds
echo "$ROLE_ID" > approle-creds/role_id.txt
echo "$SECRET_ID" > approle-creds/secret_id.txt
# 쿠버네티스 시크릿으로 저장(Agent 인증시 Approle 사용)
kubectl create secret generic vault-approle -n vault \
--from-literal=role_id="${ROLE_ID}" \
--from-literal=secret_id="${SECRET_ID}" \
--save-config \
--dry-run=client -o yaml | kubectl apply -f -
Vault Agent SideCar 연동
Vault Agent 구성은 Configmap 설정을 통해 연결할 정보(Vault의 정보와, Template 구성, 렌더링 주기, 참조할 Vault KV 위치정보)들을 정의합니다.
cat <
username: {{ with secret "secret/data/sampleapp/config" }}{{ .Data.data.username }}{{ end }}
password: {{ with secret "secret/data/sampleapp/config" }}{{ .Data.data.password }}{{ end }}
EOH
}
EOF
샘플 애플리케이션 배포
- Vault Agent 컨테이너를 별도 구성하여 주입(수동)
# Nginx + Vault Agent 생성
kubectl apply -n vault -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-vault-demo
spec:
replicas: 1
selector:
matchLabels:
app: nginx-vault-demo
template:
metadata:
labels:
app: nginx-vault-demo
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
volumeMounts:
- name: html-volume
mountPath: /usr/share/nginx/html
- name: vault-agent-sidecar
image: hashicorp/vault:latest
args:
- "agent"
- "-config=/etc/vault/agent-config.hcl"
volumeMounts:
- name: vault-agent-config
mountPath: /etc/vault
- name: vault-approle
mountPath: /etc/vault/approle
- name: vault-token
mountPath: /etc/vault-agent-token
- name: html-volume
mountPath: /etc/secrets
volumes:
- name: vault-agent-config
configMap:
name: vault-agent-config
- name: vault-approle
secret:
secretName: vault-approle
- name: vault-token
emptyDir: {}
- name: html-volume
emptyDir: {}
EOF
# SVC 생성
kubectl apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: NodePort
selector:
app: nginx-vault-demo
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30001 # Kind에서 설정한 Port
EOF
SideCar 확인
kubectl describe pod -l app=nginx-vault-demo
...
Containers:
nginx:
Container ID: containerd://c160c2268ce6d7602b718336b9036ae89646b5fdb7ebf310bed3dcf497b8675e
Image: nginx:latest
...
vault-agent-sidecar:
Container ID: containerd://6d7e37e8925e681d163b06ae7d18f5d3a236164a60ebf422abd4229a2e337e4e
Image: hashicorp/vault:latest
Image ID: docker.io/hashicorp/vault@sha256:ee674e47dcf85849aadf255b5341f76c0e1a474bc5fa9be9cdfff2a2edf9a628
Port:
Host Port:
Args:
agent
-config=/etc/vault/agent-config.hcl
...
# Agent 내 주입 정보 확인
kubectl exec -it -n vault deploy/nginx-vault-demo -c vault-agent-sidecar -- cat /etc/vault/agent-config.hcl
vault {
address = "http://vault.vault.svc:8200"
}
auto_auth {
method "approle" {
config = {
role_id_file_path = "/etc/vault/approle/role_id"
secret_id_file_path = "/etc/vault/approle/secret_id"
remove_secret_id_file_after_reading = false
}
}
sink "file" {
config = {
path = "/etc/vault-agent-token/token"
}
}
}
template_config {
static_secret_render_interval = "20s"
}
template {
destination = "/etc/secrets/index.html"
contents = <
username: {{ with secret "secret/data/sampleapp/config" }}{{ .Data.data.username }}{{ end }}
password: {{ with secret "secret/data/sampleapp/config" }}{{ .Data.data.password }}{{ end }}
EOH
- Annotation을 통한 자동 주입
# Kubernetes Auth Method 활성화
vault auth enable kubernetes
vault auth list
# Kubernetes Auth Config 설정 (최신 방식)
# Service Account관련 Secrets을 자동으로 생성하려면? - Helm Chart Values
TOKEN=$(kubectl create token vault -n vault)
CA_CERT=$(kubectl config view --raw --minify --flatten -o jsonpath='{.clusters[0].cluster.certificate-authority-data}' | base64 --decode)
vault write auth/kubernetes/config \
token_reviewer_jwt="$TOKEN" \
kubernetes_host="https://kubernetes.default.svc.cluster.local" \
kubernetes_ca_cert="$CA_CERT" \
issuer="https://kubernetes.default.svc.cluster.local" \
disable_iss_validation=false
# (앞선 과정에서 만들었으므로 생략가능) 필요한 Policy 작성
vault policy write sampleapp-policy - <
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
name: vault-ui-sa
namespace: vault
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: vault-injected-ui
namespace: vault
spec:
replicas: 1
selector:
matchLabels:
app: vault-injected-ui
template:
metadata:
labels:
app: vault-injected-ui
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "sampleapp-role"
vault.hashicorp.com/agent-inject-secret-config.json: "secret/data/sampleapp/config"
vault.hashicorp.com/agent-inject-template-config.json: |
{{- with secret "secret/data/sampleapp/config" -}}
{
"username": "{{ .Data.data.username }}",
"password": "{{ .Data.data.password }}"
}
{{- end }}
vault.hashicorp.com/agent-inject-output-path: "/vault/secrets"
spec:
serviceAccountName: vault-ui-sa
containers:
- name: app
image: python:3.10
ports:
- containerPort: 5000
command: ["sh", "-c"]
args:
- |
pip install flask && cat <<PYEOF > /app.py
import json, time
from flask import Flask, render_template_string
app = Flask(__name__)
while True:
try:
with open("/vault/secrets/config.json") as f:
secret = json.load(f)
break
except:
time.sleep(1)
@app.route("/")
def index():
return render_template_string("<h2>🔐 Vault Injected UI</h2><p>👤 사용자: {{username}}</p><p>🔑 비밀번호: {{password}}</p>", **secret)
app.run(host="0.0.0.0", port=5000)
PYEOF
python /app.py
---
apiVersion: v1
kind: Service
metadata:
name: vault-injected-ui
namespace: vault
spec:
type: NodePort
ports:
- port: 5000
targetPort: 5000
nodePort: 30002
selector:
app: vault-injected-ui
EOF
→ HELM 차트로 관리함에 있어 SideCar 주입이 어려움
Jenkins Vault 연동(AppRole)
Jenkins를 설치하고 Vault를 통해 시크릿 관리 연동 진행
#
kubectl create ns jenkins
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: jenkins-pvc
namespace: jenkins
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: jenkins
namespace: jenkins
spec:
replicas: 1
selector:
matchLabels:
app: jenkins
template:
metadata:
labels:
app: jenkins
spec:
securityContext:
fsGroup: 1000
containers:
- name: jenkins
image: jenkins/jenkins:lts
ports:
- name: http
containerPort: 8080
- name: agent
containerPort: 50000
livenessProbe:
httpGet:
path: "/login"
port: 8080
initialDelaySeconds: 90
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 5
readinessProbe:
httpGet:
path: "/login"
port: 8080
initialDelaySeconds: 60
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
volumeMounts:
- name: jenkins-home
mountPath: /var/jenkins_home
volumes:
- name: jenkins-home
persistentVolumeClaim:
claimName: jenkins-pvc
---
apiVersion: v1
kind: Service
metadata:
name: jenkins-svc
namespace: jenkins
spec:
type: NodePort
selector:
app: jenkins
ports:
- nodePort: 30001
port: 8080
targetPort: http
protocol: TCP
name: http
- port: 50000
targetPort: agent
protocol: TCP
name: agent
EOF
# 확인
kubectl get deploy,svc,ep,pvc -n jenkins
# 초기 암호 확인
kubectl exec -it -n jenkins deploy/jenkins -- cat /var/jenkins_home/secrets/initialAdminPassword
9b80701c83294ddc848426bee270f139
# 웹 접속 : 기본 설정 진행
open "http://127.0.0.1:30001"
- Customize Jenkins : Install suggested plugins 클릭 후 설치
- 관리자 계정 설정 : admin / qwe123
- Jenkins에서 Vault Plugin 설치
Jenkins 내 Approle 설정
# 이전 생성한 크리덴셜 확인
vault read auth/approle/role/sampleapp-role/role-id
vault write -f auth/approle/role/sampleapp-role/secret-id
Key Value
--- -----
role_id dc9207f1-e57e-5629-b34a-38964e7b3a18
Key Value
--- -----
secret_id e6b5cab4-6b9e-f105-72a4-780236481264
secret_id_accessor 2c6feb2e-324b-5200-99db-ed4060264700
secret_id_num_uses 0
secret_id_ttl 1h
Jenkins 내 Vault 등록
- 종류: Vault AppRole Credential
- Role ID & Secret ID 입력 → 생성해놓은 변수 또는 파일참고
- ID는 기억하기 쉬운 이름으로 지정 (vault-approle-creds 등)


Jenkins Vault 테스트
Jenkins PipeLine 생성 (이름 : jenkins-vault-kv)
pipeline {
agent any
environment {
VAULT_ADDR = 'http://vault.vault.svc:820' }
stages {
stage('Read Vault Secret') {
steps {
withVault([
vaultSecrets: [
[
path: 'secret/sampleapp/config',
engineVersion: 2,
secretValues: [
[envVar: 'USERNAME', vaultKey: 'username'],
[envVar: 'PASSWORD', vaultKey: 'password']
]
]
],
configuration: [
vaultUrl: "${VAULT_ADDR}",
vaultCredentialId: 'vault-approle-creds'
]
]) {
sh '''
echo "Username from Vault: $USERNAME"
echo "Password from Vault: $PASSWORD"
'''
script {
echo "Username (env): ${env.USERNAME}"
echo "Password (env): ${env.PASSWORD}"
}
}
}
}
}
}
- KV Version1은 경로에 data을 넣고 Version2는 경로에 data을 넣지 않는다.

Vault Dynamic Secret 구성
요청 시 즉시 발급되고, TTL이 지나면 자동으로 사라지는 단기(Short-lived) 인증 정보
→ 하지만 현실적으로 실제 동적 시크릿 로직을 구현하기 위해서 고려해야 할 사항이 많지만, Vault에서 지원 가능
인프라 구성(PostgreSQL)
# postgres-deploy.yaml
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
namespace: default
spec:
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:13
env:
- name: POSTGRES_PASSWORD
value: "rootpassword"
- name: POSTGRES_DB
value: "mydb"
ports:
- containerPort: 5432
---
apiVersion: v1
kind: Service
metadata:
name: postgres
namespace: default
spec:
type: NodePort
ports:
- port: 5432
targetPort: 5432
nodePort: 30002 # [External] Jenkins 접속용
selector:
app: postgres
EOF
Vault DB 엔진 구성 & AppRole 권한 확장
- 관리자 권한을 가지고 요청시 임시 유저 설정
# (로컬 터미널에서 수행)
export VAULT_ADDR=http://127.0.0.1:30000
export VAULT_TOKEN=root
# 1. Database Secret Engine 활성화
vault secrets enable database
vault secrets list
# 2. Vault -> Postgres 연결 설정
# (Vault와 DB는 같은 K8s 안에 있으므로 내부 DNS 사용)
vault write database/config/my-postgresql-database \
plugin_name=postgresql-database-plugin \
allowed_roles="jenkins-role" \
connection_url="postgresql://{{username}}:{{password}}@postgres.default.svc.cluster.local:5432/mydb?sslmode=disable" \
username="postgres" \
password="rootpassword"
# 3. "1시간짜리 임시 계정" 생성 규칙 정의 (DB Role)
# 주의: Vault 내부의 Role이 아니라, DB 엔진용 Role입니다.
vault write database/roles/jenkins-role \
db_name=my-postgresql-database \
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"
# 기존 KV 권한 + 새로운 DB 권한(database/creds/jenkins-role) 병합
vault policy write sampleapp-policy - <<EOF
# 1. KV v2 데이터 읽기
path "secret/data/sampleapp/*" {
capabilities = ["read"]
}
# 2. KV v2 목록 조회 (플러그인 에러 방지용 필수!)
path "secret/metadata/sampleapp/*" {
capabilities = ["list", "read"]
}
# 3. DB Creds 발급
path "database/creds/jenkins-role" {
capabilities = ["read"]
}
EOF
# 업데이트된 Policy 확인 (위 내용과 동일한지 확인)
vault policy read sampleapp-policy
# 관리자 로그인 상태에서 실행. token polices에 default도 함께추가
vault write auth/approle/role/sampleapp-role \
token_policies="default,sampleapp-policy" \
secret_id_ttl="0" \
token_ttl="1h" \
token_max_ttl="4h"
Jenkin 테스트
- KV 엔진을 1로 명시해야함
pipeline {
agent any
environment {
// Jenkins(Docker) -> Vault(K8s NodePort)
// 주의: http:// 가 포함된 전체 주소
// Jenkins 파드 사용 시 : http://vault.vault.svc:8200
VAULT_ADDR = 'http://vault.vault.svc:8200'
// Jenkins(Docker) -> DB(K8s NodePort)
// 주의: DB 접속에는 프로토콜(http://) 없이 IP만 필요합니다.
// Jenkins 파드 사용 시 : DB_HOST = 'postgres.default.svc' , DB_PORT = '5432'
DB_HOST = 'postgres.default.svc'
DB_PORT = '5432'
}
stages {
stage('Vault 통합 및 DB 접속 테스트') {
steps {
withVault([
configuration: [
vaultUrl: "${VAULT_ADDR}",
vaultCredentialId: 'vault-approle-creds',
// ⚠️ 중요: 여기서 전역 engineVersion 설정을 하지 않습니다.
skipSslVerification: true
],
vaultSecrets: [
// 1. KV Secret (정적 시크릿)
// KV v2 엔진을 사용하므로 engineVersion: 2를 명시합니다.
[
path: 'secret/sampleapp/config',
engineVersion: 2,
secretValues: [
[envVar: 'STATIC_USER', vaultKey: 'username']
]
],
// 2. Database Secret (동적 시크릿)
// DB 엔진은 기본 방식(v1)으로 통신해야 경로 에러가 없습니다.
[
path: 'database/creds/jenkins-role',
engineVersion: 1,
secretValues: [
[envVar: 'DB_USER', vaultKey: 'username'],
[envVar: 'DB_PASS', vaultKey: 'password']
]
]
]
]) {
script {
echo "=================================================="
echo " Vault 연동 테스트 시작 "
echo "=================================================="
// 1. 정적 시크릿 확인
// sed 명령어로 글자 사이에 공백을 넣어 마스킹(****)을 우회합니다.
// 예: d e m o
sh '''
echo "[1] KV Secret (Static)"
echo " - 원본 값은 보안상 **** 로 표시됩니다."
echo " - 실제 값 확인: $(echo $STATIC_USER | sed "s/./& /g")"
'''
// 2. 동적 시크릿 확인 (핵심!)
// Vault가 생성한 임시 DB 계정(v-token-...)을 확인합니다.
sh '''
echo "--------------------------------------------------"
echo "[2] Database Secret (Dynamic)"
echo " - Vault가 생성한 임시 계정 ID입니다."
echo " - 실제 값 확인: $(echo $DB_USER | sed "s/./& /g")"
echo "--------------------------------------------------"
'''
// 3. DB 접속 시뮬레이션
// 실제 애플리케이션에서 DB 연결 문자열을 만드는 과정입니다.
sh '''
echo "[3] DB Connection Simulation"
echo " - Connecting to: ${DB_HOST}:${DB_PORT}"
echo " - User: ${DB_USER}"
echo " - Password: (Hidden)"
echo " >> ✅ DB 접속 테스트 성공! (가상)"
'''
}
}
}
}
}
post {
success {
script {
echo "🎉 Pipeline 성공!"
echo " -> 확인된 DB 계정(${env.DB_USER})은 Vault의 TTL 설정에 따라 1시간 후 자동 삭제됩니다."
}
}
failure {
echo "💥 Pipeline 실패! Vault 로그나 네트워크 설정을 확인하세요."
}
}
}

kubectl exec -it -n default deploy/postgres -- psql -U postgres
\du
Role name | Attributes | Member of
----------------------------------------------------+------------------------------------------------------------+-----------
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
v-approle-jenkins--1zRpViME96NtQ4Xzqtjn-1764420933 | Password valid until 2025-11-29 13:55:38+00 | {}
'Cloud' 카테고리의 다른 글
| Vault VSO 맛보기 (0) | 2025.12.07 |
|---|---|
| KeyCloak SSO 실습 (0) | 2025.11.23 |
| ArgoCD로 멀티클러스터 관리하기 (0) | 2025.11.23 |
| ArgoCD 접근제어 설정 방법 (0) | 2025.11.16 |
| ArgoCD 정리 (1) (0) | 2025.11.08 |