跳到主要内容
版本:3.19.0

在 HashiCorp Vault 中管理密钥

HashiCorp Vault 是一个跨不同环境和应用集中管理 Secret 与加密的平台,可统一存储和访问 API Key、密码、证书等敏感信息。

APISIX 支持在配置文件中将敏感数据存储为密钥,例如 admin_key、etcd username、password。

本指南将向你展示如何配置 HashiCorp Vault 作为密钥管理器,然后将 APISIX admin_key 存储在 Vault 中,并在 APISIX 配置文件中引用该密钥。

与 Vault 集成

前置条件​

配置 Vault 服务器​

在 Docker 中以开发模式启动一个名为 apisix-quickstart-vault 的 Vault 实例,Token 为 apisix-quickstart-vault-token。暴露的端口映射到主机上的 8200:

docker run -d --cap-add=IPC_LOCK \
-e 'VAULT_DEV_LISTEN_ADDRESS=0.0.0.0:8200' \
-e 'VAULT_ADDR=http://127.0.0.1:8200' \
-e 'VAULT_DEV_ROOT_TOKEN_ID=apisix-quickstart-vault-token' \
-e 'VAULT_TOKEN=apisix-quickstart-vault-token' \
--network=apisix-quickstart-net \
--name apisix-quickstart-vault \
-p 8200:8200 hashicorp/vault:1.21.4

APISIX 需要访问 Vault 并检索密钥的权限。你应该使用 HashiCorp 配置语言 (HCL) 创建一个策略文件,以为 APISIX 生成 Vault 访问 Token。

在 Vault 实例中创建一个名为 apisix-policy.hcl 的 Vault 策略文件,以授予 APISIX 对路径 secret/ 的读取权限。你可以将密钥放在路径 secret/ 下,以允许 APISIX 读取它们:

docker exec apisix-quickstart-vault /bin/sh -c "echo '
path \"secret/data/*\" {
capabilities = [\"read\"]
}
' > /etc/apisix-policy.hcl"

将策略文件应用到 Vault 实例:

docker exec apisix-quickstart-vault vault policy write apisix-policy /etc/apisix-policy.hcl

接下来,生成附加到新定义策略的访问 Token,以便 APISIX 访问 Vault:

docker exec apisix-quickstart-vault vault token create -policy="apisix-policy"

每次执行上述命令都会生成一个不同的 Token。如果成功,输出应类似于以下内容:

Key Value
--- -----
token hvs.CAESIHUznrV4wgcifUia0FROd6iprK7NjipAiHBYwiZDQP9TGh4KHGh2cy5ndHc5dzBPbXd5Y1pzblZXd2ZuQXA3ZHI
token_accessor YY4iCj2lICDNd50ZJDsBjvZK
token_duration 768h
token_renewable true
token_policies ["apisix-policy" "default"]
identity_policies []
policies ["apisix-policy" "default"]

复制 Token 的值并创建一个名为 apisix-vault-token 的文件以将其存储在 APISIX 实例中:

docker exec apisix-quickstart /bin/sh -c "echo '
hvs.CAESIHUznrV4wgcifUia0FROd6iprK7NjipAiHBYwiZDQP9TGh4KHGh2cy5ndHc5dzBPbXd5Y1pzblZXd2ZuQXA3ZHI
' > /usr/local/apisix/conf/apisix-vault-token"

Vault Agent 在下一步中使用 Token apisix-vault-token 向 Vault 进行身份认证。

配置 Vault Agent​

Vault Agent 是一个客户端守护程序,它与你的应用程序一起运行,并自动执行 Vault 身份认证和 Token 续订。它充当 Vault API 的代理并将 Vault 密钥呈现为文件。

APISIX 中的敏感配置可以存储在 Vault 中,然后 Vault Agent 读取它们并将它们注入到 APISIX 配置文件中,例如 admin_key。

下载 Vault 二进制文件并将其复制到 APISIX 实例中:

export VAULT_VERSION=1.21.4
VAULT_MACHINE_ARCH="$(uname -m)"
case "$VAULT_MACHINE_ARCH" in
x86_64) export VAULT_ARCH=amd64 ;;
aarch64 | arm64) export VAULT_ARCH=arm64 ;;
*) echo "Unsupported architecture: $VAULT_MACHINE_ARCH" >&2; exit 1 ;;
esac
wget "https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_linux_${VAULT_ARCH}.zip"
unzip "vault_${VAULT_VERSION}_linux_${VAULT_ARCH}.zip"
docker cp vault apisix-quickstart:/usr/local/bin/

在 APISIX 实例中创建一个名为 vault-agent-apisix.hcl 的文件,以配置 Vault Agent 如何访问服务器并呈现密钥。

docker exec apisix-quickstart /bin/sh -c "echo '
pid_file = \"./pidfile\"

vault {
address = \"http://apisix-quickstart-vault:8200\"
retry {
num_retries = 5
}
}

auto_auth {
method {
type = \"token_file\"
config = {
token_file_path = \"/usr/local/apisix/conf/apisix-vault-token\"
}
}
}

listener \"tcp\" {
address = \"127.0.0.1:8100\"
tls_disable = true
}

template {
source = \"/usr/local/apisix/conf/config.ctmpl\"
destination = \"/usr/local/apisix/conf/config.yaml\"
}
' > /usr/local/apisix/conf/vault-agent-apisix.hcl"

❶ Vault 地址

❷ 用于身份认证的 Token

❸ Vault Agent 守护程序监听属性

❹ 用于渲染的模板文件

❺ 渲染后的 APISIX 配置文件

Vault Agent 启动后,根据模板文件 config.ctmpl 将密钥注入到 APISIX 配置文件 config.yaml 中。这两个文件都存储在 APISIX 默认配置路径 /usr/local/apisix/conf/ 中。

存储密钥​

创建一个密钥 adminKey=apisix-quickstart-key 并将其存储在 Vault 的路径 secret/apisix/ 中:

docker exec apisix-quickstart-vault vault kv put secret/apisix adminKey=apisix-quickstart-key

预期的响应类似于以下内容:

=== Secret Path ===
secret/data/apisix

======= Metadata =======
Key Value
--- -----
created_time 2023-03-15T11:42:17.123175125Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 1

使用密钥​

基于完整当前 config.yaml 的受保护副本创建 config.ctmpl,保留现有监听器、部署模式、etcd 连接和插件设置。将 deployment.admin.admin_key_required 设置为 true,然后把目标 Admin Key 的值改为以下 Consul Template 表达式:

{{ with secret "secret/apisix" }}{{ .Data.data.adminKey }}{{ end }}

将该表达式放入目标 Admin Key 条目的 key 字段。如果当前配置没有相应条目,请在现有的 deployment.admin 部分下添加。将这些字段合并到完整模板中,不要替换其他部署设置:

config.ctmpl(Admin Key 字段)
deployment:
admin:
admin_key_required: true
admin_key:
- name: admin
key: '{{ with secret "secret/apisix" }}{{ .Data.data.adminKey }}{{ end }}'
role: admin

限制模板和渲染文件的访问权限,将 Admin API 白名单限制为受信任的管理地址,并要求 Admin API 身份验证。请勿把不完整的 deployment 配置块当作整个配置文件使用。

渲染完成后,应先对完整文件运行 apisix test,再重新加载。在验证新密钥之前,请保留原配置,以便在渲染或验证失败时回滚。

在前台运行一次 Vault Agent,并等待所有模板完成渲染。如果渲染成功,请测试并重新加载完整的 APISIX 配置,然后启动持续运行的 Agent。执行以下命令序列前,请停止所有正在使用所配置监听器的 Agent:

docker exec apisix-quickstart vault agent \
-config=/usr/local/apisix/conf/vault-agent-apisix.hcl \
-exit-after-auth=true &&
docker exec apisix-quickstart apisix test &&
docker exec apisix-quickstart apisix reload &&
docker exec -d apisix-quickstart vault agent \
-config=/usr/local/apisix/conf/vault-agent-apisix.hcl

如果渲染或验证失败,请勿继续重新加载。持续运行的 Agent 会更新文件,但在后续密钥变更后不会自动验证或重新加载 APISIX;应用这些变更时,请再次执行验证和重新加载。

验证​

要验证新的 admin_key 是否生效:

  1. 使用正确的 admin_key 请求 Admin API:
curl -i "http://localhost:9180/apisix/admin/routes" -H 'X-API-KEY: apisix-quickstart-key'

预期的响应类似于以下内容:

HTTP/1.1 200 OK
...
  1. 使用错误的 admin_key 请求 Admin API:
curl -i "http://localhost:9180/apisix/admin/routes" -H 'X-API-KEY: wrong-key'

预期的响应类似于以下内容:

HTTP/1.1 401 Unauthorized
...

下一步​

APISIX 支持使用 Vault 管理其他类型的密钥,例如 JWT 和证书。有关其他密钥管理后端,请参阅使用 AWS Secrets Manager 管理密钥和使用 GCP Secret Manager 管理密钥。