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 sealed | Vault 处于封印状态 | 运行 vault operator unseal 解封 |
permission denied | Token 权限不足 | 检查关联的 Policy |
lease not found | 租约已过期 | 重新获取密钥 |
secret not found | 密钥路径不存在 | 检查路径是否正确(注意 kv/data/ 前缀) |
token expired | Token 已过期 | 重新登录或续约 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 → 集群通信
同类对比
| 特性 | Vault | AWS Secrets Manager | SOPS | Sealed Secrets |
|---|
| 部署方式 | 自托管/云 | AWS 托管 | CLI 工具 | K8s 控制器 |
| 动态密钥 | 完整支持 | 有限 | 无 | 无 |
| PKI/证书 | 内置 | ACM | 无 | 无 |
| 多云 | 是 | 仅 AWS | 是 | 仅 K8s |
| 审计日志 | 完整 | CloudTrail | 无 | 无 |
| 学习曲线 | 高 | 低 | 低 | 低 |
| 适合场景 | 企业级 | AWS 原生 | 小团队 | K8s 专用 |
选型建议:企业级密钥管理首选 Vault(功能最全、多云支持);纯 AWS 环境用 Secrets Manager(零运维);小团队快速加密配置文件用 SOPS;K8s 中简单加密 Secret 用 Sealed Secrets。