Hashicorp vault使用

介绍vault使用场景和使用方法

Hashicorp vault使用

介绍 Intro

Vault是Hashicorp公司开源的一个密码管理仓库软件。可以保存各种secrets,并 且提供包括otp,ldap等各种认证方式来保护这些secrets。

../images/vault/vault-architechure.png◎ ../images/vault/vault-architechure.png

官方文档请参考链接

安装 Install

vault提供二进制文件,可以很方便的安装,具体可以参考文章vault官方安装

如果用k8s可以考虑使用helm安装,这里我是用二进制安装的。

配置补全

1
2
vault -autocomplete-install
source $HOME/.bashrc

配置和启动vault

启动vault可以参考链接启动vault

个人测试
1
vault server -dev

使用vault

vault的组件

../images/vault/vault-process.png◎ ../images/vault/vault-process.png

从vault的功能入手,我们所有的目标都是从vault里面获取需要的token或者key 等机密数据,那么需要经历如下步骤:

  • 认证identify

在vault里面叫Auth Methods。比如我们用ldap登陆我们自己的系统,我们也可 以通过ldap登陆vault的dashboard或者获取token,这个时候ldap就是一种auth methods,同时支持的还有很多,比如user pass, aliyun, token, app role等。

  • 权限校验validate

vault如何根据用户进行权限管理,类似我们的rbac。主要是通过维护若干个 policy进行管理的。比如创建一个策略,允许访问database/*这个kv库。 然后把用户或者app这个实体绑定或者更新包含这个策略。

  • 实际的分配Secrets Engines

用户认证成功并且有权限以后,用户就需要获取对应的实际资源,这个资源是由 对应的secrets engine实现的。

常见的有很多,比如单独存储(KV), 云服务(Aliyun, Tencent, AWS, Azure), 数据库(MongoDB, MySQL/MariaDB, ElasticSearch),证书相关PKI。

当你和对应的secrets engine申请一个credential的时候,他们会调用api最终 生成你想要的东西,并且带上一个期限,vault通过lease进行管理。

vault的命令

具体的使用请参考vault cli reference

这里我简单介绍下我平常用的比较多的命令。

执行命令前的准备

需要注意的是vault默认认为是从127.0.0.1:8200去获取状态导致你第一次命令 可能就报错,正确办法是维护两个环境变量 VAULT_ADDR 具体的vault地址 VAULT_TOKEN 你的vault token,如果你只有用户名密码或者app role id和 secret,你需要做一下通过登陆来获取。

具体方法有如下几个:

  • 登陆vault的dashboard,就是ip:9200或者你设置的负载均衡地址,选择用户 名密码或者ldap或者app,登陆进去以后,点击右上角的下拉菜单和copy token
  • 调用对应的api,如果是app role可以参考
1
curl --request POST     --data '{"role_id":"xxx","secret_id":"yyy"}' https://vault.xxxe.com/v1/auth/approle/login
  • 使用vault命令

使用vault login命令,比如用户密码可以参考

1
vault login -method=userpass username=111 password='xxx'
集群或者vault本身管理相关
1
2
3
vault status # 查看vault状态
vault operator init #初始化集群,危险操作,最终会给你默认5个unseal token用于手动解封
vault operator unseal #手动解封,当vault被重启以后就会自动进入seal状态无法服务,需要用unseal进行解封
policy创建
1
vault policy write xxx xxx.hcl #创建xxx策略

vault的一些思想

以阿里云的动态用户为例,简单介绍下vault的工作流程。

  • 确认secret engine支持

首先目标是阿里云,首先找是否有对应的secret engine支持。发现有,alicloud vault

  • 配置secret engine

配置alicloud并且确认好max_ttl等参数,这里需要注意vault默认是30天的最大 ttl,如果需要修改,可以在vault服务器的配置文件里面进行增加max_lease_ttl = "43800h"类似的参数,默认是720h。

1
2
3
4
vault secrets enable alicloud
vault write alicloud/config \
    access_key=xxx \
    secret_key=yyy

对于一个secrets我们也可以通过vault tune进行后续的设置和修改参数。

  • 创建一个secrets相关的角色,并且确认好ttl等参数。
1
2
3
vault write alicloud/role/policy-based \
    remote_policies='name:AliyunOSSReadOnlyAccess,type:System' \
    remote_policies='name:AliyunRDSReadOnlyAccess,type:System'
  • 把角色授权给我们实际的用户或者用户创建的时候关联下
1
2
3
path "alicloud/creds/policy-based" {
  capabilities = [ "read" ]
}
  • 用户认证通过以后调用creds
1
vault read alicloud/creds/policy-based

vault集成

ldap接入
设置ldap

ldap related https://developer.hashicorp.com/vault/docs/auth/ldap

注意具体和你们自己的ldap配置有关。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
[root@prometheus-bak policy]# vault auth enable ldap
Success! Enabled ldap auth method at: ldap/

[root@prometheus-bak policy]# bash ldap.sh
Success! Data written to: auth/ldap/config
[root@prometheus-bak policy]# cat ldap.sh 
vault write auth/ldap/config \
    url="ldap://ldap.xxx.com" \
    userdn="ou=People,dc=xxx,dc=com" \
    groupdn="ou=People,dc=xxx,dc=com" \
    groupfilter="(&(objectClass=group)(member={{.UserDN}}))"
    groupattr="cn" \
    upndomain="xxx.com" \
    insecure_tls=true \
    starttls=false
ldap policy权限设置
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@prometheus-bak policy]# vault write auth/ldap/groups/sre policies=policy-sre
Success! Data written to: auth/ldap/groups/sre
[root@prometheus-bak policy]# vault write auth/ldap/users/lqx groups=sre policies=policy-lqx
Success! Data written to: auth/ldap/users/lqx

[root@prometheus-bak policy]# vault login -method=ldap username=lqx
Password (will be hidden): 
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.

WARNING! The following warnings were returned from Vault:

Key                    Value
---                    -----
token                  hvs.xxx
token_accessor         yyy
token_duration         768h
token_renewable        true
token_policies         ["default" "policy-lqx" "policy-sre"]
identity_policies      []
policies               ["default" "policy-lqx" "policy-sre"]
token_meta_username    lqx
阿里云接入

假设用户需要一个特定policy-lqx的角色权限,我们发现有则使用,无则创建一 个,创建在上面有说明,支持自定义和系统权限混合

具体文档可以参考 alicloud api https://developer.hashicorp.com/vault/api-docs/secret/alicloud

alicloud文档 https://developer.hashicorp.com/vault/docs/secrets/alicloud

创建一个阿里云ram帐号vault_test,只允许api操作,不允许控制台登录,并且给权限
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
{
  "Statement": [
    {
      "Action": [
        "ram:CreateAccessKey",
        "ram:DeleteAccessKey",
        "ram:CreatePolicy",
        "ram:DeletePolicy",
        "ram:AttachPolicyToUser",
        "ram:DetachPolicyFromUser",
        "ram:CreateUser",
        "ram:DeleteUser",
        "sts:AssumeRole"
      ],
      "Effect": "Allow",
      "Resource": "*"
    }
  ],
  "Version": "1"
}
创建secret engine alicloud-publiccloud

这里我使用aliccloud的publiccloud基础架构的做下演示

进入vault web页面https://vault.xxx.com/ui/vault/secrets ../images/vault/add-secret-engine.png◎ ../images/vault/add-secret-engine.png

选择aliccloud ../images/vault/add-aliccloud.png◎ ../images/vault/add-aliccloud.png

如果希望默认ttl可以设置,后续也可以改,这里我保持默认,点击最下面的 enable engine创建好engine ../images/vault/add-aliccloud-detail.png◎ ../images/vault/add-aliccloud-detail.png

修改使用如下命令

1
2
[root@prometheus-bak ~]# vault secrets tune -default-lease-ttl=86400 alicloud-xxx/config
Success! Tuned the secrets engine at: alicloud-xxx/config/

web打开终端,输入第一步创建的阿里云ram账户的access key,请确保此步执行 成功 ../images/vault/add-vault-alicloud-config.png◎ ../images/vault/add-vault-alicloud-config.png

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
[root@prometheus-bak policy]# cat create_policy.sh 
vault write alicloud-publiccloud/role/policy-lqx  remote_policies='name:AliyunOSSReadOnlyAccess,type:System' \
    inline_policies=-<<EOF
[
    {
      "Statement": [
        {
          "Action": "rds:Describe*",
          "Effect": "Allow",
          "Resource": "*"
        }
      ],
      "Version": "1"
    }
]
EOF

创建完role我们进行policy增加权限

1
2
3
4
[root@prometheus-bak policy]# cat policy-sre.hcl 
path "alicloud-publiccloud/creds/policy-lqx" {
  capabilities = [ "read" ]
}

把这个policy和用户进行绑定或者和token进行绑定,这里使用我的个人ldap进行测 试

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
[root@prometheus-bak policy]# vault login --method=ldap username=lqx
Password (will be hidden): 
Success! You are now authenticated. The token information displayed below
Key                    Value
---                    -----
token                  hvs.CAESICX25V_4dFgh6KZT0KRQA3fSVxaemHUsLjLbaE6opWeXGh4KHGh2cy4yNlhSOGFWQnZUYjNoOEJOV056WkNYcHI
token_accessor         LCJ7IGfKHu3anpyc4DjN4lqR
token_duration         768h
token_renewable        true
token_policies         ["default" "policy-lqx" "policy-sre"]
identity_policies      []
policies               ["default" "policy-lqx" "policy-sre"]
token_meta_username    lqx

调用http api

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
[root@prometheus-bak policy]# curl --header "X-Vault-Token: hvs.CAESICX25V_4dFgh6KZT0KRQA3fSVxaemHUsLjLbaE6opWeXGh4KHGh2cy4yNlhSOGFWQnZUYjNoOEJOV056WkNYcHI" https://vault.ssjj2.com/v1/alicloud-publiccloud/creds/policy-lqx
{
  "request_id": "4dd31dbf-c23b-a294-1455-78ac58019e50",
  "lease_id": "alicloud-publiccloud/creds/policy-lqx/rvL0sbAoXuDW971mkvP2CC6m",
  "renewable": true,
  "lease_duration": 600,
  "data": {
    "access_key": "xxx",
    "secret_key": "yyy"
  },
  "wrap_info": null,
  "warnings": null,
  "auth": null
}

申请好了对应的access key了,对应时间是10min,10min后这个用户会被删除

也可以用vault read alicloud-publiccloud/creds/policy-lqx进行申请

sts支持

关于sts,可以参考这里https://help.aliyun.com/document_detail/39744.html?spm=api-workbench.API%20Explorer.0.0.c2261e0fs8q0Xc

关于role arn,可以看下这里 https://next.api.aliyun.com/api/Sts/2015-04-01/AssumeRole?params={}&tab=DOC

创建一个阿里云角色

publiccloud 里面我创建了一个ram角色 https://ram.console.aliyun.com/roles/vault-test-lqx

复制ARN acs🐏:xxx:role/vault-test-lqx 中间是主账号

创建一个arn role测试
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
[root@prometheus-bak ~]# vault write alicloud-publiccloud/role/role-arn-test role_arn='acs🐏:xxx:role/hastrustedactors'
Success! Data written to: alicloud-publiccloud/role/role-arn-test

[root@prometheus-bak ~]# vault read alicloud-publiccloud/creds/role-arn-test
Key                Value
---                -----
lease_id           alicloud-publiccloud/creds/role-arn-test/hKaZ0tV5AjmhaSFLPMfLTIq0
lease_duration     59m59s
lease_renewable    false
access_key         STS.xxx
expiration         2022-12-15T07:04:33Z
secret_key         yyy
security_token     xxx

可以发现默认获取的是1个小时的sts token

腾讯云接入
安装插件

有问题参考文档 https://github.com/tencentcloudstack/vault-plugin-secrets-tencentcloud

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
git clone https://github.com/tencentcloudstack/vault-plugin-secrets-tencentcloud
yum -y install go
cd vault-plugin-secrets-tencentcloud
go env -w GOPROXY=https://goproxy.cn
go build -o vault/plugins/vault-plugin-secrets-tencentcloud ./cmd/vault-plugin-secrets-tencentcloud/main.go

提示go get就go get提示go mod就go mod

# scp plugin to 73,75,76 /etc/vault.d/plugins
# add plugin_directory to vault.hcl
plugin_directory = "/etc/vault.d/plugins"

注册插件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
[root@prometheus-bak ~]# SHA256=$(sha256sum /etc/vault.d/plugins/vault-plugin-secrets-tencentcloud | cut -d ' ' -f1)

# 依次重启各个vault,建议一个一个升级
[root@prometheus-bak ~]# vault plugin register -sha256=$SHA256 secret vault-plugin-secrets-tencentcloud
Success! Registered plugin: vault-plugin-secrets-tencentcloud
[root@prometheus-bak ~]# vault plugin info secret vault-plugin-secrets-tencentcloud
Key                   Value
---                   -----
args                  []
builtin               false
command               vault-plugin-secrets-tencentcloud
deprecation_status    n/a
name                  vault-plugin-secrets-tencentcloud
sha256                eea1003a64e4e753c2cbb08f378cdebbe612be0b0bdd2f84ea8f6b70d85f6972
version               n/a

# add tencentcloud path for test
[root@prometheus-bak ~]# vault secrets enable -path=tencentcloud vault-plugin-secrets-tencentcloud
Success! Enabled the vault-plugin-secrets-tencentcloud secrets engine at: tencentcloud/
测试
创建路径
1
2
[root@prometheus-bak ~]# vault secrets enable -path=tencentcloud-publiccloud vault-plugin-secrets-tencentcloud
Success! Enabled the vault-plugin-secrets-tencentcloud secrets engine at: tencentcloud-publiccloud/
配置access key和id

新建一个账户vault_test,并且给cam的所有权限

1
2
[root@prometheus-bak ~]#  vault write tencentcloud-publiccloud/config secret_id="xxx" secret_key="xxx"
Success! Data written to: tencentcloud-publiccloud/config
创建一个role
1
2
[root@prometheus-bak policy]# vault write tencentcloud-publiccloud/role/policy-lqx remote_policies='policy_name:ReadOnlyAccess,scope:All'
Success! Data written to: tencentcloud-publiccloud/role/policy-lqx
尝试把权限给lqx
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
[root@prometheus-bak policy]# cat policy-sre.hcl 
path "alicloud-publiccloud/creds/policy-lqx" {
  capabilities = [ "read" ]
}

path "tencentcloud-publiccloud/creds/policy-lqx" {
  capabilities = [ "read" ]
}

# 修改下之前的policy,重新write下
[root@prometheus-bak policy]# vault policy write policy-sre policy-sre.hcl
Success! Uploaded policy: policy-sre
尝试获取credentials
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
[root@prometheus-bak policy]# curl --header "X-Vault-Token: hvs.CAESICX25V_4dFgh6KZT0KRQA3fSVxaemHUsLjLbaE6opWeXGh4KHGh2cy4yNlhSOGFWQnZUYjNoOEJOV056WkNYcHI" https://vault.xxx.com/v1/tencentcloud-publiccloud/creds/policy-lqx
{
  "request_id": "5a78e694-ef03-f0ba-bee5-6a1e4580e26d",
  "lease_id": "tencentcloud-publiccloud/creds/policy-lqx/UHU2BW0OWWpvAPxEr4tFOyQa",
  "renewable": true,
  "lease_duration": 2764800,
  "data": {
    "secret_id": "xxx",
    "secret_key": "yyy"
  },
  "wrap_info": null,
  "warnings": null,
  "auth": null
}

此时有新用户产生,具体不截图了,这个时间长,可以调整默认ttl时间的

尝试revoke
1
2
[root@prometheus-bak policy]# vault lease revoke tencentcloud-publiccloud/creds/policy-lqx/UHU2BW0OWWpvAPxEr4tFOyQa
All revocation operations queued successfully!

发现新建的用户被删掉了,也可以进行renew,加上时间就是续约的时间

ssh支持
one-time password临时密码

具体可以参考链接 ../images/vault/vault-ssh-helper.png◎ ../images/vault/vault-ssh-helper.png

  • 用户访问vault服务获得临时密码
  • 用户ssh要登陆的服务器,输入临时密码
  • ssh服务器的vault ssh agent进行验证
  • 用户成功登陆

具体步骤如下

secrets enable ssh
1
2
[root@vault ~]# vault secrets enable ssh
Success! Enabled the ssh secrets engine at: ssh/
创建一个ssh相关角色
1
2
[root@vault ~]# vault write ssh/roles/otp_ssh_role_in key_type=otp default_user=appops cidr_list=172.16.0.0/12
Success! Data written to: ssh/roles/otp_ssh_role_in

这里可以参考文档 https://developer.hashicorp.com/vault/api-docs/secret/ssh 对于cidr支持列表,支持反向,注意这个cidr指的是管理的ip段,就是你ssh的 目标ip段。

allowed_users="appops,admin"可以指定多个用户 ttl可以指定时间

创建一个policy
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[root@vault vault-agent-test]# cat <<EOF > ssh.hcl 
path "ssh/*" {
  capabilities = [ "list" ]
}
path "ssh/creds/otp_ssh_role_in" {
  capabilities = ["create", "read", "update"]
}
EOF
[root@vault vault-agent-test]# vault policy write ssh_otp ssh.hcl
Success! Uploaded policy: ssh_otp
创建测试用户userpass appops,你也可以使用ldap或者app role
1
2
3
4
[root@vault vault-agent-test]# vault auth enable userpass
Success! Enabled userpass auth method at: userpass/
[root@vault vault-agent-test]# vault write auth/userpass/users/appops password='xxx' policies="ssh_otp"
Success! Data written to: auth/userpass/users/appop
被ssh的服务器需要配置
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@puppetmaster lqx]# wget https://releases.hashicorp.com/vault-ssh-helper/0.2.1/vault-ssh-helper_0.2.1_linux_amd64.zip
[root@puppetmaster lqx]# sudo unzip -q vault-ssh-helper_0.2.1_linux_amd64.zip -d /usr/local/bin
[root@puppetmaster lqx]# ls /usr/local/bin/vault-ssh-helper 
/usr/local/bin/vault-ssh-helper
[root@puppetmaster ~]# cat /etc/vault-ssh-helper.d/config.hcl 
vault_addr="YOUR_VAULT_DOMAIN"
tls_skip_verify = false
ssh_mount_point = "ssh"
allowed_roles = "*"
# change /etc/pam.d/sshd, 头部增加两行
auth requisite pam_exec.so quiet expose_authtok log=/var/log/vault-ssh.log /usr/local/bin/vault-ssh-helper  -config=/etc/vault-ssh-helper.d/config.hcl
auth optional pam_unix.so not_set_pass use_first_pass nodelay
# change sshd,找到对应修改或者添加
KbdInteractiveAuthentication yes / or ChallengeResponseAuthentication yes
UsePAM yes
PasswordAuthentication no
# open another terminal and restart sshd
[root@puppetmaster ~]# systemctl restart sshd
# check ssh
[root@puppetmaster ~]#  vault-ssh-helper -verify-only  -config /etc/vault-ssh-helper.d/config.hcl
2023/08/08 10:11:04 [INFO] using SSH mount point: ssh
2023/08/08 10:11:04 [INFO] using namespace: 
2023/08/08 10:11:04 [INFO] vault-ssh-helper verification successful!
用户侧如何连接

首先无论任何用户都需要有对应的policy,我们之前创建了一个user, pass认证, 这里可以认证一下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
➜  ~ export VAULT_ADDR="https://vault.xxx.com"
➜  ~ APPOPS_TOKEN=$(vault login -method=userpass username=appops password='xxx' -format=json | jq -r '.auth | .client_token')
➜  ~ echo $APPOPS_TOKEN
hvs.CAESIO9AEBxpx7iM_xC3XmKMvpUAKQcbMm2hZIeswsL8ehPOGh4KHGh2cy4yMHVJb2hXaHB5SWl1MFJjVxxx
➜  ~ VAULT_TOKEN=$APPOPS_TOKEN vault write ssh/creds/otp_ssh_role_in ip="172.31.253.73"
Key                Value
---                -----
lease_id           ssh/creds/otp_ssh_role_in/raWEMgiFq76y3XI5A6WE8y7D
lease_duration     768h
lease_renewable    false
ip                 172.31.253.73
key                12581b9e-a6c1-2407-234e-2030340744a1
key_type           otp
port               22
username           appops

可能有如下问题:

  1. uuid 相关问题
1
2
3
2023/08/08 10:54:38 [INFO] using SSH mount point: ssh
2023/08/08 10:54:38 [INFO] using namespace: 
2023/08/08 10:54:38 [ERROR]: uuid is improperly formatted

检查远程用户是否创建了

  1. 没有对应的 vault helper 日志产生

把对应的命令在控制台跑一下看看

  1. pam_unix(sshd:auth): authentication failure

出现这个问题是因为调用pam_unix的时候报错了,这个时候我们应当是不需要再 使用user password认证的,所以我逐个尝试禁止password-auth最终发现是这个 问题, 只需要注释auth这行就好了,在pam系统里面auth用于认证密码,这个引 用会导致失败。

1
\#auth       substack     password-auth
  1. error: PAM: User account has expired for xxx

原因是你禁止的东西太多了,把后面的password-auth都禁用了导致系统不知道 应不应该保持session了。

  1. error: PAM: pam_setcred(): Permission denied

这个错误是少加了一行

1
auth optional pam_unix.so not_set_pass use_first_pass nodelay

最终贴下我的完整的配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
\#%PAM-1.0
auth requisite pam_exec.so quiet expose_authtok log=/var/log/vault-ssh.log /usr/local/bin/vault-ssh-helper -config=/etc/vault-ssh-helper.d/config.hcl
auth optional pam_unix.so not_set_pass use_first_pass nodelay
auth	   required	pam_sepermit.so
\#auth       substack     password-auth
auth       include      postlogin
\# Used with polkit to reauthorize users in remote sessions
-auth      optional     pam_reauthorize.so prepare
account    required     pam_nologin.so
account    include      password-auth
password   include      password-auth
\# pam_selinux.so close should be the first session rule
session    required     pam_selinux.so close
session    required     pam_loginuid.so
\# pam_selinux.so open should only be followed by sessions to be executed in the user context
session    required     pam_selinux.so open env_params
session    required     pam_namespace.so
session    optional     pam_keyinit.so force revoke
session    include      password-auth
session    include      postlogin
\# Used with polkit to reauthorize users in remote sessions
-session   optional     pam_reauthorize.so prepare

另外需要注意上述的操作只会影响vault设置的username,不设置的仍然可以通 过公私钥的方式登陆。

这里一定要注意如果要跳过公私钥认证,可以

1
ssh -o PubkeyAuthentication=no admin@xxx.xxx.xxx.xxx

否则默认还是会通过公私钥登陆的。

signed ssh certificates证书方式登陆

具体参见vault with signed certificates

enable ssh-client-signer && generate ca
1
2
3
4
5
6
[root@vault ~]# vault secrets enable -path=ssh-client-signer ssh
Success! Enabled the ssh secrets engine at: ssh-client-signer/
[root@vault ~]# vault write ssh-client-signer/config/ca generate_signing_key=true
Key           Value
---           -----
public_key    ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCxs8gdW4HkNiJ/FhcIULhCbwk8/We2TYxod85lXaMIrYsXlv6qkP7RPgg5BwhGNlWOiDE3rTKyBccA2bO6DX4wnb5BQ8T8G+2oeku0jZpMZ1Hisq+WrfF2Fedm1+wHHsXQw6DElYyDUpJ0VjxTiKJxJrYkWaet7dEWeAdMfbeYTl+7hKc8qd3hIOfYT5zV6SvjQqkhzoeq9Rm0EPq4Jg1t6XCz9xsmk7T6oXLFJcJTfX8RVIdajewaviAr77RkKvzfu9K4jVr/7gL6Ju0ZiXfoKgIupr9V90qjpG4NXhE4IWCrg9kYtT3iolAmlp8IQmI7gVWrtM3Jg9Y38zAvUhH81P0h0UQBfl7lEpHd3koNJJQ8JF//9oS8Usr8LD6CKGErsPBLo2v9TaxE3aGXczTSgNAe3CYGxI8aN6CwGwWsokUirm7XktA12E5ZE5mnEt4Ws0JSYe52iMCNulmZ8XfZDvNO6QS4u+FZCHzVRI2oztO4i9qWTb3P6QAbKTqR6XESw3fBA7AZxvFeOOMIkhWbZ/PtmhX+0iXHduhIcLjUiD1wCXnUeDwwjLNt8k25t/ZfY+AQM4AUkBJIWUwaYnCUftuApJmIb7AjCdGor2p0IKzbZ0zilT0gIngzHrNIiHKku+DX+ebdzKNrIb48yjtefuulfqul8gqxxxx==
ssh server get ca 要被ssh的机器下载ca
1
2
3
[root@vault ~]# curl -o /etc/ssh/trusted-user-ca-keys.pem  https://vault.xxx.com/v1/ssh-client-signer/public_
key
# add TrustedUserCAKeys /etc/ssh/trusted-user-ca-keys.pem to /etc/ssh/sshd_config and restart sshd
add vault ssh role for sign

注意给你测试的client增加对应的hcl权限

1
2
3
path "ssh-client-signer/sign/ssh-sign" {
  capabilities = ["create", "update"]
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
vault write ssh-client-signer/roles/ssh-sign -<<EOF
{
  "algorithm_signer": "rsa-sha2-256",
  "allow_user_certificates": true,
  "allowed_users": "*",
  "allowed_extensions": "permit-pty,permit-port-forwarding",
  "default_extensions": {
    "permit-pty": ""
  },
  "key_type": "ca",
  "default_user": "ca_test_user",
  "ttl": "30m0s"
}
EOF
client(用户)需要做的事情

把领到的私钥放到服务器上面

1
➜  ~ vault write -field=signed_key ssh-client-signer/sign/ssh-sign public_key=@$HOME/.ssh/id_rsa.pub > ~/.ssh/test-signed-cert.pub

这个时候测试下登陆,我这边没有配置成功,后来发现和ssh客户端有关系,在 另一台centos7.9上面成功了。我自己的debian 12没有成功。

1
2
3
4
5
6
7
[root@puppetmaster ca_test]# ssh  -i id_rsa_ca_test_user  ca_test_user@172.31.253.75
Warning: Permanently added '172.31.253.75' (ECDSA) to the list of known hosts.
Last login: Wed Aug  9 10:30:00 2023 from 172.31.253.73

Welcome to Alibaba Cloud Elastic Compute Service !

[ca_test_user@vault ~]$

目前没找到解决的办法,总之依赖于ca证书就需要解决多个客户端的各种ssh问 题,对于运维成本来说确实比堡垒机要高很多。

也可以参考这篇文章进行查看 https://gist.github.com/kawsark/587f40541881cea58fbaaf07bb82b1be#client-01a---create-key-pair-and-sign-with-vault

数据库支持

关于数据库相关 可以参考vault secrets engine database

支持大部分数据库,包括但不限于

MySQL/MariaDB

mysql平常用的比较多,为了测试兼容性,我用了aliyun的rds进行测试。

enable database and add database connections 添加database密钥仓库并且初始化连接信息
1
2
3
4
5
6
7
8
9
[root@vault ~]# vault secrets enable database                                                                  
Success! Enabled the database secrets engine at: database/
[root@vault ~]# vault write database/config/mysql_vault_test \
     plugin_name=mysql-database-plugin \
     connection_url="{{username}}:{{password}}@tcp(xxx.mysql.rds.aliyuncs.com:3306)/" \
     allowed_roles="mysql_vault_test" \
     username="root" \
     password="xxx"
Success! Data written to: database/config/mysql_vault_test
add mysql role 添加对应的角色
1
2
3
4
5
vault write database/roles/mysql_vault_test \
    db_name=mysql_vault_test \
    creation_statements="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';GRANT SELECT ON *.* TO '{{name}}'@'%';" \
    default_ttl="1m" \
    max_ttl="24h"
给你的主体添加对应的权限

添加policy

1
2
3
4
[root@vault vault-agent-test]# cat mysql-test-policy.hcl 
path "database/creds/mysql_vault_test" {
  capabilities = ["read"]
}

给对应实体添加对应的policy,这里可以去dashboard简单点,如果你是维护在 gitlab等仓库里面或者用terraform管理则更方便啦。

尝试获取creds

首先确认当前登陆用户是你的要测试的用户,尽量避免在主admin账户进行测试 命令如下: vault token lookup

1
2
3
4
5
6
7
8
➜  ~ vault read database/creds/mysql_vault_test
Error reading database/creds/mysql_vault_test: Error making API request.

URL: GET https://vault.xxx.com/v1/database/creds/mysql_vault_test
Code: 500. Errors:

\* 1 error occurred:
	\* failed to find entry for connection with name: "vault_test"

这个时候报错了。后来才发现是db_name这个参数有迷惑性,db_name这里需要配 置成mysql_vault_test才行

再次执行就好了,

1
2
3
4
5
6
7
8
➜  ~ vault read database/creds/mysql_vault_test                                                                    
Key                Value
---                -----
lease_id           database/creds/mysql_vault_test/CA4FQMKc2jDtQQ80y28u4S30
lease_duration     1m
lease_renewable    true
password           rhmM3IEc2u-xsC2m-fgN
username           v-ldap-xxx-mysql_vaul-pNu3jeq9hH

mysql也可以连上了

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
MySQL [(none)]> select user from mysql.user;
+----------------------------------+
| user                             |
+----------------------------------+
| aurora                           |
| lqx_test                         |
| root                             |
| v-ldap-xxx-mysql_vaul-pNu3jeq9hH |
| aliyun_root                      |
| mysql.infoschema                 |
| mysql.session                    |
| mysql.sys                        |
+----------------------------------+
8 rows in set (0.003 sec)

一分钟后用户不见了。

这个好处是密码只需要用户自己去申请或者自动化程序去申请就好了,并且能关 联到人。回收也是自动回收的。

坏处就是不是很方便。但是可以通过开发一个平台或者工单来解决。对于一些平 台,也是可以集成的。

对于代码来说即使泄漏了密码也不会导致问题。在线上服务器上可以通过 vault-agent自动渲染mysql密码,从而加强安全性。

应用接入
创建policy和role

你可以创建一个policy,然后再关联对应的创建的app

1
2
3
4
5
6
7
[root@vault vault-agent-test]# cat vault-role-test-policy.hcl 
path "vault-role-test/*" {
  capabilities = [ "read","list","create","delete" ]
}
path "vault-role-test/data/*" {
  capabilities = [ "read","list", "create", "delete" ]
}

创建app role

1
2
[root@vault vault-agent-test]# vault write auth/approle/role/vault-role-test-api policies="vault-role-test" token_ttl=10m  token_max_ttl=30m
Success! Data written to: auth/approle/role/vault-role-test-api

获取app role的token和secret

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
[root@vault vault-agent-test]# vault read auth/approle/role/vault-role-test-api/role-id
Key        Value
---        -----
role_id    5fa00538-e960-dd8f-f075-72313776bf98
[root@vault vault-agent-test]# vault write -force auth/approle/role/vault-role-test-api/secret-id
Key                   Value
---                   -----
secret_id             xxx-xxx-xxx
secret_id_accessor    62d1318d-d288-0962-ac5a-52ef3807857b
secret_id_num_uses    0
secret_id_ttl         0s
场景1 静态密码

那么我们想象一个场景是我的业务有个配置,某个外部api的用户名密码保存在 vault里面,我们这个业务去机器的/secrets/app-x/identity.json里面读取对 应的用户名和密码。

首先我们帮用户创建好对应的kv名称,让他们写入一组测试的密码到 secrets/vault-role-test/里面,可以通过vault域名进去自己添加,也可以通 过vault命令写入

下面的操作都可以通过登陆vault网页操作,我用命令只是为了方便,不习惯的 可以用页面进行管理。

创建kv vault-role-test

1
2
[root@vault vault-agent-test]# vault secrets enable -path=vault-role-test kv-v1
Success! Enabled the kv-v1 secrets engine at: vault-role-test/

首先需要从app role id和secret id获取token

1
2
[root@vault vault-agent-test]# curl     --request POST     --data '{"role_id":"5fa00538-e960-dd8f-f075-72313776bf98","secret_id":"xxx"}' https://vault.xxx.com/v1/auth/approle/login
{"request_id":"47185b1c-681a-9512-8827-f37e0ea64913","lease_id":"","renewable":false,"lease_duration":0,"data":null,"wrap_info":null,"warnings":null,"auth":{"client_token":"hvs.CAESIG8CjFhqPONJ4nWrCx9a5oXJlNH-OpGqXtsA4tNV3yNNGh4KHGh2cy5wS210MHdRUVdQZ0x4RklLbzNjRnlHNzM","accessor":"eixuOlY6u2RNRPh0FG8w3ObZ","policies":["default","vault-role-test"],"token_policies":["default","vault-role-test"],"metadata":{"role_name":"vault-role-test-api"},"lease_duration":600,"renewable":true,"entity_id":"ba8a55d2-47c4-e057-0347-398fa493405c","token_type":"service","orphan":true,"mfa_requirement":null,"num_uses":0}}

继续模拟用户插入一条数据

1
2
3
4
5
6
7
8
9
[root@vault vault-agent-test]# export VAULT_TOKEN="hvs.CAESIG8CjFhqPONJ4nWrCx9a5oXJlNH-OpGqXtsA4tNV3yNNGh4KHGh2cy5wS210MHdRUVdQZ0x4RklLbzNjRnlHNzM"
[root@vault vault-agent-test]# vault kv put vault-role-test/x x-username="apple" x-password="orange"
Success! Data written to: vault-role-test/x
[root@vault vault-agent-test]# vault kv get vault-role-test/x
======= Data =======
Key           Value
---           -----
x-password    orange
x-username    apple

这个时候我们成功插入了一条数据,并且vault-role-test这个app role可以进 行读取和写入。

这个时候我们使用vault-agent是比较合适的。

我们编写好agent.hcl,并且下载vault的二进制文件。具体可以参考vault-agent install

请确保你的/etc/vault/roleid和/etc/vault/secretid是我们的role对应信息。

 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
[root@vault vault-agent-test]# cat agent.hcl 
auto_auth {
  method {
    type = "approle"

    config = {
      role_id_file_path = "/etc/vault/roleid"
      secret_id_file_path = "/etc/vault/secretid"
    }
  }

  sinks {
    sink {
      type = "file"

      config = {
        path = "/tmp/vault-role-test"
      }
    }
  }
}


[root@vault vault-agent-test]# vault agent -config=agent.hcl
==> Vault agent started! Log data will stream in below:

==> Vault agent configuration:

                     Cgo: disabled
               Log Level: info
                 Version: Vault v1.12.2, built 2022-11-23T12:53:46Z
             Version Sha: 415e1fe3118eebd5df6cb60d13defdc01aa17b03

2023-08-02T15:22:20.548+0800 [INFO]  sink.file: creating file sink
2023-08-02T15:22:20.548+0800 [INFO]  sink.file: file sink configured: path=/tmp/vault-role-test mode=-rw-r-----
2023-08-02T15:22:20.550+0800 [INFO]  template.server: starting template server
2023-08-02T15:22:20.550+0800 [INFO]  template.server: no templates found
2023-08-02T15:22:20.550+0800 [INFO]  auth.handler: starting auth handler
2023-08-02T15:22:20.550+0800 [INFO]  auth.handler: authenticating
2023-08-02T15:22:20.550+0800 [INFO]  sink.server: starting sink server
2023-08-02T15:22:20.591+0800 [INFO]  auth.handler: authentication successful, sending token to sinks
2023-08-02T15:22:20.591+0800 [INFO]  auth.handler: starting renewal process
2023-08-02T15:22:20.591+0800 [INFO]  sink.file: token written: path=/tmp/vault-role-test
2023-08-02T15:22:20.601+0800 [INFO]  auth.handler: renewed auth token

[root@vault ~]# cat /tmp/vault-role-test
hvs.CAESIOyTVeDW2CCfQchEzV_uDh1qzNd9f0eZqvIBEWgdVFj9Gh4KHGh2cy41WGJqYVhrdjRnU3U0NklGd3B1dVlwYTA

当我们启动以后发现/tmp/vault-role-test有了对应的token,这个也就是相当 于帮我们执行了login的操作。这个是auto-auth的功能。

我们可以继续延展下我们的使用,我们需要它能映射x-username和x-password到 我们的/secrets/app-x/identity.json文件。这里原则上可以template解决。

使用vault template。这里大家一定要注意自己的vault版本,我的是v1.12暂时 不支持generate-config等高级操作。template编写的时候注意"需要转义一下。

 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
auto_auth {
  method {
    type = "approle"

    config = {
      role_id_file_path = "/etc/vault/roleid"
      secret_id_file_path = "/etc/vault/secretid"
    }
  }

  sinks {
    sink {
      type = "file"

      config = {
        path = "/tmp/vault-role-test"
      }
    }
  }
}

template_config {
  static_secret_render_interval = "5m"
  exit_on_retry_failure         = true
}

vault {
  address = "https://vault.xxx.com"
}

template  {
  contents             = "{{ with secret \"vault-role-test/x\" }}{\"username\": \"{{ .Data.x_username }}\", \"password\": \"{{ .Data.x_password}}\"}{{ end }}"
  destination          = "/secrets/app-x/identity.json"
  error_on_missing_key = true
}

exec {
  command                   = ["./test.sh"]
  restart_on_secret_changes = "always"
  restart_stop_signal       = "SIGTERM"
}

这样操作完以后,在我的identity就有新的json了。

1
2
[root@vault vault-agent-test]# cat /secrets/app-x/identity.json 
{"username": "apple", "password": "orange"}
场景2 动态ak

另一个场景是包含lease的动态token情况下,比如用户每次去调用阿里云服务, 通过此方式实现动态ak的效果。

目前动态ak的思路,可以参考auto auth的思路,但是这个需要用户有一个ak, 这个和我们的初衷有点不一样,我们希望只给用户一个app role id和role secret, 剩下的就让vault-agent生成(我提了个issue,估计他们不一定做~, 后来发现这个是支持的), 目前看如果是vault-agent的方法,目前我这边有三个办法:

  • 利用auto auth这个腾讯云和阿里云都有对应的method

aliyun https://developer.hashicorp.com/vault/docs/agent-and-proxy/autoauth/methods/alicloud

利用template file,我们也可以自动生成aliyun的ak

这里注意template file的配置

 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
[root@vault vault-agent-test]# cat aliyun-role-ak.hcl 
auto_auth {
  method {
    type = "approle"

    config = {
      role_id_file_path = "/etc/vault/lqx_test-roleid"
      secret_id_file_path = "/etc/vault/lqx_test-secretid"
      remove_secret_id_file_after_reading = false
    }
  }
}

template_config {
  static_secret_render_interval = "5m"
  exit_on_retry_failure         = true
}

vault {
  address = "https://vault.xxx.com"
}

template  {
  contents             = "{{ with secret \"alicloud-xxx/creds/lqx_test\" }}{\"access_key\": \"{{ .Data.access_key }}\", \"secret_key\": \"{{ .Data.secret_key}}\"}{{ end }}"
  destination          = "/secrets/app-x/identity.json"
  error_on_missing_key = true
}

如果有自定义ttl需求,这个时候注意你创建aliyun role的ttl设置

1
vault write alicloud-xxx/role/lqx_test   credential_ttl=300 remote_policies='name:AliyunECSReadOnlyAccess,type:System'

这样就能控制模板的生成时间了,默认我没法找到传ttl参数的地方

  • 开发全部用api调用aliccloud/creds获取对应的临时token,并且判断过期等

这个办法就是比较麻烦需要开发接入,并且需要有个定时刷新或者每次判断是否 过期,实际接入会比较难受

毫无疑问,第一个方案更好

场景3 golang代码里面直接访问
场景4 python代码直接访问
场景5 awx或者ansible里面访问
场景6 k8s里面访问
vault本身配置管理

vault本身随着设置越来越多,我们对于配置一致性就会要求越来越高,这个时 候可以引入IAC工具进行管理,常见的可以是puppet,ansible,terraform等。

terraform和vault同属一家公司,支持肯定也会方便,这里以terraform为例进 行vault的固化,简化vault的运维管理,避免一大堆的本地hcl和create role脚 本。

链接请参考集成文档最佳实践视频

增加audit审计
file类型
 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
59
60
61
62
63
64
65
66
67
[root@prometheus-bak policy]# touch /var/log/vault.log
[root@prometheus-bak policy]# chown -R vault /var/log/vault.log
[root@prometheus-bak policy]# vault audit enable file file_path=/var/log/vault.log
Success! Enabled the file audit device at: file/
[root@prometheus-bak policy]# tail -f /var/log/vault.log
{
  "time": "2022-12-14T08:50:37.281050158Z",
  "type": "response",
  "auth": {
    "client_token": "hmac-sha256:c59b3c1f9e2982606de36be5fad5a9a0a0f88d3e78496ca5a4b22d44e8c9bba5",
    "accessor": "hmac-sha256:bec550feb46e175c6d017879c1e978a1f8d9bef05acd1075f11f11a283b9ca3b",
    "display_name": "ldap-lqx",
    "policies": [
      "default",
      "policy-lqx",
      "policy-sre"
    ],
    "token_policies": [
      "default",
      "policy-lqx",
      "policy-sre"
    ],
    "policy_results": {
      "allowed": true,
      "granting_policies": [
        {
          "name": "policy-sre",
          "namespace_id": "root",
          "type": "acl"
        }
      ]
    },
    "metadata": {
      "username": "lqx"
    },
    "entity_id": "a5851c83-1ffc-b2b7-ae9f-6af9af3264d3",
    "token_type": "service",
    "token_ttl": 2764800,
    "token_issue_time": "2022-12-14T16:50:28+08:00"
  },
  "request": {
    "id": "5cefe863-d4ba-52c1-7bf5-c0185c252f76",
    "client_id": "a5851c83-1ffc-b2b7-ae9f-6af9af3264d3",
    "operation": "read",
    "mount_type": "alicloud",
    "mount_accessor": "alicloud_e21289d1",
    "client_token": "hmac-sha256:d57d03e207cd0d39f1219c897458a5dd0d45af2dad105cb66542c4de9b3d4f25",
    "client_token_accessor": "hmac-sha256:bec550feb46e175c6d017879c1e978a1f8d9bef05acd1075f11f11a283b9ca3b",
    "namespace": {
      "id": "root"
    },
    "path": "alicloud-publiccloud/creds/policy-lqx",
    "remote_address": "127.0.0.1",
    "remote_port": 60744
  },
  "response": {
    "mount_type": "alicloud",
    "mount_accessor": "alicloud_e21289d1",
    "secret": {
      "lease_id": "alicloud-publiccloud/creds/policy-lqx/lYyx5l0bsfMtDOHDZ273R1nR"
    },
    "data": {
      "access_key": "hmac-sha256:640d607780d126ab8f29a8e28058e247dc3233751bad3922411dba7531d587ad",
      "secret_key": "hmac-sha256:556a23a1fb3d7fe775730f548986e1b56388d9366203876c5e7dbea3f5c5f29d"
    }
  }
}

生产部署

如果用k8s里面的部署方式,一般helm会帮你配置好,我这里没有测试过。

如果是服务器部署,我这边使用的是如下的部署方式consul+vault集群方式配合 auto unseal,你也可以配置通过mysql集群方式部署。

这里解释下seal,seal的本意是密封,当服务器被重启或者vault服务重启以后, vault会进入密封状态,需要提供对应的vault unseal token才可以。但是我们 又不方便在服务器上面暴露unseal token,所以另搞一个unseal的vault用于 unseal这个集群。

若干vault服务器配置73等

 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
# Full configuration options can be found at https://www.vaultproject.io/docs/configuration
ui = true
api_addr = "http://172.31.253.73:8200"
cluster_addr = "http://172.31.253.73:8201"
plugin_directory = "/etc/vault.d/plugins/"
storage "consul" {
  address = "127.0.0.1:8500"
  path    = "vault-xxx"
  token = "c54be713-5266-b9ef-17b6-xxx"
}

# HTTP listener
listener "tcp" {
  address = "0.0.0.0:8200"
  tls_disable = 1
}

# 用于auto unseal
seal "transit" {
  address = "http://172.31.253.75:8200"
  disable_renewal = "false"
  token = "hvs.xxx"
  key_name = "autounseal"
  mount_path = "transit/"
  tls_skip_verify = "true"
}

autoseal服务器75

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# Full configuration options can be found at https://www.vaultproject.io/docs/configuration

ui = true
api_addr = "http://172.31.253.75:8200"
#mlock = true
#disable_mlock = true
plugin_directory = "/etc/vault.d/plugins/"

storage "file" {
  path = "/opt/vault/data"
}

# HTTP listener
listener "tcp" {
  address = "0.0.0.0:8200"
  tls_disable = 1
}

prometheus监控

建议把服务器的vault seal的状态进行监控,避免服务异常。

1
2
3
4
5
6
7
8
[root@vault xxx]# vault policy write prometheus-metrics - << EOF
 path "/sys/metrics" {
   capabilities = ["read"]
 }
EOF
Success! Uploaded policy: prometheus-metrics

[root@vault xxx]# vault token create    -field=token -policy prometheus-metrics > prometheus-vault.token

这里要注意配置完成以后可能会报错,expected a valid start token, 啥的, 原因是因为vault还需要加个配置,不加这个?format=prometheus就无法访问。

1
2
3
4
telemetry {
  prometheus_retention_time = "30s"
  disable_hostname = true
}

如果提示认证失败,则可能token过期或者你的集群访问错了机器,建议用对外 的暴露的域名。

告警策略目前我发现vault_core_unsealed == 0无法告警,我用了up{job=xxx}的 方式来告警。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
- alert: VaultJobSealed
  expr: up{job="vault"} == 0
  for: 0m
  labels:
    severity: warning
    alert_ding: "消息测试群"
    alert_group: "xxx"

  annotations:
    summary: Vault sealed (instance {{ $labels.instance }})
    description: "Vault instance 被密封了 实例是 {{ $labels.instance }}\n  VALUE = {{ $value }}\n  LABELS = {{ $labels }}"

其他类似的可以从awesome rules vault里面查看

其他

admin policy example

copied from https://community.opengroup.org/osdu/tutorials/osdu-tutorials-cicd/-/blob/5cc751d5f37a876f5849b27d04f5ea6aadf2ebc3/vault/policies/examples/admin-policy.hcl

 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
# Manage auth methods broadly across Vault
path "auth/*"
{
  capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}

# Create, update, and delete auth methods
path "sys/auth/*"
{
  capabilities = ["create", "update", "delete", "sudo"]
}

# List auth methods
path "sys/auth"
{
  capabilities = ["read"]
}

# List existing policies
path "sys/policies/acl"
{
  capabilities = ["list"]
}

# Create and manage ACL policies
path "sys/policies/acl/*"
{
  capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}

# List, create, update, and delete key/value secrets
path "secret/*"
{
  capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}

# Manage secrets engines
path "sys/mounts*"
{
  capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}

# Read health checks
path "sys/health"
{
  capabilities = ["read", "sudo"]
}

vault重装

属于风险操作,执行前请确认vault不在集群中

1
vault operator init

vault auto unseal

unseal服务器或者集群安装好vault 参考 https://developer.hashicorp.com/vault/tutorials/auto-unseal/autounseal-transit

https://developer.hashicorp.com/vault/docs/concepts/seal

 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
[root@test0 ~]# vault secrets enable transit
Success! Enabled the transit secrets engine at: transit/
[root@test0 ~]# vault write -f transit/keys/autounseal
Success! Data written to: transit/keys/autounseal
[root@test0 ~]# tee autounseal.hcl <<EOF
> path "transit/encrypt/autounseal" {
>    capabilities = [ "update" ]
> }
> 
> path "transit/decrypt/autounseal" {
>    capabilities = [ "update" ]
> }
> EOF
path "transit/encrypt/autounseal" {
   capabilities = [ "update" ]
}

path "transit/decrypt/autounseal" {
   capabilities = [ "update" ]
}

[root@test0 ~]# vault policy write autounseal autounseal.hcl
Success! Uploaded policy: autounseal


[root@test0 ~]# vault token create -orphan -policy="autounseal" -wrap-ttl=120 -period=24h
Key                              Value
---                              -----
wrapping_token:                  hvs.xxx
wrapping_accessor:               xxx
wrapping_token_ttl:              2m
wrapping_token_creation_time:    2023-01-06 10:43:15.344848018 +0800 CST
wrapping_token_creation_path:    auth/token/create
wrapped_accessor:                xxx

上面这个时间比较少,所以最好还是设置成几年,对于vault unseal来说,

具体可以在unseal的vault上面配置这个并且重启

1
max_lease_ttl = "43800h"

前面都是没问题的 后面记得要auto unseal的集群添加如下配置

1
2
3
4
5
6
7
8
seal "transit" {
  address = "http://unseal那个机器or集群的ip:8200"
  disable_renewal = "false"
  token = "hvs.xxx" # 这个配置很重要
  key_name = "autounseal"
  mount_path = "transit/"
  tls_skip_verify = "true"
}

这个时候重启vault集群的这台vault

发现集群进去seal状态了,看日志需要migrate,因为我们设置了自动解封,所 以vault认为需要把原来的unseal key转成recovery key

1
2
3
4
5
2023-01-06T11:00:27.426+0800 [WARN]  core: entering seal migration mode; Vault will not automatically unseal even if using an autoseal: from_barrier_type=shamir to_barrier_type=transit
2023-01-06T11:00:27.426+0800 [INFO]  core: Initializing version history cache for core
2023-01-06T11:00:35.575+0800 [WARN]  core: stored keys supported on init, forcing shares/threshold to 1
2023-01-06T11:01:05.257+0800 [WARN]  core: stored keys supported on init, forcing shares/threshold to 1
2023-01-06T11:03:15.800+0800 [WARN]  core: stored keys supported on init, forcing shares/threshold to 1

这个时候执行任何命令都不行了

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
[root@vault-prod ~]# vault operator init
Error initializing: Error making API request.

URL: PUT http://localhost:8200/v1/sys/init
Code: 400. Errors:

\* Vault is already initialized
[root@vault-prod ~]# vault operator rekey
Error getting rekey status: Error making API request.

URL: GET http://localhost:8200/v1/sys/rekey/init
Code: 503. Errors:

\* Vault is sealed

需要执行unseal -migrate

1
2
3
vault operator unseal -migrate xxx
vault operator unseal -migrate xxx
vault operator unseal -migrate xxx

执行完以后,发现vault进入unseal状态了,这个时候重启它,也不会seal了。

测试 stop掉集群的一台

1
2
3
4
5
6
7
1月 06 11:25:45 vault-prod vault[1737]: ==> Vault shutdown triggered
1月 06 11:25:45 vault-prod vault[1737]: 2023-01-06T11:25:45.488+0800 [INFO]  core: marked as sealed
1月 06 11:25:45 vault-prod vault[1737]: 2023-01-06T11:25:45.488+0800 [INFO]  service_registration.consul: shut
1月 06 11:25:59 vault-prod vault[1737]: 2023-01-06T11:25:59.628+0800 [INFO]  core: stopping cluster listeners
1月 06 11:25:59 vault-prod vault[1737]: 2023-01-06T11:25:59.628+0800 [INFO]  core.cluster-listener: forwarding
1月 06 11:26:00 vault-prod systemd[1]: Stopped "HashiCorp Vault - A tool for managing secrets".
1月 06 11:26:26 vault-prod systemd[1]: Starting "HashiCorp Vault - A tool for managing secrets"...

我们发现vault变成sealed了,再开

1
2
3
4
5
6
7
8
9
1月 06 11:26:27 vault-prod vault[2580]: 2023-01-06T11:26:27.034+0800 [INFO]  proxy environment: http_proxy="" 
1月 06 11:26:27 vault-prod vault[2580]: 2023-01-06T11:26:27.034+0800 [WARN]  storage.consul: appending trailin
1月 06 11:26:27 vault-prod vault[2580]: 2023-01-06T11:26:27.087+0800 [INFO]  core: Initializing version histor
1月 06 11:26:27 vault-prod vault[2580]: 2023-01-06T11:26:27.087+0800 [INFO]  core: stored unseal keys supporte
1月 06 11:26:27 vault-prod vault[2580]: 2023-01-06T11:26:27.095+0800 [INFO]  core.cluster-listener.tcp: starti
1月 06 11:26:27 vault-prod vault[2580]: 2023-01-06T11:26:27.095+0800 [INFO]  core.cluster-listener: serving cl
1月 06 11:26:27 vault-prod vault[2580]: 2023-01-06T11:26:27.095+0800 [INFO]  core: vault is unsealed
1月 06 11:26:27 vault-prod vault[2580]: 2023-01-06T11:26:27.095+0800 [WARN]  service_registration.consul: conc
1月 06 11:26:27 vault-prod vault[2580]: 2023-01-06T11:26:27.095+0800 [INFO]  core: unsealed with stored key

发现自动被unseal的了