# Implementing Secrets Management With Vault

> 本技能涵盖在云环境中部署 HashiCorp Vault 进行集中式密钥管理，包括为数据库和云提供商生成动态密钥、传输加密（Transit Encryption）、PKI 证书管理以及 Kubernetes 集成。通过实现短生命周期、自动轮换的密钥，解决应用代码和 CI/CD 流水线中硬编码凭据的问题。

- Skill: `killvxk/implementing-secrets-management-with-vault` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add killvxk/implementing-secrets-management-with-vault`
- Raw SKILL.md: https://api.skillmd.com/api/skills/killvxk/implementing-secrets-management-with-vault/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- License: Apache-2.0
- Author: killvxk (https://skillmd.com/u/killvxk)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/killvxk/implementing-secrets-management-with-vault

---


# 使用 Vault 实施密钥管理

## 适用场景

- 应用程序将数据库密码、API 密钥或证书存储在环境变量或配置文件中时
- 从静态长期凭据迁移到动态短期密钥时
- Kubernetes 工作负载需要安全访问数据库凭据或云提供商 API 时
- 合规要求强制进行集中凭据管理并具备审计日志时
- CI/CD 流水线中包含代表供应链风险（Supply Chain Attack）的硬编码密钥时

**不适用于**：纯 AWS 环境（AWS Secrets Manager 已足够且无多云需求）、应用层加密逻辑（尽管 Vault Transit 可辅助实现），或身份联合（Identity Federation）场景（参见 managing-cloud-identity-with-okta）。

## 前置条件

- 以高可用（HA）模式部署的 HashiCorp Vault 服务器（Consul 或 Raft 存储后端）
- 用于 Vault 监听端点的 TLS 证书
- Vault Enterprise 许可证（用于命名空间、Sentinel 策略和复制，可选）
- 已集成 Vault Agent Injector 或 CSI 提供程序的 Kubernetes 集群（用于工作负载集成）

## 工作流程

### 步骤 1：以高可用模式部署 Vault

使用集成存储（Raft）部署 Vault，无需外部依赖即可实现 HA。配置 TLS、审计日志以及基于云 KMS 的自动解封（Auto-Unseal）。

```hcl
# vault-config.hcl
storage "raft" {
  path    = "/opt/vault/data"
  node_id = "vault-node-1"

  retry_join {
    leader_api_addr = "https://vault-node-2.internal:8200"
  }
  retry_join {
    leader_api_addr = "https://vault-node-3.internal:8200"
  }
}

listener "tcp" {
  address     = "0.0.0.0:8200"
  tls_cert_file = "/opt/vault/tls/vault.crt"
  tls_key_file  = "/opt/vault/tls/vault.key"
}

seal "awskms" {
  region     = "us-east-1"
  kms_key_id = "alias/vault-unseal-key"
}

api_addr      = "https://vault-node-1.internal:8200"
cluster_addr  = "https://vault-node-1.internal:8201"

telemetry {
  prometheus_retention_time = "30s"
  disable_hostname         = true
}
```

```bash
# 初始化 Vault
vault operator init -key-shares=5 -key-threshold=3

# 启用审计日志
vault audit enable file file_path=/var/log/vault/audit.log

# 启用 syslog 审计以集成 SIEM
vault audit enable syslog tag="vault" facility="AUTH"
```

### 步骤 2：配置认证方法

为人工操作员、应用程序和 CI/CD 流水线启用认证后端。使用 AppRole 进行机器认证，使用 OIDC 进行人工访问。

```bash
# 通过 Okta 为人工用户启用 OIDC 认证
vault auth enable oidc
vault write auth/oidc/config \
  oidc_discovery_url="https://company.okta.com/oauth2/default" \
  oidc_client_id="vault-client-id" \
  oidc_client_secret="vault-client-secret" \
  default_role="default"

# 为应用程序认证启用 AppRole
vault auth enable approle
vault write auth/approle/role/web-app \
  secret_id_ttl=10m \
  token_num_uses=10 \
  token_ttl=20m \
  token_max_ttl=30m \
  secret_id_num_uses=1 \
  token_policies="web-app-policy"

# 为 Pod 访问启用 Kubernetes 认证
vault auth enable kubernetes
vault write auth/kubernetes/config \
  kubernetes_host="https://kubernetes.default.svc:443" \
  token_reviewer_jwt=@/var/run/secrets/kubernetes.io/serviceaccount/token \
  kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
```

### 步骤 3：启用动态密钥引擎

配置数据库密钥引擎，按需生成短期凭据。每组凭据都有 TTL，到期后自动撤销。

```bash
# 为 PostgreSQL 启用数据库密钥引擎
vault secrets enable database
vault write database/config/production-db \
  plugin_name=postgresql-database-plugin \
  allowed_roles="readonly,readwrite" \
  connection_url="postgresql://{{username}}:{{password}}@db.internal:5432/production?sslmode=require" \
  username="vault_admin" \
  password="initial-password"

# 轮换根凭据，使 Vault 独占管理
vault write -force database/rotate-root/production-db

# 创建 TTL 为 1 小时的只读角色
vault write database/roles/readonly \
  db_name=production-db \
  creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
  revocation_statements="REVOKE ALL ON ALL TABLES IN SCHEMA public FROM \"{{name}}\"; DROP ROLE IF EXISTS \"{{name}}\";" \
  default_ttl="1h" \
  max_ttl="24h"

# 启用 AWS 密钥引擎以动态生成 IAM 凭据
vault secrets enable aws
vault write aws/config/root \
  access_key=AKIAEXAMPLE \
  secret_key=secretkey \
  region=us-east-1

vault write aws/roles/deploy-role \
  credential_type=iam_user \
  policy_document=@deploy-policy.json \
  default_sts_ttl=3600
```

### 步骤 4：与 Kubernetes 工作负载集成

使用 Vault Agent Injector 或 CSI Provider，无需修改应用代码即可将密钥传递给 Pod。密钥以文件形式渲染到共享卷中。

```yaml
# 带 Vault Agent Injector 注解的 Kubernetes Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  template:
    metadata:
      annotations:
        vault.hashicorp.com/agent-inject: "true"
        vault.hashicorp.com/role: "web-app"
        vault.hashicorp.com/agent-inject-secret-db-creds: "database/creds/readonly"
        vault.hashicorp.com/agent-inject-template-db-creds: |
          {{- with secret "database/creds/readonly" -}}
          export DB_USERNAME="{{ .Data.username }}"
          export DB_PASSWORD="{{ .Data.password }}"
          {{- end }}
    spec:
      serviceAccountName: web-app
      containers:
        - name: web-app
          image: company/web-app:v2.1
          command: ["/bin/sh", "-c", "source /vault/secrets/db-creds && ./start.sh"]
```

### 步骤 5：实施传输加密和 PKI

使用 Transit 密钥引擎实现应用层加密即服务，无需在应用代码中管理密钥。部署 PKI 引擎进行 TLS 证书自动管理。

```bash
# 启用 Transit 引擎实现加密即服务
vault secrets enable transit
vault write -f transit/keys/payment-data type=aes256-gcm96

# 加密敏感数据
vault write transit/encrypt/payment-data \
  plaintext=$(echo "card-number-4111-1111-1111-1111" | base64)

# 启用 PKI 进行内部证书管理
vault secrets enable pki
vault secrets tune -max-lease-ttl=87600h pki

# 生成根 CA
vault write pki/root/generate/internal \
  common_name="Internal Root CA" \
  ttl=87600h

# 配置中间 CA 用于签发证书
vault secrets enable -path=pki_int pki
vault write pki_int/intermediate/generate/internal \
  common_name="Internal Intermediate CA" \
  ttl=43800h

# 创建证书签发角色
vault write pki_int/roles/internal-services \
  allowed_domains="internal.company.com" \
  allow_subdomains=true \
  max_ttl=720h
```

### 步骤 6：建立策略和审计追踪

按最小权限原则定义细粒度 ACL 策略。为所有密钥访问和管理操作启用全面的审计日志。

```hcl
# web-app-policy.hcl
path "database/creds/readonly" {
  capabilities = ["read"]
}

path "transit/encrypt/payment-data" {
  capabilities = ["update"]
}

path "transit/decrypt/payment-data" {
  capabilities = ["update"]
}

path "secret/data/web-app/*" {
  capabilities = ["read", "list"]
}

# 禁止访问管理路径
path "sys/*" {
  capabilities = ["deny"]
}
```

```bash
# 应用策略
vault policy write web-app-policy web-app-policy.hcl

# 验证审计日志捕获所有操作
vault audit list -detailed
```

## 核心概念

| 术语 | 定义 |
|------|------|
| 动态密钥（Dynamic Secrets） | 按需生成并自动到期撤销的凭据，消除了长期静态凭据 |
| 密钥引擎（Secret Engine） | 存储、生成或加密数据的 Vault 组件；包括 KV、database、AWS、PKI 和 Transit 引擎 |
| 自动解封（Auto-Unseal） | 基于云 KMS 的机制，重启时自动解封 Vault 节点，无需手动输入密钥 |
| AppRole | 面向机器的认证方法，使用 Role ID 和 Secret ID 供应用程序和 CI/CD 流水线访问 |
| Transit 引擎（Transit Engine） | 加密即服务引擎，处理加密操作而不向应用程序暴露加密密钥 |
| 租约（Lease） | 带有 TTL 的时限凭据，到期后 Vault 自动撤销，除非续期 |
| 命名空间（Namespace） | Vault Enterprise 功能，提供独立的认证、密钥和策略管理的租户隔离 |
| 响应封装（Response Wrapping） | 将密钥响应封装在一次性令牌中的技术，防止传输过程中的中间人攻击暴露 |

## 工具与系统

- **HashiCorp Vault**：核心密钥管理平台，提供动态密钥、加密和基于身份的访问控制
- **Vault Agent Injector**：Kubernetes 变更性 Webhook，通过边车容器自动将 Vault 密钥注入 Pod 卷
- **Vault CSI Provider**：Kubernetes CSI 驱动程序，无需边车容器即可将 Vault 密钥直接挂载到 Pod 卷
- **consul-template**：模板渲染守护进程，监视 Vault 密钥并在密钥变更时重新渲染配置文件
- **Vault Radar**：密钥扫描工具，检测源代码、CI/CD 流水线和云配置中的硬编码凭据

## 常见场景

### 场景：消除 CI/CD 流水线中的硬编码数据库凭据

**场景背景**：DevOps 团队将 PostgreSQL 凭据存储在 GitHub Actions 密钥和 Jenkins 凭据存储中。同一组凭据在测试和生产环境中共用，18 个月未进行轮换。

**方法**：
1. 部署 Vault 并为 CI/CD 系统启用 AppRole 认证
2. 配置数据库密钥引擎，为测试（readwrite，TTL 2h）和生产（readonly，TTL 1h）分别设置角色
3. 为每个流水线阶段创建独立的 Vault 策略，限制对相应数据库角色的访问
4. 更新 GitHub Actions 工作流，在每个作业开始时通过 AppRole 认证并请求动态凭据
5. 轮换静态 PostgreSQL 凭据，将根访问权限独占交给 Vault
6. 启用审计日志，追踪每次凭据请求及流水线作业元数据

**常见陷阱**：Vault 迁移后未轮换原始静态凭据，导致旧凭据仍然有效。TTL 设置过短导致长时间运行的作业在部署过程中凭据过期。

## 输出格式

```
Vault 密钥管理审计报告
=======================================
Vault 集群: vault.internal.company.com
版本: 1.18.1 Enterprise
HA 模式: Raft (3 节点)
封印类型: AWS KMS 自动解封
报告日期: 2025-02-23

密钥引擎:
  database/         PostgreSQL 动态凭据   活跃租约: 47
  aws/              动态 IAM 凭据         活跃租约: 12
  transit/          加密即服务            密钥数: 8
  pki/              根 CA                已签发证书: 0
  pki_int/          中间 CA              已签发证书: 234
  secret/           KV v2 静态密钥        版本数: 1,892

认证方法:
  oidc/             Okta SSO（人工用户）  活跃令牌: 23
  approle/          CI/CD 流水线          活跃令牌: 156
  kubernetes/       基于 Pod 的认证       活跃令牌: 89

审计发现:
  [WARN] 3 个 AppRole 的 secret_id_num_uses 设为 0（无限制）
  [WARN] 12 个 KV 密钥超过 90 天未访问（潜在孤儿密钥）
  [PASS] 所有动态密钥 TTL 均低于 24 小时
  [PASS] 所有节点已启用审计日志
  [PASS] 初始设置后根令牌已撤销

凭据卫生:
  静态密钥 (KV): 234
  活跃动态密钥: 59
  平均租约 TTL: 2.3 小时
  本月已轮换密钥数: 12,456
```

