适用场景
Vault 密钥管理适用于需要统一管理数据库密码、API 令牌、SSH 密钥等敏感凭证的团队。传统做法把密码明文写在配置文件中,一旦服务器被入侵,攻击者可直接读取全部凭证。Vault 密钥管理方案将凭证集中存储在加密后端,通过策略控制谁能读、何时能读,并支持生成临时动态密钥,适用于中小型企业的多台服务器、数据库与 CI/CD 流水线场景。
前置条件
- 一台 Linux 服务器(本文以 Ubuntu 22.04 为例),内存不低于 1GB
- root 或 sudo 权限
- 已安装 curl、unzip 等基础工具
- 可访问外网以下载 Vault 二进制包
原理说明
Vault 的核心思想是”集中存储 + 策略隔离 + 动态下发”。所有机密写入后端存储(开发模式为内存,生产推荐 Consul 或 Raft),写入前经过 Seal 机制用主密钥加密;读取时必须解封(Unseal)。策略(Policy)使用 HCL 语法描述路径权限,配合认证方式(Token、AppRole、Kubernetes 等)实现最小权限访问。数据库引擎可为 MySQL、PostgreSQL 生成临时只读账号,到期自动吊销,杜绝静态密码长期有效带来的泄露风险。
操作步骤
1. 安装与启动 Vault
# 下载 Vault 1.15 版本并解压到 /usr/local/bin
wget https://releases.hashicorp.com/vault/1.15.6/vault_1.15.6_linux_amd64.zip
unzip vault_1.15.6_linux_amd64.zip -d /usr/local/bin/
vault version
# 创建数据目录并写入最小配置
mkdir -p /etc/vault /opt/vault/data
cat > /etc/vault/config.hcl <<'EOF'
storage "raft" {
path = "/opt/vault/data"
node_id = "node1"
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_disable = 1
}
api_addr = "http://127.0.0.1:8200"
cluster_addr = "https://127.0.0.1:8201"
ui = true
EOF
# 启动 Vault 服务
nohup vault server -config=/etc/vault/config.hcl > /var/log/vault.log 2>&1 &
export VAULT_ADDR='http://127.0.0.1:8200'
vault status
首次启动输出 “Sealed” 状态属正常,需要执行初始化生成根令牌与 5 个解封密钥分片。
2. 初始化与解封
vault operator init -key-shares=5 -key-threshold=3
# 输出 Unseal Key 1-5 与 Initial Root Token,务必安全保存
# 解封 3 次(阈值),每次输入一个 Unseal Key
vault operator unseal
vault operator unseal
vault operator unseal
vault status # Seal Type: shamir, Sealed: false
# 使用根令牌登录
vault login <Initial Root Token>
3. 启用 KV 引擎写入密钥
vault secrets enable -path=secret kv-v2
vault kv put secret/webapp db_password='S3cure!Pass'
vault kv get secret/webapp
vault kv metadata get secret/webapp
4. 配置 MySQL 动态密钥(可选)
vault secrets enable database
vault write database/config/mysql \
plugin_name=mysql-database-plugin \
connection_url="{{username}}:{{password}}@tcp(10.0.0.5:3306)/" \
allowed_roles="readonly"
vault write database/roles/readonly \
db_name=mysql \
creation_statements="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';GRANT SELECT ON *.* TO '{{name}}'@'%';" \
default_ttl="1h" max_ttl="24h"
# 获取动态密钥(1 小时后自动吊销)
vault read database/creds/readonly
5. 编写策略并创建 AppRole
cat > webapp.hcl <<'EOF'
path "secret/data/webapp" {
capabilities = ["read"]
}
EOF
vault policy write webapp webapp.hcl
vault auth enable approle
vault write auth/approle/role/webapp \
token_policies="webapp" \
token_ttl="30m" \
secret_id_ttl="24h"
# 获取 RoleID 与 SecretID 分发给应用
vault read -format=json auth/approle/role/webapp/role-id
vault write -f auth/approle/role/webapp/secret-id
配置验证
# 使用 AppRole 登录并读取密钥,验证策略生效
vault write auth/approle/login role_id=<RoleID> secret_id=<SecretID>
export VAULT_TOKEN=<返回的 client_token>
vault kv get secret/webapp # 应能读取
# 验证动态密钥租期与吊销
vault read database/creds/readonly
vault list sys/leases/lookup/database/creds/readonly
常见问题
FAQ 1:Vault 重启后变为 Sealed 状态怎么办?
这是 Vault 的安全设计,密钥保存在磁盘时已加密。重启后需重新输入 3 个(阈值)Unseal Key 完成解封。生产环境建议使用 Auto Unseal(云 KMS 或 HSM)自动解封,避免人工介入。
FAQ 2:根令牌丢失还能恢复吗?
可以。执行 vault operator generate-root 配合解封密钥分片重新生成根令牌。若解封密钥也全部丢失则无法恢复,只能销毁存储目录重新初始化,因此 Unseal Key 与根令牌必须离线加密备份。
FAQ 3:应用如何避免硬编码 RoleID/SecretID?
SecretID 属于机密,RoleID 可视为半公开标识。建议用环境变量注入 SecretID,或结合 Vault Agent 的 auto-auth 功能在应用启动时自动获取令牌并缓存,应用内不再接触任何明文凭证。
总结
通过本文步骤,可以在半小时内搭建一套可用的 Vault 密钥管理环境:Raft 存储 + Shamir 解封保障数据安全,KV 引擎存储静态密钥,数据库引擎下发临时动态凭证,Policy 与 AppRole 实现最小权限认证。这套方案把密码从”散落配置”变为”集中管控”,显著降低凭证泄露面。后续可进一步接入 Kubernetes 认证、Terraform 联动与 Consul 高可用部署,构建完整的密钥治理体系。