跳转至

598_Vault密钥管理

一句话概述:HashiCorp Vault 是业界标准的密钥管理工具,集中管理 API Key、数据库密码、TLS 证书等敏感数据,支持动态密钥生成、自动轮换、细粒度访问控制和审计日志,解决"密码写在配置文件里"的安全隐患。

核心知识点表

概念白话解释
Secret Engine密钥引擎,不同类型密钥的存储和管理后端
KV Store键值存储,最简单的密钥引擎(存静态密钥)
Dynamic Secret动态密钥,按需生成的临时密钥(如临时数据库密码)
Auth Method认证方式,验证"你是谁"(Token/LDAP/K8s/GitHub)
Policy策略,定义"你能访问什么"(RBAC 权限)
Seal/Unseal封印/解封,Vault 启动后需要解封才能使用
Lease租约,密钥的有效期(过期自动失效)

安装配置

安装 Vault

# macOS
brew install vault                       # Homebrew 安装

# Ubuntu/Debian
wget -O - https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install vault

# Docker
docker run -d --name vault \
  -p 8200:8200 \                        # Web UI 和 API 端口
  --cap-add=IPC_LOCK \                  # 防止内存被交换到磁盘
  -e 'VAULT_DEV_ROOT_TOKEN_ID=myroot' \ # 开发模式 Root Token
  hashicorp/vault:latest server -dev    # 开发模式启动

# 验证安装
vault version                            # 查看版本(当前 v2.0)

开发模式(学习用)

# 启动开发服务器(数据存内存,重启丢失)
vault server -dev                        # 开发模式
# 自动解封,Root Token 显示在终端

# 设置环境变量
export VAULT_ADDR='http://127.0.0.1:8200'   # Vault 地址
export VAULT_TOKEN='hvs.xxxxx'               # Root Token
# 访问 http://127.0.0.1:8200/ui 查看 Web UI

生产模式部署

# config.hcl — Vault 生产配置
storage "raft" {                         # 使用 Raft 存储后端
  path    = "/opt/vault/data"            # 数据路径
  node_id = "vault-1"                    # 节点 ID
}

listener "tcp" {
  address     = "0.0.0.0:8200"          # 监听地址
  tls_cert_file = "/opt/vault/tls/tls.crt"  # TLS 证书
  tls_key_file  = "/opt/vault/tls/tls.key"  # TLS 私钥
}

api_addr = "https://vault.example.com:8200"  # 外部 API 地址
cluster_addr = "https://vault.example.com:8201"  # 集群通信地址
ui = true                               # 启用 Web UI
# 启动生产模式
vault server -config=config.hcl          # 使用配置文件启动

# 初始化(首次启动)
vault operator init                      # 生成 5 个 Unseal Key + 1 个 Root Token
# 输出 5 个 Unseal Key(解封密钥)和 1 个 Root Token
# 务必安全保存!丢失则无法恢复

# 解封(需要 3 个 Unseal Key)
vault operator unseal KEY_1              # 第 1 个 Key
vault operator unseal KEY_2              # 第 2 个 Key
vault operator unseal KEY_3              # 第 3 个 Key
# Sealed: false → 解封成功

基本使用

KV 密钥存储

# === KV v2(推荐,支持版本管理) ===

# 启用 KV v2 引擎
vault secrets enable -version=2 kv       # 启用 kv 路径

# 写入密钥
vault kv put kv/myapp/config \
  db_host="db.example.com" \            # 数据库地址
  db_user="admin" \                     # 数据库用户名
  db_pass="super-secret-123"            # 数据库密码

# 读取密钥
vault kv get kv/myapp/config             # 读取所有字段
vault kv get -field=db_pass kv/myapp/config  # 读取单个字段

# 读取 JSON 格式
vault kv get -format=json kv/myapp/config  # JSON 输出

# 更新密钥(会创建新版本)
vault kv put kv/myapp/config \
  db_pass="new-password-456"            # 更新密码

# 查看版本历史
vault kv metadata get kv/myapp/config    # 查看元数据
vault kv get -version=1 kv/myapp/config  # 读取版本 1

# 删除密钥
vault kv delete kv/myapp/config          # 软删除(可恢复)
vault kv destroy -versions=1 kv/myapp/config  # 永久删除版本 1

认证方式

# === Token 认证(默认) ===
vault token create -ttl=1h              # 创建 1 小时有效的 Token
vault login TOKEN                        # 使用 Token 登录

# === AppRole 认证(应用程序推荐) ===
vault auth enable approle                # 启用 AppRole

# 创建 Role
vault write auth/approle/role/myapp \
  token_policies="myapp-policy" \        # 关联策略
  token_ttl=1h \                         # Token 有效期
  token_max_ttl=4h                       # Token 最大有效期

# 获取 RoleID 和 SecretID
vault read auth/approle/role/myapp/role-id    # 获取 RoleID
vault write -f auth/approle/role/myapp/secret-id  # 生成 SecretID

# 应用使用 RoleID + SecretID 登录
vault write auth/approle/login \
  role_id="ROLE_ID" \
  secret_id="SECRET_ID"                 # 返回 Token

# === Kubernetes 认证 ===
vault auth enable kubernetes             # 启用 K8s 认证
# Pod 中的应用使用 ServiceAccount Token 自动认证

策略管理(RBAC)

# myapp-policy.hcl — 策略文件
# 允许读取 myapp 的密钥
path "kv/data/myapp/*" {
  capabilities = ["read", "list"]        # 只读权限
}

# 禁止访问其他路径
path "kv/data/production/*" {
  capabilities = ["deny"]               # 拒绝访问
}

# 允许管理自己的 Token
path "auth/token/renew-self" {
  capabilities = ["update"]             # 允许续约 Token
}
# 创建策略
vault policy write myapp-policy myapp-policy.hcl

# 查看策略
vault policy list                        # 列出所有策略
vault policy read myapp-policy           # 查看策略内容

# 创建关联策略的 Token
vault token create -policy=myapp-policy  # 创建受限 Token

高级用法

动态数据库密钥

# 场景:每次请求生成临时数据库密码,过期自动失效

# 1. 启用数据库引擎
vault secrets enable database            # 启用

# 2. 配置数据库连接
vault write database/config/mydb \
  plugin_name=mysql-database-plugin \    # MySQL 插件
  connection_url="{{username}}:{{password}}@tcp(db:3306)/" \
  allowed_roles="readonly" \             # 允许的角色
  username="vault-admin" \               # 管理员用户名
  password="vault-admin-pass"            # 管理员密码

# 3. 创建角色(定义临时用户的权限)
vault write database/roles/readonly \
  db_name=mydb \                         # 关联数据库
  creation_statements="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}'; GRANT SELECT ON *.* TO '{{name}}'@'%';" \
  default_ttl="1h" \                     # 默认 1 小时有效
  max_ttl="24h"                          # 最大 24 小时

# 4. 获取临时密钥
vault read database/creds/readonly       # 生成临时用户名和密码
# username: v-approle-readonly-abc123
# password: random-generated-password
# 1 小时后自动删除该用户

PKI 证书管理

# 自动签发和管理 TLS 证书

# 1. 启用 PKI 引擎
vault secrets enable pki                 # 启用

# 2. 生成根 CA
vault write pki/root/generate/internal \
  common_name="My Root CA" \             # CA 名称
  ttl=87600h                             # 10 年有效期

# 3. 创建角色
vault write pki/roles/web-server \
  allowed_domains="example.com" \        # 允许的域名
  allow_subdomains=true \                # 允许子域名
  max_ttl="720h"                         # 证书最长 30 天

# 4. 签发证书
vault write pki/issue/web-server \
  common_name="app.example.com" \        # 证书域名
  ttl="72h"                              # 3 天有效
# 返回:证书、私钥、CA 链

应用集成示例

# Python 应用读取 Vault 密钥
import hvac                              # pip install hvac

client = hvac.Client(
    url='https://vault.example.com:8200',  # Vault 地址
    token='hvs.xxxxx'                      # Token(生产环境不要硬编码)
)

# 读取密钥
secret = client.secrets.kv.v2.read_secret_version(
    path='myapp/config'                    # 密钥路径
)
db_pass = secret['data']['data']['db_pass']  # 获取密码
print(f"数据库密码: {db_pass}")

常见报错

报错信息原因解决方案
Vault is sealedVault 处于封印状态运行 vault operator unseal 解封
permission deniedToken 权限不足检查关联的 Policy
lease not found租约已过期重新获取密钥
secret not found密钥路径不存在检查路径是否正确(注意 kv/data/ 前缀)
token expiredToken 已过期重新登录或续约 Token

速查表

# === 密钥操作 ===
vault kv put PATH KEY=VALUE     # 写入密钥
vault kv get PATH               # 读取密钥
vault kv delete PATH            # 删除密钥
vault kv list PATH              # 列出密钥

# === 认证 ===
vault login TOKEN               # Token 登录
vault token create              # 创建 Token
vault token renew               # 续约 Token
vault token revoke TOKEN        # 吊销 Token

# === 管理 ===
vault operator init             # 初始化
vault operator unseal KEY       # 解封
vault operator seal             # 封印
vault status                    # 状态
vault secrets list              # 列出密钥引擎
vault auth list                 # 列出认证方式

# === 策略 ===
vault policy write NAME FILE    # 创建策略
vault policy list               # 列出策略
vault policy read NAME          # 查看策略

# === 关键端口 ===
# 8200 → API 和 Web UI
# 8201 → 集群通信

同类对比

特性VaultAWS Secrets ManagerSOPSSealed Secrets
部署方式自托管/云AWS 托管CLI 工具K8s 控制器
动态密钥完整支持有限
PKI/证书内置ACM
多云仅 AWS仅 K8s
审计日志完整CloudTrail
学习曲线
适合场景企业级AWS 原生小团队K8s 专用

选型建议:企业级密钥管理首选 Vault(功能最全、多云支持);纯 AWS 环境用 Secrets Manager(零运维);小团队快速加密配置文件用 SOPS;K8s 中简单加密 Secret 用 Sealed Secrets。