Vault是个很厉害的 secret 引擎了,不多说了,主要用于集中管理各种密码、密钥。
用来管理Kubernetes的凭据相当好,但是我们通常是自己开发的程序,然后需要读各种配置文件,比如连接DB的用户名,密码等等,最后连接到数据库。
那么这种情况下,如果管理好配置项呢?
方法如下,用approle读取Vault的配置信息:
一、启动vault引擎测试环境
首先启动vault引擎,测试,用Docker,方便创建和销毁
# 启动容器
# 我们手动指定了ROOT_TOKEN是root,这只用于测试环境
docker run -d --rm \
--add-host host.docker.internal:host-gateway \
--cap-add=IPC_LOCK \
--name vault \
-p 8200:8200 \
-e VAULT_DEV_ROOT_TOKEN_ID=root \
-e VAULT_DEV_LISTEN_ADDRESS=0.0.0.0:8200 \
hashicorp/vault
--add-host host.docker.internal:host-gateway
这个个参数的作用是在容器的 /etc/hosts 文件中添加一个主机名和 IP 地址的映射。
--add-host: 这是docker run的一个选项,用来在容器的/etc/hosts文件中添加一个自定义的主机条目。host.docker.internal: 这是主机名。在 Docker Desktop(macOS 和 Windows)中,host.docker.internal是一个特殊的 DNS 名称,它会被解析为宿主机的内部 IP 地址。host-gateway: 这是docker在较新版本中引入的一个特殊关键字。它代表了宿主机与 Docker 网络之间的网关 IP 地址。在许多 Linux 环境中,这个关键字会指向 Docker 的网桥 IP(例如172.17.0.1)。
综合起来,--add-host host.docker.internal:host-gateway 的作用是:
在容器内部创建一个 DNS 条目,将 host.docker.internal 这个名字映射到宿主机的 IP 地址。这使得容器中的应用程序可以通过 host.docker.internal 这个域名来访问宿主机上运行的服务,而无需知道宿主机的具体 IP 地址。
这对于开发环境非常有用,比如你的 Vault 容器需要访问在宿主机上运行的数据库或认证服务。
容器跑起来之后我们验证一下:
export VAULT_ADDR="http://127.0.0.1:8200"
export VAULT_TOKEN="root"
vault status

然后我们打开浏览器:http://x.x.x.x:8200,使用Token root登录

看看有啥secret引擎,还真不少

接下来的操作尽量都是在CLI命令行完成了。
二、初始化各种配置信息
export VAULT_ADDR="http://127.0.0.1:8200"
export VAULT_TOKEN="root"
# 放入测试数据
vault kv put secret/dbinfo user=root pass=test123
# 设置approle的认证方式
vault auth enable approle
# 编辑一个policy文件,agent-policy.hcl
cat < EOF > agent-policy.hcl
path "secret/data/dbinfo" {
capabilities = ["read"]
}
EOF
# 写入policy
vault policy write agent-policy agent-policy.hcl
# 建立AppRole 并附加policy
vault write auth/approle/role/vault-agent-role policies="agent-policy"
# gen出 role-id 和 secret-id
vault read auth/approle/role/vault-agent-role/role-id
vault write -f auth/approle/role/vault-agent-role/secret-id
# 把 role-id 和 secert-id 放入文件
vault read -field role_id auth/approle/role/vault-agent-role/role-id > role-id
或
vault read auth/approle/role/vault-agent-role/role-id -format=json | jq -r .data.role_id > role-id
# 注意,每次写都会变的
vault write -f -field secret_id auth/approle/role/vault-agent-role/secret-id > secret-id
或
vault write -f auth/approle/role/vault-agent-role/secret-id -format=json | jq -r .data.secret_id > secret-id
unset VAULT_ADDR
unset VAULT_TOKEN
注意上面一系列操作,跟IAM的操作基本一摸一样,如出一辙,先定义policy,然后policy附加role,role再gen出role-id和secret-id
那role-id就相当于username,那secret-id就相当于password,这么理解就对了。
三、配置Vault Agent代理,动态从Vault获取配置信息,并通过模板输出
设置vault-agent.hcl:
vault {
address = "http://127.0.0.1:8200"
token = "root"
}
auto_auth {
method {
type = "approle"
config = {
role_id_file_path = "./role-id"
secret_id_file_path = "./secret-id"
remove_secret_id_file_after_reading = false
}
}
sink {
type = "file"
config = {
path = "./vault-agent-token"
}
}
}
template {
source = "./env.tmpl"
destination = "./.env"
}
设置模板文件env.tmpl:
DB_USER={{ with secret "secret/data/dbinfo" }}{{ .Data.data.user }}{{ end }}
DB_PASS={{ with secret "secret/data/dbinfo" }}{{ .Data.data.pass }}{{ end }}
启动
vault agent -config=./agent.hcl -log-level=debug
然后检查.env
cat .env
DB_USER=root
DB_PASS=test123
cat vault-agent-token
hvs.CAESILRWC98usmzSfxdJRMnKWUlvT9kFV1zzPfrkGgdBInYfGh4KHGh2cy54NHhEQnNUa2pmTzU5NTlRN1234567890
这样就ok了,但是这样也有个大麻烦,那就是token,如果重启token变了,那必须重新灌入。
最后,放上agent的systemd文件/etc/systemd/system/vault-agent.service:
[Unit]
Description=Nomad Agent
Requires=consul-online.target
After=consul-online.target
[Service]
KillMode=process
KillSignal=SIGINT
ExecStart=/usr/local/bin/vault agent -config /etc/vault-agent.d/vault-agent.hcl
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=2
StartLimitBurst=3
StartLimitIntervalSec=10
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
关于Root Token
第一次运行的时候,vault operator init 会得到这个这个Token
随后呢,再得到这个,就必须 vault operator generate-root了,必须unseal key。
再随后,用vault login,就可以用了。