Hashicorp Vault 密钥管理
path "secret/data/*" { capabilities = ["read"] }
这个策略授予对 `secret/data` 下所有路径的只读权限。策略与令牌绑定,实现最小权限。
### 1.4 审计设备(Audit Devices)
Vault 会记录所有请求和响应(不含敏感值),可输出到文件、syslog、Elasticsearch 等,满足合规要求。
---
## 二、安装与快速启动
### 2.1 下载安装
从 [HashiCorp 官网](https://developer.hashicorp.com/vault/downloads) 下载对应系统的二进制包,解压后将 `vault` 可执行文件放入 `PATH` 路径中。
验证安装:
```bash
vault version
2.2 启动开发模式
注意:开发模式只用于学习和实验,数据存储在内存中,每次重启都会丢失。切勿用于生产。
vault server -dev -dev-root-token-id="root"
终端会输出一个监听地址(默认 http://127.0.0.1:8200)和根令牌 root。保持此终端运行。
另开一个终端,配置环境变量:
export VAULT_ADDR='http://127.0.0.1:8200'
export VAULT_TOKEN='root'
现在你可以用 CLI 与 Vault 交互了。
2.3 生产级启动概览
生产环境通常使用 RAFT 集成存储或外部存储(如 Consul),通过配置文件指定 storage 和 listener,并进行 vault operator init 初始化分割密钥(Unseal Keys)。初始化后 Vault 处于密封状态,需要用一定数量的 Unseal Key 解封才能使用。这种设计确保了任何单点存储泄露不会直接暴露明文。
三、使用 KV 秘密引擎管理静态密钥
KV 引擎是最常用的静态秘密存储方式,分为 v1 和 v2 两个版本。v2 增加了版本控制、软删除和元数据管理,推荐使用 kv v2。
3.1 启用 KV v2 引擎
默认挂载点 secret/ 在 dev 模式下已经创建为 kv v2 引擎。生产环境需要手动启用:
vault secrets enable -path=my-secrets kv-v2
这条命令在路径 my-secrets 上挂载了一个 kv v2 引擎。
3.2 写入和读取秘密
写入秘密:
vault kv put my-secrets/database username="dbadmin" password="s3cret!"
读取秘密:
vault kv get my-secrets/database
输出会包含版本号、元数据以及实际的数据字段。
3.3 版本管理(仅在 v2)
kv v2 保留多个版本,你可以查看历史版本:
vault kv get -version=1 my-secrets/database
软删除一个版本(保留数据,但标记为删除):
vault kv delete my-secrets/database
彻底删除所有版本:
vault kv metadata delete my-secrets/database
恢复已软删除的版本:
vault kv undelete -versions=2 my-secrets/database
3.4 数据编码与结构化
秘密值可以是任意 JSON 对象,所以你可以存储复杂结构:
vault kv put my-secrets/app config='{"host":"db.example.com","port":5432}'
读取时直接获得完整的 JSON 对象,方便机器解析。
四、动态秘密:按需生成临时凭证
动态秘密是 Vault 最强大的能力之一,它按需创建凭证,并在租约到期后自动撤销,彻底杜绝长期凭证泄露风险。
4.1 动态数据库凭证示例(PostgreSQL)
步骤 1:启用数据库秘密引擎
vault secrets enable database
步骤 2:配置数据库连接
我们需要提供数据库的连接 URL 和用于创建/删除角色的管理员凭证。
vault write database/config/my-postgres-db \
plugin_name=postgresql-database-plugin \
allowed_roles="read-role" \
connection_url="postgresql://{{username}}:{{password}}@localhost:5432/postgres?sslmode=disable" \
username="vault_admin" \
password="admin_secret"
步骤 3:定义角色(Role)
角色会映射到一组 SQL 语句,用于创建临时用户。
创建 read-role,执行一条创建用户并授权只读的语句:
vault write database/roles/read-role \
db_name=my-postgres-db \
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
default_ttl="1h" \
max_ttl="24h"
{{name}}、{{password}}、{{expiration}}是 Vault 自动填充的变量。default_ttl和max_ttl控制凭证生命周期。
步骤 4:获取动态凭证
vault read database/creds/read-role
输出包含 username、password 和 lease_id、lease_duration。现在你可以用这个临时用户连接数据库读取数据。租约到期后,Vault 会自动运行 revocation_statements 删除用户。
4.2 动态云凭证(以 AWS 为例)
同样先启用 AWS 引擎,配置根 IAM 用户权限,然后创建可以生成临时 IAM 用户的角色。应用只需要请求 vault read aws/creds/my-role,即可获得 access_key 和 secret_key,这些凭证的有效期由策略控制,到期自动撤销。
五、Transit 引擎:加解密即服务
Transit 引擎允许应用在不接触底层加密密钥的情况下执行加密操作,非常适合保护传输中的数据或存储加密。
5.1 启用 Transit 并创建密钥环
vault secrets enable transit
vault write -f transit/keys/orders key_type=ecdsa-p256
这条命令创建一个名为 orders 的密钥,用于后续加密。
5.2 加密数据
需要加密的数据必须先进行 base64 编码。
# 加密
vault write transit/encrypt/orders plaintext=$(echo -n "creditcard=4111111111111111" | base64)
返回 ciphertext,这是加密后的结果。
5.3 解密数据
# 解密
vault write transit/decrypt/orders ciphertext="vault:v1:lccC52cz5UZ9iKT+..."
解密结果中的 plaintext 仍然是 base64 编码,解码后即可得到原始数据:
echo "Y3JlZGl0Y2FyZD00MTExMTExMTExMTExMTEx" | base64 -d
Transit 引擎还支持密钥轮换、数据重加密、签名验证等功能,应用完全无需关心密钥生命周期。
六、访问控制:策略与令牌管理
6.1 编写策略文件
创建文件 app-read.hcl:
# 允许读取 my-secrets 路径下的数据
path "my-secrets/data/*" {
capabilities = ["read"]
}
# 允许列出路径(可选)
path "my-secrets/metadata/*" {
capabilities = ["list"]
}
将策略写入 Vault:
vault policy write app-read app-read.hcl
6.2 生成受限制的令牌
使用该策略创建一个新令牌:
vault token create -policy=app-read