跳到主要内容

使用 Keyring 加密数据

数据加密是 APISIX 的一个关键考虑因素。在实施身份认证或与另一个系统集成时,网关配置中经常会出现敏感信息,例如用户密码和私钥。为了防止这些信息被恶意行为者拦截和利用,APISIX 对这些信息进行加密,并将其转换为难以理解的密文进行存储。无论何时需要,密文都可以使用正确的密钥转换回明文。

在 APISIX 中,启用数据加密后,以下数据在保存到 etcd 之前将被加密:

本指南将帮助你了解为什么要对敏感数据启用数据加密,以及如何启用数据加密来加强安全性。

启用数据加密

默认情况下,APISIX 启用了数据加密,并带有两个默认密钥:

apisix/cli/config.lua
apisix ={
...,
data_encryption = {
enable_encrypt_fields = true,
keyring = { "qeddd145sfvddff3", "edd1c9f0985e76a2" }
},
...
}

要查看数据加密的效果,请创建一个消费者 JohnDoe

curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"username": "JohnDoe"
}'

JohnDoe 配置 key-auth 凭证:

curl "http://127.0.0.1:9180/apisix/admin/consumers/JohnDoe/credentials" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "cred-john-key-auth",
"plugins": {
"key-auth": {
"key": "john-key"
}
}
}'

在此配置中,用户密钥是不应以明文存储的敏感信息。

创建消费者时你应该会看到一个响应,显示加密的密钥:

{
"key": "/apisix/consumers/JohnDoe/credentials/cred-john-key-auth",
"value": {
"create_time": 1726300662,
"update_time": 1726300662,
"plugins": {
"key-auth": {
"key": "a/TGSySA4i1LGn4ZXlYuew=="
}
},
"id": "cred-john-key-auth"
}
}

为了进一步验证密钥已加密,你还可以检查保存到 etcd 的项目:

etcdctl get /apisix/consumers/JohnDoe/credentials/cred-john-key-auth

你应该看到密钥已加密:

{
"update_time":1726300662,
"create_time":1726300662,
"plugins":{
"key-auth":{
"key":"a/TGSySA4i1LGn4ZXlYuew=="
}
},
"id": "cred-john-key-auth"
}

同样,APISIX 也会在将 TLS 证书私钥保存到 etcd 之前对其进行加密。要验证,你可以按照 配置客户端和 APISIX 之间的 HTTPS 中的步骤操作,并观察 server_key 是否已加密。

验证解密

要验证消费者 key-auth 密钥将被解密并按预期用于身份认证,请创建一个启用了 key-auth 的路由:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "auth-route",
"uri": "/get",
"plugins": {
"key-auth": {},
},
"upstream" : {
"nodes": {
"httpbin.org":1
}
}
}'

使用消费者凭证向路由发送请求:

curl -i "http://127.0.0.1:9080/get" -H 'apikey: john-key'

你应该收到 HTTP/1.1 200 OK 响应,验证密钥已成功解密并用于身份认证。

更新密钥环

可以使用正确的密钥环将加密数据还原为明文。因此,强烈建议你在生产环境中使用自定义密钥环。

密钥应为长度为 16 的十六进制字符串,以配合底层密码 AES-128-CBC。要更新密钥环,你可以按如下方式添加新密钥:

config.yaml
apisix:
data_encryption:
enable_encrypt_fields: true
keyring:
- aa2b3c4d1e6f7g8h
- xiy8z7a2b522dke1
- qeddd145sfvddff3
- edd1c9f0985e76a2

❶ 为 敏感插件字段 启用加密。

❷ 添加第一个和第二个新密钥。

❸ 添加第一个和第二个旧密钥。

警告

如果你的 APISIX 已经在运行并且有数据被加密,请不要删除旧密钥。如上所示,将新密钥添加到数组顶部,以便可以正确解密加密数据。直接删除旧密钥可能会导致加密数据不可逆。

如果没有数据被加密,你可以直接使用自定义密钥配置该部分。

如果你的 APISIX 已经在运行,重新加载 APISIX 以使配置更改生效。

禁用数据加密

要禁用数据加密,只需将 enable_encrypt_fields 更新为 false

config.yaml
apisix:
data_encryption:
enable_encrypt_fields: false

如果你的 APISIX 已经在运行,重新加载 APISIX 以使配置更改生效。

现在,如果你再次使用 key-auth 配置消费者凭证:

curl "http://127.0.0.1:9180/apisix/admin/consumers/JohnDoe/credentials" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "cred-john-key-auth",
"plugins": {
"key-auth": {
"key": "john-key"
}
}
}'

你应该看到密钥以明文保存的响应:

{
"key": "/apisix/consumers/JohnDoe/credentials/cred-john-key-auth",
"value": {
"create_time": 1726300662,
"update_time": 1726300668,
"plugins": {
"key-auth": {
"key": "john-key"
}
},
"id": "cred-john-key-auth"
}
}

了解插件加密字段

加密插件字段定义于每个插件图案的encrypt_fields属性中. 田径可以指: 顶级田径或筑巢田径. 例如:

apisix/plugins/basic-auth.lua
local consumer_schema = {
type = "object",
title = "work with consumer object",
properties = {
username = { type = "string" },
password = { type = "string" },
},
# highlight-next-line
encrypt_fields = {"password"},
required = {"username", "password"},
}

一旦定义,启用数据加密时这些字段将被加密。

对于筑巢场,使用点分隔路径,如session.secretredis.passwordauth_config.private_key

下表总结了所有插件的加密插件字段:

** 胶片**** 字段**
authz-casdoorclient_secret
authz-keycloakclient_secret
azure-functionsauthorization.apikeymaster_apikey
basic-authpassword
cas-authcookie.secret
clickhouse-loggerpassword
dingtalk-authapp_secret,secret,secret_fallbacks
elasticsearch-loggerauth.password
feishu-authapp_secret,secret,secret_fallbacks
rocketmq-loggersecret_key
sls-loggeraccess_key_secret
error-log-loggerclickhouse.passwordkafka.brokers.sasl_config.password
google-cloud-loggingauth_config.private_key
csrfkey
hmac-authsecret_key
http-loggerauth_header
jwt-authsecret
kafka-loggerbrokers.sasl_config.password
key-authkey
lagotoken
logglycustomer_token
openwhiskservice_token
openfunctionauthorization.service_token
tencent-cloud-clssecret_key
openid-connectclient_secretclient_rsa_private_keysession.secretsession.redis.passwordsession.redis.password
kafka-proxysasl.password
jwe-decryptkeysecret
ai-aliyun-content-moderationaccess_key_secret
ai-aws-content-moderationcomprehend.secret_access_key
ai-proxyauth.header,auth.query,auth.gcp.service_account_json,auth.aws.secret_access_key,auth.aws.session_token
ai-proxy-multiinstances.auth.header,instances.auth.query,instances.auth.gcp.service_account_json,instances.auth.aws.secret_access_key,instances.auth.aws.session_token
ai-ragembeddings_provider.azure_openai.api_keyvector_search_provider.azure_ai_search.api_key
aws-lambdaauthorization.apikey,authorization.iam.accesskey,authorization.iam.secretkey
saml-authsp_private_key,secret,secret_fallbacks
splunk-hec-loggingendpoint.token