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

image-20250806111735993

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

image-20250806111838077

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

image-20250806111920434

接下来的操作尽量都是在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,就可以用了。