配置密钥管理
API7 企业版支持密钥提供方,可避免硬编码 API Key(API 密钥)、SSL 证书和插件凭证等敏感数据。通过 $secret:// 引用语法,可以将外部系统中的密钥注入网关资源,同时将密钥值保留在外部系统中。
密钥提供方通过 Admin API 创建和管理。ADC 不管理密钥提供方,但可以在支持的资源中使用 $secret://... 引用现有密钥提供方中的密钥。
前置条件
- API7 企业版实例正在运行。
- 已创建网关组且网关实例正在运行。
- 按照从控制台获取令牌中的步骤准备一个令牌。
- 如果要测试网关完整的密钥解析流程,需要可用的密钥后端。
配置 HashiCorp Vault 密钥提供方
HashiCorp Vault 可用于管理密钥。可以在 API7 企业版中将其配置为密钥提供方。
启动 Vault 进行评估
如果已有 Vault 和供 API7 企业版使用的受限令牌,可跳过本节。否则,请启动一个开发模式的 Vault 容器,并将 KV v1 引擎挂载到 kv/:
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=api7-quickstart-vault-token' \
-e 'VAULT_TOKEN=api7-quickstart-vault-token' \
--name api7-quickstart-vault \
-p 8200:8200 vault:1.13.0
docker exec api7-quickstart-vault vault secrets enable -path=kv -version=1 kv
如果要改用 KV v2,请按以下方式调整上述步骤(一个挂载路径只能承载一个引擎,因此 v1 和 v2 不能共存于 kv/):
- 使用
vault secrets enable -path=kv kv-v2替代-version=1 kv命令启用引擎。 - 策略路径使用
kv/data/api7/*,因为 KV v2 会将密钥存储在<mount>/data/<path>下。 - 注册密钥提供方时设置
"kv_version": "kv-v2"。
创建网关策略和令牌
授予网关读取 kv/api7/* 的权限并创建受该策略限制的令牌:
docker exec api7-quickstart-vault /bin/sh -c "echo '
path \"kv/api7/*\" {
capabilities = [\"read\"]
}
' > /etc/api7-policy.hcl"
docker exec api7-quickstart-vault vault policy write api7-policy /etc/api7-policy.hcl
docker exec api7-quickstart-vault vault token create -policy="api7-policy"
token create 命令会输出一个 hvs.... 令牌。请保存该值,并在下一步注册密钥提供方时使用。
写入测试密钥
在该前缀下存储一个密钥,以便网关能够解析实际内容:
docker exec api7-quickstart-vault vault kv put kv/api7/demo key=demo-value
下面的在配置中引用密钥将展示如何将其作为 $secret://vault/my-vault/demo/key 使用。
注册 Vault 密钥提供方
注册 Vault 时传入上一步生成的令牌。使用 host.docker.internal 而不是 127.0.0.1,确保该 URL(从网关容器内部访问时)解析到主机上的 Vault;在 Docker 容器中,127.0.0.1 指向网关自身。在 Docker Desktop 上该配置开箱即用;在 Linux 上运行 Docker 时,可以使用 --add-host=host.docker.internal:host-gateway 启动网关,或者将两个容器连接到同一用户自定义网络,并使用 Vault 容器名称(例如 http://api7-quickstart-vault:8200)。
curl -k "https://localhost:7443/apisix/admin/secret_providers/vault/my-vault?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-d '{
"uri": "http://host.docker.internal:8200",
"prefix": "kv/api7",
"token": "hvs.example-vault-token"
}'
配置 AWS Secrets Manager
如果基础设施运行在 AWS 上,可以使用 AWS Secrets Manager 存储 API 密钥。按照 AWS Secrets Manager 文档创建密钥和具有读取权限的 IAM 凭证,再使用得到的 access_key_id、secret_access_key 和 region 注册密钥提供方:
curl -k "https://localhost:7443/apisix/admin/secret_providers/aws/my-aws?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-d '{
"access_key_id": "AKIAxxxxxxxx",
"secret_access_key": "xxxxxxxx",
"region": "us-east-1"
}'
配置 Kubernetes Secrets 密钥提供方
在 Kubernetes 原生部署中,可以直接使用 Kubernetes Secret 作为密钥提供方。按照 Kubernetes Secrets 文档创建 Secret 和对 secrets 资源具有 get 权限的 ServiceAccount,再使用集群 API Server 地址和 ServiceAccount 令牌注册密钥提供方:
curl -k "https://localhost:7443/apisix/admin/secret_providers/kubernetes/my-k8s?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"apiserver_addr": "https://kubernetes.default.svc",
"token": "example-service-account-token"
}'
在配置中引用密钥
使用 $secret://{provider_type}/{provider_id}/{secret_key} 语法引用密钥。
在 SSL 证书中使用密钥
你可以引用密钥提供方中的密钥,避免以明文存储私钥。
- Admin API
- ADC
curl -k "https://localhost:7443/apisix/admin/ssls/example-com-ssl?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"snis": ["example.com"],
"cert": "$secret://vault/my-vault/ssl/cert",
"key": "$secret://vault/my-vault/ssl/key"
}'
ssls:
- id: example-com-ssl
snis:
- example.com
certificates:
- certificate: "$secret://vault/my-vault/ssl/cert"
key: "$secret://vault/my-vault/ssl/key"
在插件配置中使用密钥
密钥也可以用于插件凭证,例如 key-auth 插件的 key 字段(即 API Key):
- Admin API
- ADC
curl -k "https://localhost:7443/apisix/admin/consumers/user-1/credentials/user-1-key?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "user-1-key",
"plugins": {
"key-auth": {
"key": "$secret://vault/my-vault/consumer/api-key"
}
}
}'
consumers:
- username: user-1
credentials:
- name: user-1-key
type: key-auth
config:
key: "$secret://vault/my-vault/consumer/api-key"