HashiCorp Vault 金库
Vault 是 HashiCorp 推出的企业级秘密管理工具, 专为集中保护, 控制和审计敏感信息访问而设计
源代码开源(source-available) + 商业授权 模式
OpenBao(开源版 Vault)
如果可以, 推荐应用直接通过 SDK 直接访问 Vault 来获取密钥
特性
集中化秘密存储:
安全管理 API 密钥, 数据库密码, SSL 证书等敏感信息
替代分散在代码或配置文件中的明文存储, 从源头降低泄露风险
细粒度访问控制:
基于策略(Policy)实现"最小权限"管理,
支持多身份认证(Token, LDAP, OAuth2, MFA 等), 确保只有授权实体能访问特定秘密;
动态凭证生成:
为数据库, 云服务等自动生成短期有效, 自动过期的临时凭证, 大幅降低长期凭证泄露的安全隐患;
全链路审计追踪:
记录所有秘密访问, 修改, 删除操作, 生成不可篡改的审计日志, 满足合规审计需求(如等保, SOC2);
可以为数据库 /SSH/Consul/AWS/Nomad/PKI/RabbitMQ 等多种平台生成和管理访问密钥
可以与 Cousul, Chef, Ansible 等运维工具集成起来共同使用
密钥:
- 静态 Secret: 密钥是固定的
- 动态 Secret:
请求时会到后端应用去创建一个临时账号(有效期), 并处理权限;
然后将临时账号给到到前端应用, 应用侧自己需要能处理租约到期
数据存储
- 内存: 临时存储, 配置内存锁定
- 文件存储: 开发环境使用
- 分布式存储: etcd, consul 等
- aws s3, nosql
应用身份认证方式
应避免硬编码 token 的方式
AppRole: 为应用分配一个 role_id 和 secret_id, 适用于服务器端应用
Kubernetes Auth Method: 针对运行于 Kubernetes 上的服务;
SDK 会利用 Pod 的 ServiceAccount 自动与 Vault 完成认证
云平台认证: 对于运行在 AWS, Azure, GCP 上的应用, 可以使用云平台的原生认证
即 IAM 身份进行认证
JWT/OIDC:
利用外部 OAuth2 提供者进行用户认证;
k8s 集成
方式 1: Vault Secrets Operator 同步创建 Secrets
方式 2: Sidecar 模式, pod 附加一个容器, 即 Vault Agent Sidecar 容器负责与 Vault 通信, 并创建文件挂载
方式 3: Vault CSI Driver 卷挂载模式, 挂载为 Pod 的 临时卷
主流方式 1
但方式 2 和 3 无 Secret, 所有密钥不会在命名空间内, 即也不会存储到 etcd 中, 适合安全性非常高的场景
Raft 集群
2/3 可用
Leader 节点宕机, 会进行选举;
Follower 节点, 系统无感知
1
2
3
4
5
6
|
# 查看成员健康度
vault operator raft list-peers
Node Address State Voter
---- ------- ----- -----
node1 vault:8201 leader true
|
运行模式
- seal 密封模式
- Auto-Unseal 自动解封模式
需要注意 seal密封模式 和 Recovery 恢复模式是互斥的;
seal密封模式会生成 5 个解封密钥片段;
密钥有两个用途: 解封 + 授权(重大操作的授权)
自动解封模式时, 解封密钥实际是由 kms/HSM 管理, 此时生成的是5个恢复密钥;
密钥只有 1个用途: 授权(重大操作的授权)
dev 模式
dev 模式下 Vault 会在内存中自动完成初始化和解封
数据没有持久化, 仅用于本地开发调试;
没有解封密钥, 只有一个 rootToken
1
2
|
# 如果指定了这个变量, 会强制运行在开发模式下, 没有持久化
VAULT_DEV_ROOT_TOKEN_ID=
|
seal 密封模式
需要手工初始化和解封
初始化
集群模式下, 只需要 init 一个节点, 其他节点只需要加入集群;
1
2
3
4
5
|
docker exec -it vault-server sh
export VAULT_ADDR=http://127.0.0.1:8200;
# 会生成 5 个 unseal key 和 1 个 root token, 务必保存
vault operator init
|
unsealKey: 解封所需要的密钥分片;
当节点重启后, Vault 启动后处于"密封"状态, 需要 5 个 unsealKey 密钥分片 中的至少 3 个才能解封;
1
2
|
# 解封 - 并按提示输入任意 3 个 unsealKey
vault operator unseal
|
Auto-Unseal 自动解封
初始化时, Vault 会直接把解封密钥存入 KMS;
节点重启时, 会调用 云 kms 接口进行自动解封;
权限控制变成了对"谁能调用 KMS 接口"的阿里云 RAM 权限管理;
ECS 实例或运行 Vault 的环境拥有调用 kms:Decrypt 和 kms:Encrypt 的权限
在 Vault 的配置文件中定义 seal 部分
1
2
3
4
5
6
|
seal "alicloudkms" {
region = "cn-hangzhou"
access_key = "ak"
secret_key = "sk"
kms_key_id = "KMS 主密钥 ID"
}
|
Recovery Keys 恢复密钥
是一个专门用于授权和恢复操作的安全机制, 区别于常规的解封密钥(Unseal Keys);
只有当 Vault 使用了自动解封(Auto Unseal), 例如集成了云厂商的 KMS 或硬件安全模块(HSM)时, 才会用到它;
Vault 的解封过程由 KMS/HSM 自动完成, 不再需要人来输入解封密钥; 因此没有 解封密钥(Unseal Keys);
Recovery Keys 是一个纯人工授权的机制, 它的核心功能是授权, 而不是解密
用于关键操作授权需要人工批准
- 如生成根令牌 generate-root
- 执行重新加密 rekey 等
- 更改迁移 KMS 配置
需要达到设定的阈值(threshold)数量的密钥持有者同意, 操作才能继续
初始化生成:
使用 HSM 或 KMS 初始化 Vault 时, 系统会生成一个内部的 Recovery Key,
并将其拆分成多个密钥碎片(Key Shares), 返回给操作者;
重新生成(Rekey):
在人员变动或合规要求下, 可以使用 rekey 命令来重新生成一套新的 Recovery Keys
PGP 加密:
可以使用 在生成或重新生成 Recovery Keys 时使用 -pgp-keys 参数传入 pgp 公钥;
1
2
3
4
5
|
# 重新生成恢复密钥 - 需要多数旧的恢复密钥, Vault 会输出 5 个全新的 Recovery Keys
vault operator rekey -target=recovery
# 重新生成恢复密钥 - 到达阈值后才会有输出
vault operator rekey -init -key-shares=5 -key-threshold=3
|
避免单人掌握多数 unsealKey/RecoveryKey
官方方案: 使用 PGP 公钥加密
5 位密钥持有者每人提供一个 PGP 公钥, 初始化时需要传入这 5 个公钥;
1
2
3
4
|
vault operator init \
-key-shares=5 \
-key-threshold=3 \
-pgp-keys="user1.asc,user2.asc,user3.asc,user4.asc,user5.asc"
|
终端会输出 5 段密文, 经 PGP 加密的 Base64 字符串, 只有对私钥持有者能解密出自己的那段密文;
alicloudkms
需要 alicloudkms 插件
在 Auto-Unseal 模式下, Vault 会利用 KMS 的"信封加密"技术,
自动产生一个 Recovery Key(恢复密钥),
并将真正用于加解密数据的 Root Key(根密钥) 存储在 KMS 中
- 每次重启 Vault 服务, 它会自动连接阿里云 KMS 完成解密并进入 unsealed(解封)状态
- 不在生成 5 个解封的 key, 而是 Recovery Keys
在阿里云控制台:
- 开通 KMS(密钥管理服务);
- 创建一个 对称密钥(用户主密钥), 记录下它的 KeyId;
- 确保你的 ECS 实例或运行 Vault 的环境拥有调用 kms:Decrypt 和 kms:Encrypt 的权限(建议通过 RAM 角色授权);
config.hcl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
ui = true
storage "file" {
path = "/vault/data"
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_disable = 1
}
# 核心配置: 阿里云 KMS 自动解封
seal "alicloudkms" {
region = "cn-hangzhou" # KMS 所在的地域
access_key = "你的 AccessKeyId" # 建议使用 RAM 角色, 此处可省略
secret_key = "你的 AccessKeySecret"
# 刚才在阿里云创建的密钥 ID
kms_key_id = "bc4xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
|
初始化
不再输出 Unseal Key 1…5, 会输出 Recovery Key 1…5, 依然会输出 Initial Root Token
阿里云权限控制
方案1: 细化权限
禁止给非 Vault 服务器授予 Resource: * 的权限
1
2
3
4
5
|
{
"Action": ["kms:Decrypt"],
"Resource": ["*"], // 禁止所有权限, 必须细化
"Effect": "Allow"
}
|
每个业务系统细化权限
1
2
3
4
5
|
{
"Action": ["kms:Decrypt"],
"Resource": ["acs:kms:cn-hangzhou:12345:key/业务Key_ID_xxxx"], // 明确指定
"Effect": "Allow"
}
|
方案2: 提供预设的字符串对进行双保险
1
2
3
4
|
seal "alicloudkms" {
kms_key_id = "你的ID"
encryption_context = "{\"AppName\": \"Vault-Production-Cluster\"}"
}
|
方案3: 限制作用域, 这个 权限 只能在某个范围用
1
2
3
4
5
6
7
8
9
10
|
{
"Action": "kms:Decrypt",
"Resource": "acs:kms:cn-hangzhou:12345:key/Vault_Key_ID",
"Effect": "Allow",
"Condition": {
"StringEquals": {
"acs:SourceVpc": ["vpc-t4nxxxxxxxx"] # 只有这个 VPC 内的请求才有效
}
}
}
|
RootToken
初始化后会生成一个最高权限的 rootToken
最佳实践
撤销掉这个初始的 rootToken, 有必要时再进行临时创建(需要 5 个解封密钥)
1
2
|
# 撤销 token
vault token revoke <TOKEN_VALUE>
|
重新生成 rootToken
1
2
3
4
5
6
7
8
9
|
# 利用 Recovery Keys 重新生成 root token
# 系统会返回一个 Nonce 值和 OTP (One-Time Password)
vault operator generate-root -init
# 提供 Recovery Keys 签名, 需要多个管理员输入足够数量的 Recovery Keys
vault operator generate-root -recovery-key
# 解码获取新 Token:
# 最后一步会输出一个加密的 Token 字符串, 结合第 1 步的 OTP 即可解密出真实的 hvs.root-xxx
|
管理cli
1
2
3
4
|
export VAULT_ADDR='http://192.168.5.9:8200'
export VAULT_TOKEN='xxxxxxxxxxxxxewofoeiwoiieo'
vault status # 运行状态
|
kv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# write
vault kv put secret/myapp/config \
db_username="admin" \
db_password="very-secret-password" \
timeout="5s"
# read
vault kv get secret/myapp/config
# modify
vault kv patch secret/myapp/config timeout="10s"
vault kv metadata get secret/myapp/config # 查看版本历史
vault kv get -version=1 secret/myapp/config # 读取旧版本 (版本 1)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
# 查看已经开启的认证方法
vault auth list
Path Type Accessor Description Version
---- ---- -------- ----------- -------
approle/ approle auth_approle_f18cd096 n/a n/a
token/ token auth_token_ecd6971e token based credentials n/a
userpass/ userpass auth_userpass_42108dc7 n/a n/a
# token 是已经签发的token, 不能直接列出
vault write auth/userpass/users/user1 password=passw0rd
vault login -method=userpass username=bob password=foobar
vault list auth/userpass/users
vault list auth/approle/role/
|
业务集成
在 k8s 集群中
-
每个 Pod 都有一个挂载在 /var/run/secrets/kubernetes.io/serviceaccount/token 的 JWT 令牌;
-
交换 Token: 应用(或 Vault Agent)将这个 JWT 发给 Vault;
-
验证: Vault 调用 K8s API 确认: “这个 JWT 确实是 order-service 这个应用的;”
-
下发 Token: 验证通过, Vault 返回一个专门给该应用使用的, 权限受限的 VAULT_TOKEN
续签
- Vault sdk 有续签机制
- Vault Agent - Sidecar 模式
在虚拟机或物理机上
利用 AppRole; 这类似于 OAuth2;
应用持有一个 RoleID(类似用户名)和 SecretID(类似密码);
启动时调用 Vault API 换取 VAULT_TOKEN
最佳实践
-
云上优先考虑 Auto-unseal 自动解封, 节点漂移后方便自动解封;
-
云下部署考虑硬件密钥
-
app 通过sdk直接访问 vault 获取秘密信息
-
k8s集群可选通过 eso(ExternalSecretsOperator) 或者 vault-secrets-operator 将密钥更新到 k8s secrets
-
vault 最好在k8s集群外独立部署
vault-secrets-operator
将 vault 中的秘密同步到 k8s 集群中
原生支持动态秘密
认证集成: 深度利用 K8s Auth Method, 让 Pod 能够以原生的方式与 Vault 交互
1
2
3
4
5
|
helm repo add hashicorp https://helm.releases.hashicorp.com
helm repo update
helm install vault-secrets-operator hashicorp/vault-secrets-operator \
--namespace vault-secrets-operator-system \
--create-namespace
|
Vault 配置
- 在 Vault 侧配置, 需要启用 Kubernetes 认证, 并创建一个角色(Role), 这个角色会将特定的 Kubernetes ServiceAccount 和命名空间绑定到 Vault 的权限策略上
- 在 Kubernetes 侧配置: 通过创建 VaultAuth 资源来告诉 VSO 如何使用这个角色进行认证
1
2
3
4
5
6
7
8
9
10
11
12
|
# 示例: VaultAuth 资源
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultAuth
metadata:
name: static-auth
namespace: default
spec:
method: kubernetes
mount: kubernetes
kubernetes:
role: database # 对应在 Vault 中创建的 role 名称
serviceAccount: my-app-sa # VSO 将使用的 ServiceAccount
|
通过 VaultStaticSecret 资源从 Vault 拉取 Secret
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# 示例: VaultStaticSecret 资源
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultStaticSecret
metadata:
name: myapp-static-secret
namespace: default
spec:
type: kv-v2 # 使用 KV V2 引擎
mount: secret # Vault 中的挂载路径
path: myapp/config # Vault 中的 Secret 路径
destination:
name: myapp-k8s-secret # 生成的 Kubernetes Secret 名称
create: true # 自动创建 Secret
refreshAfter: 1h # 定期从 Vault 拉取最新数据, 每小时同步一次
|
开启 instantUpdates 可以实现基于 Vault 事件(Event)的近实时同步
当 Secret 更新后, 可以通过在 VaultStaticSecret 中配置 rolloutRestartTargets,
让 VSO 自动触发关联的 Deployment 或 StatefulSet 滚动更新
数据转换:
如果 Vault 中的原始数据格式不适合应用,
还可以使用 transformation 字段, 通过 Go 模板对数据进行处理后再存入 Kubernetes Secret
动态密码-数据库
1
2
|
# 启用数据库引擎
vault secrets enable database
|
PostgreSQL
配置连接
1
2
3
4
5
6
|
vault write database/config/my-db \
plugin_name=postgresql-database-plugin \
allowed_roles="my-role" \
connection_url="postgresql://{{username}}:{{password}}@localhost:5432/postgres?sslmode=disable" \
username="postgres" \
password="root-password"
|
定义角色与权限: 告诉 Vault 每次生成临时用户时执行什么 SQL
1
2
3
4
5
|
vault write database/roles/my-role \
db_name=my-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"
|
生成临时密码
1
|
vault read database/creds/my-role
|
得到一个全新的 username (如 v-token-my-role-xxx) 和 password
1小时后, Vault 会自动在数据库里删掉这个用户
java引入配置
引入 spring-cloud-starter-vault-config
bootstrap.yml
1
2
3
4
5
6
7
8
9
|
spring:
cloud:
vault:
uri: http://localhost:8200
token: ${VAULT_TOKEN}
kv:
enabled: true
backend: secret
default-context: myapp/config
|
API
1
2
3
4
5
|
# 查看状态, 是否封锁和解封
curl https://vault.services.wait/v1/sys/seal-status
# API 可用性验证
curl http://IP:8200/v1/sys/health # 返回包含 initialized 和 sealed 状态的 JSON
|
approle
AppRole 代表一组 Vault 策略和登录约束, 必须满足这些策略才能使用这些策略获取令牌
面向应用程序
roleID - 角色ID
SecretID - 认证密钥
只产生 Vault Token, 解决你是谁的问题, 并不涉及权限
具体的权限要看绑定的 kv 或者 path 路径策略
1
2
|
# 开启 AppRole 认证
vault auth enable approle
|
token_type
- service 默认类型; 存储在 Vault 的内存和磁盘中, 支持续期(Renew), 吊销(Revoke), 并会在 Vault 界面显示;
- batch 类型; 类似 JWT, 所有的权限信息都加密编码在 Token 字符串本身;
极高性能, 减轻 Vault 存储后端的负担, 不可续期, 且一旦发出除非到期否则无法吊销;
适合短暂的自动化任务, 高并发的临时访问
role manager
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
vault delete auth/approle/role/terraform-role
# 创建角色并绑定策略 - auth/approle/role/terraform-role
vault write auth/approle/role/terraform-role \
secret_id_ttl=0 \ # SecretID 自身的有效期
secret_id_num_uses=0 \ # SecretID 使用次数限制
token_type=service \ # 默认就是 service
token_num_uses=0 \
token_ttl=1h \ # Token 产生后的初始有效期
token_max_ttl=3h \ # Token 允许被续期到的最长总时长, batch 类型的 Token 不可续期
token_policies="admin-readonly"
# 获取 role-id
vault read auth/approle/role/homelab-app1/role-id
# 创建/获取 Secret ID
vault write -f auth/approle/role/homelab-app1/secret-id
|
登录并换取 Token
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
## 登录
vault write auth/approle/login \
role_id="ae7830a4-ee10-3e84-b186-770b286b51b4" \
secret_id="f8268b33-6b96-d08f-bcb7-0c959dcd09bd"
# 响应 json 里面有 client_token 字段
# 也可以通过 vault token lookup 查看认证和 token
curl \
--request POST \
--data '{"role_id":"ae7830a4-ee10-3e84-b186-770b286b51b4","secret_id":"f8268b33-6b96-d08f-bcb7-0c959dcd09bd"}' \
https://vault.services.wait/v1/auth/approle/login
|
1
2
3
4
5
6
7
8
9
10
11
12
|
wait@ub05:~$ vault read auth/approle/role/homelab-app1/role-id
Key Value
--- -----
role_id 3211340e-fe90-3236-36fe-ff7100763cf2
wait@ub05:~$
wait@ub05:~$ vault write -f auth/approle/role/homelab-app1/secret-id
Key Value
--- -----
secret_id b4d8c662-0042-040a-0527-dbbbe3acec90 # 密码
secret_id_accessor b86c5e6d-880f-32e4-279b-eaf19151bc5b # 访问器/工号
secret_id_num_uses 0
secret_id_ttl 0s
|
secret_id_accessor 即密钥的编号, 便于通过 secret_id_accessor 管理 secret, 例如删除
1
|
vault write auth/approle/role/homelab-app1/secret-id-accessor/destroy accessor=b86c5e6dxxx
|
CIDR绑定
在 Vault 的 AppRole 机制中, CIDR 绑定分为两个层级, 建议同时使用:
- secret_id_bound_cidrs 限制 谁能拿 SecretID 去登录
- token_bound_cidrs 限制 登录后拿到的 Token 只能在哪些 IP 使用
1
2
3
4
5
6
7
8
9
10
11
12
|
vault write auth/approle/role/homelab-node \
secret_id_num_uses=0 \
secret_id_ttl="0" \
# 核心限制:只允许来自 指定 的 IP 请求登录, 多ip使用逗号分隔
secret_id_bound_cidrs="192.168.1.5/32" \
# 核心限制: 生成的 Token 也只能在 这个 ip 上使用
token_bound_cidrs="192.168.1.5/32" \
token_ttl="1h" \
token_max_ttl="3h" \
policies="pki-policy" # 绑定某个策略
|
userpass
vault 内部的账号体系
可以通过 Vault 的 API, CLI 或 UI 来登录这个账号
Vault 验证密码正确后, 会现场生成一个 Token
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
vault auth enable userpass # 开启 userpass 认证
vault auth list # 查看已经开启的认证方法
vault list auth/userpass/users # 查看全部用户
# 新建一个用户, 增加策略也是这个命令
vault write auth/userpass/users/alice \
password="foo" \
policies="admin" # 关联 admin 这个策略
# 登录时会自动获取 token
vault login -method=userpass username=admin
curl --request POST \
--data '{"password": "user_password"}' \
${VAULT_ADDR}/v1/auth/userpass/login/admin
# 设置环境变量
export VAULT_TOKEN="hvs.xxx..."
vault login -method=userpass username=admin
Key Value
--- -----
token hvs.CAESIKXoJd6k37JUxGEZZ5tHOdBydB4Y07Zfl0B3z8FrmpY-Gh4KHGh2cy5YT3FLaGNEbEJSeDJPYUdRcTFZN3R4aTg
token_accessor jfy69OCJVuZXn6gjKfdWbsmg
token_duration 768h
token_renewable true
token_policies ["admin" "default"]
identity_policies []
policies ["admin" "default"]
token_meta_username admin
# 查看 Token 详情, 验证权限
vault token lookup
Key Value
--- -----
accessor jfy69OCJVuZXn6gjKfdWbsmg
creation_time 1775833166
creation_ttl 768h
display_name userpass-admin
entity_id bebb8efc-3615-7fff-219d-78598cf87bb3
expire_time 2026-05-12T22:59:26.642334339+08:00
explicit_max_ttl 0s
id hvs.CAESIKXoJd6k37JUxGEZZ5tHOdBydB4Y07Zfl0B3z8FrmpY-Gh4KHGh2cy5YT3FLaGNEbEJSeDJPYUdRcTFZN3R4aTg
issue_time 2026-04-10T22:59:26.642342468+08:00
meta map[username:admin]
num_uses 0
orphan true
path auth/userpass/login/admin
policies [admin default]
renewable true
ttl 767h59m35s
type service
# 用户登录后修改密码
vault write auth/userpass/users/alice/password password="NewSecurePassword"
|
engine
secret engine
Generic: KV, Kubernetes, LDAP, PKI Certificates, SSH, TOTP, Transit
Cloud: AliCloud AWS Azure Google Cloud Google Cloud KMS
Infra: Consul Databases Nomad RabbitMQ
Generic (通用类): 核心功能与加解密
| 引擎 |
作用 |
| KV |
Key-Value 存放静态密钥, api token 等 |
| Transit |
加密服务 |
| PKI Certificates: |
CA (证书颁发机构) 自动为内网服务签发 TLS 证书 |
| SSH |
生成临时的 SSH 登录凭证 |
| TOTP |
生成临时的 动态两步验证码; |
| LDAP |
|
| Kubernetes |
通常指机密引擎(为 K8s 生成 Service Account Token), 而不是登录认证; |
Cloud: AliCloud / AWS / Azure / GCP
场景: 动态生成 IAM 角色账号
程序向 Vault 申请, Vault 调用云 API 临时创建一个只拥有特定权限的 AK
Google Cloud KMS / AWS KMS
密钥桥接; 让 Vault 利用云端的硬件安全模块(HSM)来保护自己的主密钥
Infra (基础设施类): 中间件动态授权
Databases: 支持 MySQL, Postgres, MongoDB, Redis 等
应用请求角色, Vault 会去数据库创建账号并赋权, 消除共享的 DB 账号
Consul / Nomad: 动态生成 Consul 的 ACL Token 或 Nomad 的调度权限
RabbitMQ: 动态管理消息队列的用户和权限(VHosts, Permissions)
cubbyhole
每个 token 都有的临时存储空间
仅当前 Token 可见
即使是 Root Token, 也无法看到其他 Token 的 cubbyhole
随 Token 销毁的, 一旦 Token 到期, 被撤销或注销, 该 Token 在 cubbyhole/ 下存储的所有数据会立即被永久物理删除
aws
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
vault secrets enable aws
# 写入一个高级权限的aws账号
vault write aws/config/root \
access_key=AKIAZXN6JNH5D6ZSHS5V \
secret_key=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 \
region=us-east-1
# 创建一个角色(vpc),让它可以操作 VPC
vault write aws/roles/vpc \
credential_type=iam_user \
policy_document=-<<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ec2:*",
"Resource": "*"
}
]
}
EOF
# 获取 access_key 和 secret_key, 这里获取到的是 aws 的;
# Vault 中把动态生成的机密信息关联了一个 lease 租约, 默认 768h 可用
vault read aws/creds/vpc
|
1
2
3
4
5
|
# 手动吊销租约, 会删除 aws iam 账号
vault lease revoke aws/creds/vpc/w8OTDxIri80TCkGtoZPkc6Qc
# 设置生成的 Key 的有效时间
vault secrets tune -default-lease-ttl=30m aws/
|
alicloud
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
# 开启阿里云认证插件
vault auth enable alicloud
# 配置 Vault 访问阿里云的凭证(建议给这个 RAM 用户最小权限: Action: "sts:GetCallerIdentity")
vault write auth/alicloud/config \
access_key="YOUR_ACCESS_KEY" \
secret_key="YOUR_SECRET_KEY"
# 创建 Vault 角色并绑定 RAM 角色
# 这一步是建立 RAM 角色 (ARN) 与 Vault 策略 之间的映射关系
# 创建一个 Vault 角色, 绑定到特定的阿里云 RAM 角色 ARN
vault write auth/alicloud/role/homelab-gpu-node \
arn="acs:ram::1234567890:role/my-gpu-instance-role" \
policies="pki-policy,kv-readonly" \
ttl="1h"
# 只有拥有 my-gpu-instance-role 这个 RAM 角色的实例, 才能登录这个 Vault 角色
|
kv
v1 版本比较简单, 没有多版本
v2 支持多版本
1
2
|
# 启用 v1
vault secrets enable -version=1 kv
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
vault kv put kv/my-secret my-value=s3cr3t
vault kv get kv/my-secret
vault kv delete kv/my-secret
vault kv list homelab/infra/
vault kv get homelab/infra/aliyun
vault kv list homelab/infra/ssh-keys/
vault kv put secret/test db_password=123456 # 创建秘密
vault kv get secret/test # 读取秘密(应显示 db_password:123456)
|
Transit 加密服务
- 自身不存储数据
- 只负责提供加解密数据的api, 即只执行不存储;
支持的加密方式 (算法)
| 类型 |
算法 |
| 对称加密 |
AES-GCM (默认), AES-CBC, ChaCha20-Poly1305 |
| 非对称加密 |
RSA (2048/4096), ECDSA (P-256/384/521), Ed25519 |
| 哈希 |
SHA-2 (224/256/384/512) |
| HMAC |
SHA-2 (256/384/512) |
性能: 标准4核主机, AES-GCM 这种硬件加速算法每秒可以处理约万次请求
关键特性: 收敛加密 (Convergent Encryption)
Vault 支持一种模式, 使得相同的明文和上下文在加密后产生相同的密文, 这在数据库脱敏后的"等值查询"中非常有用
信封加密
- Vault 端: 仅生成一个 数据密钥 (Data Encryption Key, DEK);
- 应用端使用这个 DEK 对数据进行加密和解密
- 应用向 Vault 请求用"主密钥"加密这个 DEK, 并将加密后的 DEK 连同密文一起存入数据库
- 应用重启后需要先向将 DEK 的密文给 vault 解密, 然后用 DEK 去解密业务数据;
优点: 只有获取 / 加密 DEK 时调用一次 Vault, 实际大数据量的加解密在本地 CPU 完成
ssh
原理: ssh 服务器通过信任CA根证书的方式允许可信客户端登录
- vault 是 ca 签署者
- 签署用户的 ssh 公钥后 生成 证书文件
- 用户使用 ssh 私钥 + 证书文件 登录服务器
1
2
3
4
5
6
7
8
9
10
11
12
|
# 开启 SSH 秘密引擎
vault secrets enable -path=ssh-client-signer ssh
# 配置 Vault 生成自己的 CA 私钥和公钥
# 注意: Vault 会安全地保存私钥, 只把公钥给你
vault write ssh-client-signer/config/ca generate_signing_key=true
需要获取 Vault 的 CA 公钥, 并把它放到你所有服务器 /etc/ssh/trusted-user-ca-keys.pem
并在 sshd_config 里引用它
# 获取公钥并保存
curl -o /etc/ssh/ssh_ca.pub $VAULT_ADDR/v1/ssh-client-signer/public_key
|
示例
创建 Vault 角色 (Role)
创建一个名为 ops-role 的角色, 它强制要求证书中必须包含 ops 这个勋章, 并且限制有效期为 1 小时
1
2
3
4
5
6
7
8
9
10
11
12
|
vault write ssh-client-signer/roles/ops-role \
key_type=ca \
allow_user_certificates=true \
allowed_users="ops" \ # 为证书里的角色名
default_extensions="permit-pty,permit-port-forwarding" \
allow_user_key_ids=true \
key_id_format="{{token_display_name}}" \
max_ttl="1h" \
ttl="1h"
# key_id_format: 这会自动把登录 Vault 的用户名(如 alice)填入证书的 Key ID (-I)
|
用户申请签名
用户生成自己的ssh公私钥
1
2
3
4
5
6
7
8
|
ssh-keygen -t ed25519 -f ~/.ssh/vault_temp -N ""
# 提交自己的公钥进行签名 - 获取到证书文件
vault write -field=signed_key ssh-client-signer/sign/ops-role \
public_key=@$HOME/.ssh/vault_temp.pub > ~/.ssh/vault_temp-cert.pub
# 登录目标系统的公共账号 ops-runner, 会自动引用 vault_temp-cert.pub 文件
ssh -i ~/.ssh/vault_temp ops-runner@192.168.5.x
|
PKI
tls 证书管理
是 CA, 还负责身份校验, 权限控制和短期证书颁发
Vault 维护动态的 CRL(证书撤销列表)
组合
- Root CA: 可以在 Vault 内部生成
- Intermediate CA: 由根 CA 签发, 专门用于处理日常请求
- Role(角色): 你可以定义一个角色 homelab-dot-com, 限制它只能签发 *.homelab.com, 有效期最长 24h
与 cert-manager 组合
cert-manager 只是证书的搬运工, 自身不生成证书
安装 cert-manager, 配置一个 Issuer 类型为 vault
- cert-manager 自动向 Vault 申请证书
- Vault 验证 K8s 的 ServiceAccount
- Vault 返回证书, cert-manager 将其存入 Secret 供 app 使用
1
2
3
4
5
6
|
# 配置 PKI 角色, 限制只能申请特定的域名, 有效期 24 小时
vault write pki_int/roles/homelab-node \
allowed_domains="homelab.local" \
allow_subdomains=true \
max_ttl="24h" \
generate_lease_with_token=true
|
客户端脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
#!/bin/bash
set -e
# --- 配置区 ---
VAULT_ADDR="https://vault.services.wait"
ROLE_NAME="homelab-node"
COMMON_NAME="ub05.homelab.local" # 当前机器的域名
CERT_DIR="/etc/ssl/vault"
RESTART_COMMAND="systemctl reload nginx" # 或者 traefik
# AppRole 凭证 (建议通过环境变量或受保护的文件读取)
ROLE_ID="你的 -role-id"
SECRET_ID="你的 -secret-id"
# --- 1. 登录 Vault 获取临时 Token ---
echo "Logging into Vault..."
LOGIN_TOKEN=$(vault write -field=token auth/approle/login \
role_id="$ROLE_ID" secret_id="$SECRET_ID")
export VAULT_TOKEN=$LOGIN_TOKEN
# --- 2. 申请新证书 ---
echo "Requesting new certificate for $COMMON_NAME..."
CERT_DATA=$(vault write -format=json pki_int/issue/$ROLE_NAME \
common_name="$COMMON_NAME" ttl="24h")
# --- 3. 解析并保存证书, 私钥和 CA 链 ---
mkdir -p $CERT_DIR
chmod 700 $CERT_DIR
echo "$CERT_DATA" | jq -r '.data.certificate' > $CERT_DIR/cert.pem
echo "$CERT_DATA" | jq -r '.data.private_key' > $CERT_DIR/key.pem
echo "$CERT_DATA" | jq -r '.data.issuing_ca' > $CERT_DIR/ca.pem
# 合并证书链 (很多 Web 服务需要这个)
cat $CERT_DIR/cert.pem $CERT_DIR/ca.pem > $CERT_DIR/fullchain.pem
echo "Certificates updated in $CERT_DIR"
# --- 4. 重载服务 ---
echo "Reloading service..."
$RESTART_COMMAND
echo "Done!"
|
安全
1
2
3
4
5
6
7
8
9
10
11
12
13
|
# 强制启用 TLS 加密
listener "tcp" {
address = "0.0.0.0:8200"
tls_disable = 0
tls_cert_file = "/vault/certs/cert.pem" # 挂载证书目录
tls_key_file = "/vault/certs/key.pem"
}
# 使用分布式存储(替代文件存储)
storage "consul" { # 或 etcd/raft
address = "consul:8500"
path = "vault/"
}
|
1
2
3
|
# 启用审计日志
vault audit enable file file_path=/vault/logs/audit.log # 登录后执行
|
1
2
3
4
5
6
7
|
创建子 token 和限制策略
vault policy write mysql-readonly readonly-policy.hcl
# 创建带限制的子 Token
# 创建一个有效期 24 小时, 只能用 10 次, 绑定该策略的子 Token
# 得到一个以 hvs. 开头的 Token, 它只能执行策略定义的读取操作
vault token create -policy="mysql-readonly" -ttl="24h" -use-limit=10
|
轮换 KMS 主密钥 (底层加密)
在阿里云 KMS 侧, 可以手动触发主密钥(CMK)的轮换, 或者开启"自动轮换"功能(如每 365 天一次);
效果: KMS 会生成一个新的密钥版本(Key Version);
对 Vault 的影响: Vault 无需重启;
它下次加密数据时会使用新版本, 解密旧数据时 KMS 会自动识别并使用旧版本;
这是对业务无感的最佳方案;
policy策略
权限 / 策略
- 允许访问 Vault 中哪些路径;
- 策略可以附加到 token 或 角色
Vault 采用一组具有优先级的判定规则来决定最为具体的路径匹配;
如果一个匹配模式被多个策略使用并能匹配上给定路径, Vault 会取其能力的并集
如果一个路径能被多个策略定义的不同的匹配模式所匹配, 那么只有最高优先级的匹配会被采用
如果 P1 中第一个 + 或是 * 出现的位置早于 P2, 那么采用 P2
如果 P1 以 * 结尾, 而 P2 不是, 那么采用 P2
如果 P1 包含更多的 + 段, 那么采用 P2
如果 P1 更短, 那么采用 P2
如果 P1 得到的字典序更小, 那么采用 P2
仅允许 * 出现在模式的末尾
一旦令牌被签发, 其关联的策略无法再被修改; 必须吊销旧令牌并申请新令牌才能得到更新后的关联策略
令牌关联的策略内容是实时解析的, 也就是说, 如果更新了策略内容,
附加此策略的令牌下次的请求就会按照新策略内容进行权限检查
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
path "secret/foo" {
capabilities = ["read"]
required_parameters = ["bar", "baz"] # 必须指定的参数
# 针对指定路径允许操作的键值对的白名单, 非空时只能使用列表中限定的值
allowed_parameters = {
"bar" = []
}
# 键值对的黑名单,优先级高于 allowed_parameters
denied_parameters = {
"bar" = []
}
min_wrapping_ttl = "1s" # 客户端可以指定的响应封装有效期的最小值
max_wrapping_ttl = "90s" # 允许设置的响应封装有效期的最大值
}
|
path
五个核心板块: 身份与认证(Auth), 系统管理(Sys), 身份实体(Identity), 秘密引擎(KV & PKI)
认证相关路径 (Auth & AppRole)
控制用户如何进入 Vault 以及如何管理登录方式
| path |
用途 |
| auth/approle/login |
这是 AppRole 登录的端点 |
| auth/* |
所有认证方法(如 Userpass, GitHub, LDAP)的配置接口 |
| sys/auth/* |
用于管理"挂载点" |
如果需要程序通过 RoleID 和 SecretID 获取 Token, 必须拥有 auth/approle/login 路径的 create 或 update 权限;
开启一个新的认证方式或关闭已有的, 就需要访问 sys/auth/
系统管理与审计 (Sys)
是 Vault 服务器级别的底层控制路径
| path |
用途 |
| sys/health |
返回 Vault 节点状态(是否初始化, 解封, 主节点) |
| sys/audit |
审计日志管理 |
| sys/leases/* |
租约管理, 可以续期和撤销 |
| sys/mounts/* |
秘密引擎管理 |
例如手动执行的 vault secrets enable, 本质上就是在操作sys/mounts路径, 决定在哪个路径挂载哪种秘密存储
策略管理 (Policies)
| path |
用途 |
| sys/policies/acl/* |
管理所有的 ACL 策略, 即 hcl 策略文件 |
| sys/policies/acl/admin |
专门指代名为 admin 的策略; |
通常在 CI/CD 或权限分配时, 会限制用户只能读取而不能修改这个特定的admin管理员策略
身份模型 (Identity)
是 Vault 的核心, 它把不同的登录方式(Alias)统一到一个"人"(Entity)身上
每个 Entity 代表一个真实的用户或机器
alias 别名: 它负责把 userpass 里的 admin 和 github 里的 wait 映射到同一个 Identity Entity 上;
| path |
用途 |
| identity/entity/* |
管理"身份实体" |
| identity/entity-alias/* |
管理"别名" |
| identity/entity/id |
通过 ID 精确查询某个身份的信息 |
| identity/entity/name |
通过 名称精确查询某个身份的信息 |
秘密引擎路径 (KV & PKI)
KV-V2 (Key-Value)
kvv2/data/
KV-V2 的路径中必须包含 data/ 才能读写实际数据
kvv2/data/prod/*
kvv2/data/dev/*
PKI (证书颁发机构)
| path |
用途 |
| pki_int/issue/* |
签发证书; 通过请求此路径并指定 Role, Vault 会动态生成私钥和证书; |
| pki_int/revoke |
吊销证书; 将证书序列号加入吊销列表(CRL); |
| pki_int/tidy |
清理操作; 删除过期的证书以释放存储空间, 保持 Vault 性能; |
| pki/config/urls |
配置证书的下载地址和 CRL 分发点; |
Capabilites 动作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
create(POST/PUT) # 允许在指定路径创建数据
read(GET) # 允许读取指定路径的数据
delete(DELETE) # 允许删除指定路径的数据
# 允许修改指定路径的数据; 对多数 Vault 部件来说, 这隐含了在指定位置创建初始值的能力
update(POST/PUT)
# 允许列出指定路径的所有键;
# 要注意的是, 经由 list 操作返回的键是未经策略过滤的;
# 请勿在键名中编码敏感信息; 不是所有后端都支持 list 操作
list(LIST)
# 允许访问需要根权限保护的路径;
# 除非拥有 sudo 能力, 否则令牌被禁止与这些路径交互(对这种路径的操作可能同时需要其他能力, 例如 read 或 delete)
# 例如, 修改审计日志后端配置就需要令牌具有 sudo 特权;
sudo
# 不允许访问;
# 该定义总是优先于其他能力定义, 包括 sudo, 只要能力中存在 deny, 就不允许执行任何操作
deny
|
管理cli
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
vault policy list # 列出策略
vault policy read <policy-name> # read
vault read sys/policy # 列出所有已注册的策略
# create
vault policy write policy-name policy-file.hcl
# update
vault write my-existing-policy updated-policy.json
vault delete sys/policy/policy-name
# 关联策略
## 创建用户时关联策略
vault write auth/userpass/users/user1 \
password="s3cr3t!" \
policies="dev-readonly,logs"
vault login -method="userpass" username="user1"
## 创建令牌时附加策略
vault token create -policy=dev-readonly -policy=logs
|
示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
# 允许对 secret/foo 路径进行读
path "secret/foo" {
capabilities = ["read"]
}
# 允许访问
path "secret/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
# 拒绝访问, 拒绝的优先级最高
path "secret/super-secret" {
capabilities = ["deny"]
}
# 允许创建, 但是只能是限定值
path "secret/restricted" {
capabilities = ["create"]
allowed_parameters = {
"foo" = []
"bar" = ["zip", "zap"]
}
}
# 模糊匹配
path "secret/zip-*" {
capabilities = ["read"]
}
# + 代表路径中一个段内任意长度的字符
path "secret/+/teamb" {
capabilities = ["read"]
}
# 除 bar 外可以对任意 key 设置任意值
path "secret/foo" {
capabilities = ["create"]
allowed_parameters = {
"bar" = ["zip", "zap"]
"*" = []
}
}
path "secret/foo" {
capabilities = ["create"]
denied_parameters = {
"bar" = ["zip", "zap"]
}
}
path "secret/foo" {
capabilities = ["create"]
denied_parameters = {
"*" = []
}
}
|
1
2
3
4
5
6
7
8
9
|
# 允许读取特定路径下的秘密
path "secret/data/mysql/*" {
capabilities = ["read"]
}
# 允许列出秘密列表
path "secret/metadata/mysql/*" {
capabilities = ["list"]
}
|
内置策略
Vault 有两个内建策略: default 和 root
default
默认情况下, 它被附加到所有令牌上, 但可以通过使用身份验证方式创建令牌时显式排除
该策略包含了基础的功能, 例如准许令牌查询有关自身的数据以及使用 Cubbyhole 数据
1
2
3
4
5
6
7
8
|
# 创建令牌时排除 default 策略
vault token create -no-default-policy
curl \
--request POST \
--header "X-Vault-Token: ..." \
--data '{"no_default_policy": "true"}' \
https://vault.hashicorp.rocks/v1/auth/token/create
|
root
任何关联了该策略的用户都将是根用户;
强烈建议在生产环境中使用 Vault 前首先吊销所有的根令牌
1
2
3
4
5
6
7
8
|
# 吊销根令牌
vault token revoke "<token>"
curl \
--request POST \
--header "X-Vault-Token: ..." \
--data '{"token": "<token>"}' \
https://vault.hashicorp.rocks/v1/auth/token/revoke
|
插件
Ethereum Secrets Engine 插件
Vault 变成一个 远程签名机(Remote Signer):
私钥永远不出 Vault 内存, 你只需发送交易摘要给 Vault, 它返回签名后的结果
存储: 私钥经过 Vault 的主密钥加密后存入 Raft
计算: 签名操作在 Vault 内部完成
访问: 你的 Sepolia 节点或应用通过 AppRole 获取一个短期的 Token, 仅能调用 /sign 接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
# 第一步: 启用插, 进入容器执行, 或配置好本地 VAULT_ADDR 后执行
vault secrets enable ethereum
# 第二步: 创建钱包(私钥)
# 让 Vault 生成新钱包, 这会返回一个以太坊地址(如 0xabc...), 但不会返回私钥
vault write ethereum/accounts/my-sepolia-wallet
# 方法 2: 导入现有私钥
vault write ethereum/accounts/import-wallet \
private_key="你的十六进制私钥"
## 第三步: 请求签名(交易)
# 当你的 Sepolia 节点需要发送一笔交易时, 应用构造好交易 RLP 编码或交易 JSON, 发送给 Vault:
# Vault 会返回一个 signed_transaction, 直接将其广播到以太坊网络即可
```bash
vault write ethereum/accounts/my-sepolia-wallet/sign \
transaction='{"to":"0x...","value":"1000000000000000000","gas":21000,"gas_price":"20000000000"}'
|
分层确定性钱包 (HD Wallet)
Vault 支持 BIP-32/BIP-44
在 Vault 中存储一个 助记词 (Mnemonic)
通过不同的路径衍生出无数个地址(如 m/44’/60’/0’/0/1)
只需要备份一次 Vault, 就能管理整个钱包矩阵
deploy
准备镜像
1
|
docker pull hashicorp/vault:1.21
|
https://hub.docker.com/r/hashicorp/vault
dev 模式
不持久化
注意: 添加 VAULT_DEV_ROOT_TOKEN_ID 后会强制为开发模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
services:
vault:
image: hashicorp/vault:1.21
container_name: vault
restart: always
environment:
VAULT_DEV_ROOT_TOKEN_ID: xxxxxxxxxxxxxewofoeiwoiieo
VAULT_ADDR: "=http://0.0.0.0:8200"
TZ: Asia/Shanghai
LANG: en_US.UTF-8
cap_add:
- IPC_LOCK
ports:
- 8200:8200/tcp
|
1
|
docker exec -it vault-dev sh vault status # 输出 Sealed: false 即正常
|
单节点-持久化
1
2
3
4
5
6
7
8
9
10
|
mkdir -p /opt/vault/{config,data,logs}
chown -R 100:100 /opt/vault/ # Vault 默认用户 ID 是 100
docker run -d --name vault-dev \
-p 8200:8200 \
-v /opt/vault/config:/vault/config \
-v /opt/vault/data:/vault/data \
--cap-add=IPC_LOCK \
hashicorp/vault:latest \
server
|
vault.hcl
1
2
3
4
5
6
7
8
9
10
11
12
13
|
api_addr = "http://127.0.0.1:8200"
cluster_addr = "http://127.0.0.1:8201"
ui = true
storage "raft" {
path = "/vault/data"
node_id = "node1"
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_disable = 1 # 开发环境禁用 TLS
}
|
单节点-持久化-compose
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
volumes:
vault_volume:
name: vault_volume
services:
vault:
image: hashicorp/vault:1.21
container_name: vault
restart: always
environment:
VAULT_ADDR: "=http://0.0.0.0:8200"
TZ: Asia/Shanghai
LANG: en_US.UTF-8
cap_add:
- IPC_LOCK
networks:
- core
ports:
- 8200:8200/tcp
volumes:
- vault_volume:/vault
- ./vault.hcl:/config/vault.hcl:ro
command:
- "server"
- "-config=/config/vault.hcl"
labels:
- "service_name=vault"
logging:
options:
labels: "service_name"
|
vault.hcl
1
2
3
4
5
6
7
8
9
10
11
12
|
ui = true # 启用 Web UI
default_lease_ttl = "168h" # 默认租约 7 天
max_lease_ttl = "720h" # 最大租约 30 天
listener "tcp" {
address = "0.0.0.0:8200"
tls_disable = 1
}
storage "file" {
path = "/vault/file"
}
|
三节点模式
Storage: 使用 Raft;
Networking: 节点间通过 8201 端口同步数据;
Auto-Unseal: 建议配合云厂商的 KMS 使用(如阿里云 KMS, AWS KMS)
初始化
会生成 5 个 Unseal Keys
1
|
docker exec -it vault-1 vault operator init
|
解封
每个节点都需要, 输入3/5个分片密钥
docker-compose.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
services:
vault-1:
image: hashicorp/vault:latest
container_name: vault-1
volumes:
- ./vault-1/config:/vault/config
- ./vault-1/data:/vault/data
cap_add:
- IPC_LOCK
command: server
ports:
- "8200:8200"
environment:
VAULT_ADDR: 'http://127.0.0.1:8200'
vault-2:
image: hashicorp/vault:latest
container_name: vault-2
volumes:
- ./vault-2/config:/vault/config
- ./vault-2/data:/vault/data
cap_add:
- IPC_LOCK
command: server
ports:
- "8202:8200"
vault-3:
image: hashicorp/vault:latest
container_name: vault-3
volumes:
- ./vault-3/config:/vault/config
- ./vault-3/data:/vault/data
cap_add:
- IPC_LOCK
command: server
ports:
- "8203:8200"
|
vault-1.hcl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
api_addr = "http://vault-1:8200" # 业务可用地址
cluster_addr = "http://vault-1:8201" # 节点通信地址
ui = true
listener "tcp" {
address = "0.0.0.0:8200"
cluster_address = "0.0.0.0:8201"
tls_disable = 1
}
storage "raft" {
path = "/vault/data"
node_id = "vault-1"
# 初始启动时指定其他节点地址, 或者通过 retry_join 自动发现
retry_join {
leader_api_addr = "http://vault-2:8200"
}
retry_join {
leader_api_addr = "http://vault-3:8200"
}
}
|