跳到主要内容

使用 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",
"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

你应该看到密钥已加密:

{
"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:
// Annotate 1
enable_encrypt_fields: true
keyring:
// Annotate 2
- aa2b3c4d1e6f7g9h
- xiy8z7a2b522dke
// Annotate 3
- 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",
"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"},
}

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

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

插件字段
authz-casdoorclient_secret
authz-keycloakclient_secret
basic-authpassword
clickhouse-loggerpassword
elasticsearch-loggerauth.password
rocketmq-loggersecret_key
sls-loggeraccess_key_secret
error-log-loggerclickhouse.password
google-cloud-loggingauth_config.private_key
csrfkey
hmac-authsecret_key
jwt-authsecret, private_key
key-authkey
openwhiskservice_token
tencent-cloud-clssecret_key
openid-connectclient_secret, client_rsa_private_key
kafka-proxysasl.password
jwt-decryptkey, secret