界面已本地化;技能介绍与说明文档按所选语言由 AI 自动翻译,代码、命令、路径和专业术语保留原文,以原作者文档为准。
探索技能
部署与运维 · SKILL.md

implementing-secrets-management-with-vault

implementing-secrets-management-with-vault

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

独立 GitHub 快照 · 自动分类 · 以原作者文档为准

技能说明

GitHub

name: implementing-secrets-management-with-vault description: > 本技能涵盖在云环境中部署 HashiCorp Vault 进行集中式密钥管理,包括为数据库和云提供商生成动态密钥、传输加密(Transit Encryption)、PKI 证书管理以及 Kubernetes 集成。通过实现短生命周期、自动轮换的密钥,解决应用代码和 CI/CD 流水线中硬编码凭据的问题。 domain: cybersecurity subdomain: cloud-security tags: [hashicorp-vault, secrets-management, dynamic-secrets, credential-rotation, zero-trust] version: 1.0.0 author: mahipal license: Apache-2.0

使用 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)。

# 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
}
# 初始化 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 进行人工访问。

# 通过 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,到期后自动撤销。

# 为 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。密钥以文件形式渲染到共享卷中。

# 带 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 证书自动管理。

# 启用 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 策略。为所有密钥访问和管理操作启用全面的审计日志。

# 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"]
}
# 应用策略
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
我的收藏