This is an automated email from the ASF dual-hosted git repository.
nic-6443 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git
The following commit(s) were added to refs/heads/master by this push:
new e7d9abf53 feat: encrypt redis_password and sentinel_password in
limit-count/limit-req/limit-conn (#13624)
e7d9abf53 is described below
commit e7d9abf5385f19ac2f50ffac1044b1eef5be9144
Author: Nic <[email protected]>
AuthorDate: Mon Jun 29 17:25:06 2026 +0800
feat: encrypt redis_password and sentinel_password in
limit-count/limit-req/limit-conn (#13624)
---
apisix/plugins/limit-conn.lua | 3 +-
apisix/plugins/limit-count/init.lua | 3 +-
apisix/plugins/limit-req.lua | 3 +-
docs/en/latest/plugins/limit-conn.md | 2 +
docs/en/latest/plugins/limit-count.md | 2 +
docs/en/latest/plugins/limit-req.md | 2 +
docs/zh/latest/plugins/limit-conn.md | 2 +
docs/zh/latest/plugins/limit-count.md | 2 +
docs/zh/latest/plugins/limit-req.md | 2 +
t/node/data_encrypt.t | 170 ++++++++++++++++++++++++++++++++++
10 files changed, 188 insertions(+), 3 deletions(-)
diff --git a/apisix/plugins/limit-conn.lua b/apisix/plugins/limit-conn.lua
index 7b79ac20a..9c760d548 100644
--- a/apisix/plugins/limit-conn.lua
+++ b/apisix/plugins/limit-conn.lua
@@ -103,7 +103,8 @@ local schema = {
},
},
["then"] = redis_schema.limit_conn_redis_cluster_schema,
- }
+ },
+ encrypt_fields = {"redis_password"},
}
local _M = {
diff --git a/apisix/plugins/limit-count/init.lua
b/apisix/plugins/limit-count/init.lua
index 838bf27fd..2cdfdac85 100644
--- a/apisix/plugins/limit-count/init.lua
+++ b/apisix/plugins/limit-count/init.lua
@@ -220,7 +220,8 @@ local schema = {
},
["then"] = policy_to_additional_properties["redis-sentinel"],
}
- }
+ },
+ encrypt_fields = {"redis_password", "sentinel_password"},
}
local schema_copy = core.table.deepcopy(schema)
diff --git a/apisix/plugins/limit-req.lua b/apisix/plugins/limit-req.lua
index dd3c1dcf8..6963d3deb 100644
--- a/apisix/plugins/limit-req.lua
+++ b/apisix/plugins/limit-req.lua
@@ -83,7 +83,8 @@ local schema = {
},
},
["then"] = policy_to_additional_properties["redis-cluster"],
- }
+ },
+ encrypt_fields = {"redis_password"},
}
diff --git a/docs/en/latest/plugins/limit-conn.md
b/docs/en/latest/plugins/limit-conn.md
index 05b3b1b4d..a92ecf2db 100644
--- a/docs/en/latest/plugins/limit-conn.md
+++ b/docs/en/latest/plugins/limit-conn.md
@@ -71,6 +71,8 @@ The `limit-conn` Plugin limits the rate of requests by the
number of concurrent
| rules.burst | integer or string | True | | >= 0 or
[lua-resty-expr](https://github.com/api7/lua-resty-expr) | The number of
excessive concurrent requests allowed to be delayed. Requests exceeding `conn +
burst` will be rejected immediately. This parameter also supports the string
data type and allows the use of built-in variables prefixed with a dollar sign
(`$`). |
| rules.key | string | True | | | The key to count requests by. If the
configured key does not exist, the rule will not be executed. The `key` is
interpreted as a combination of variables. All variables should be prefixed by
dollar signs (`$`). |
+NOTE: `encrypt_fields = {"redis_password"}` is also defined in the schema,
which means that the field will be stored encrypted in etcd. See [encrypted
storage fields](../plugin-develop.md#encrypted-storage-fields).
+
## Examples
The examples below demonstrate how you can configure `limit-conn` in different
scenarios.
diff --git a/docs/en/latest/plugins/limit-count.md
b/docs/en/latest/plugins/limit-count.md
index f00672cfe..38f1d4f59 100644
--- a/docs/en/latest/plugins/limit-count.md
+++ b/docs/en/latest/plugins/limit-count.md
@@ -86,6 +86,8 @@ You may see the following rate limiting headers in the
response:
| sentinel_username | string | False
| | | The username for
Redis Sentinel if Sentinel ACL is enabled. |
| sentinel_password | string | False
| | | The password for
Redis Sentinel if Sentinel ACL is enabled. |
+NOTE: `encrypt_fields = {"redis_password", "sentinel_password"}` is also
defined in the schema, which means that the fields will be stored encrypted in
etcd. See [encrypted storage
fields](../plugin-develop.md#encrypted-storage-fields).
+
## Examples
The examples below demonstrate how you can configure `limit-count` in
different scenarios.
diff --git a/docs/en/latest/plugins/limit-req.md
b/docs/en/latest/plugins/limit-req.md
index 44dc822ac..59c65d8e5 100644
--- a/docs/en/latest/plugins/limit-req.md
+++ b/docs/en/latest/plugins/limit-req.md
@@ -73,6 +73,8 @@ The `limit-req` Plugin supports two modes of rate limiting:
| redis_cluster_ssl | boolean | False | false | | If true, use SSL to connect
to Redis cluster when `policy` is `redis-cluster`. |
| redis_cluster_ssl_verify | boolean | False | false | | If true, verify the
server SSL certificate when `policy` is `redis-cluster`. |
+NOTE: `encrypt_fields = {"redis_password"}` is also defined in the schema,
which means that the field will be stored encrypted in etcd. See [encrypted
storage fields](../plugin-develop.md#encrypted-storage-fields).
+
## Examples
The examples below demonstrate how you can configure `limit-req` in different
scenarios.
diff --git a/docs/zh/latest/plugins/limit-conn.md
b/docs/zh/latest/plugins/limit-conn.md
index 02a9251ba..85d75a6f1 100644
--- a/docs/zh/latest/plugins/limit-conn.md
+++ b/docs/zh/latest/plugins/limit-conn.md
@@ -71,6 +71,8 @@ import TabItem from '@theme/TabItem';
| rules.burst | integer 或 string | 是 | | >= 0 或
[lua-resty-expr](https://github.com/api7/lua-resty-expr) | 允许延迟的过多并发请求数。超过
`conn + burst` 的请求将被立即拒绝。该参数也支持 string 数据类型,并允许使用以美元符号(`$`)为前缀的内置变量。|
| rules.key | string | 是 | | | 用于计数请求的键。如果配置的键不存在,则不会执行该规则。`key`
被解释为变量的组合。所有变量都应以美元符号(`$`)为前缀。|
+注意:schema 中还定义了 `encrypt_fields = {"redis_password"}`,这意味着该字段将会被加密存储在 etcd
中。具体参考[加密存储字段](../plugin-develop.md#加密存储字段)。
+
## 示例
以下示例演示了如何在不同场景中配置 `limit-conn`。
diff --git a/docs/zh/latest/plugins/limit-count.md
b/docs/zh/latest/plugins/limit-count.md
index 25320c179..c02a09961 100644
--- a/docs/zh/latest/plugins/limit-count.md
+++ b/docs/zh/latest/plugins/limit-count.md
@@ -87,6 +87,8 @@ import TabItem from '@theme/TabItem';
| sentinel_username | string | 否 | | | 如果启用了 Sentinel ACL,则为 Sentinel 用户名。 |
| sentinel_password | string | 否 | | | 如果启用了 Sentinel ACL,则为 Sentinel 密码。 |
+注意:schema 中还定义了 `encrypt_fields = {"redis_password",
"sentinel_password"}`,这意味着这些字段将会被加密存储在 etcd
中。具体参考[加密存储字段](../plugin-develop.md#加密存储字段)。
+
## 示例
下面的示例演示了如何在不同情况下配置 `limit-count` 。
diff --git a/docs/zh/latest/plugins/limit-req.md
b/docs/zh/latest/plugins/limit-req.md
index ff88087b1..91d92b8f6 100644
--- a/docs/zh/latest/plugins/limit-req.md
+++ b/docs/zh/latest/plugins/limit-req.md
@@ -73,6 +73,8 @@ import TabItem from '@theme/TabItem';
| redis_cluster_ssl | boolean | 否 | false | | 如果为 `true`,当 `policy` 为
`redis-cluster` 时,使用 SSL 连接 Redis 集群。|
| redis_cluster_ssl_verify | boolean | 否 | false | | 如果为 `true`,当 `policy` 为
`redis-cluster` 时,验证服务器 SSL 证书。|
+注意:schema 中还定义了 `encrypt_fields = {"redis_password"}`,这意味着该字段将会被加密存储在 etcd
中。具体参考[加密存储字段](../plugin-develop.md#加密存储字段)。
+
## 示例
以下示例演示了如何在不同场景中配置 `limit-req`。
diff --git a/t/node/data_encrypt.t b/t/node/data_encrypt.t
index fceee1d56..c9b9e6d00 100644
--- a/t/node/data_encrypt.t
+++ b/t/node/data_encrypt.t
@@ -573,3 +573,173 @@ apisix:
}
--- response_body
["bar","test"]
+
+
+
+=== TEST 14: limit-count redis_password is encrypted in etcd
+--- yaml_config
+apisix:
+ data_encryption:
+ enable_encrypt_fields: true
+ keyring:
+ - edd1c9f0985e76a2
+--- config
+ location /t {
+ content_by_lua_block {
+ local json = require("toolkit.json")
+ local t = require("lib.test_admin").test
+ local code, body = t('/apisix/admin/routes/1',
+ ngx.HTTP_PUT,
+ [[{
+ "plugins": {
+ "limit-count": {
+ "count": 1,
+ "time_window": 60,
+ "policy": "redis",
+ "redis_host": "127.0.0.1",
+ "redis_password": "foobar"
+ }
+ },
+ "upstream": {
+ "nodes": {"127.0.0.1:1980": 1},
+ "type": "roundrobin"
+ },
+ "uri": "/hello"
+ }]]
+ )
+ if code >= 300 then
+ ngx.status = code
+ ngx.say(body)
+ return
+ end
+
+ ngx.sleep(0.1)
+
+ -- admin API returns the decrypted value
+ local code, message, res = t('/apisix/admin/routes/1',
ngx.HTTP_GET)
+ res = json.decode(res)
+ ngx.say(res.value.plugins["limit-count"].redis_password)
+
+ -- etcd stores the encrypted value
+ local etcd = require("apisix.core.etcd")
+ local res = assert(etcd.get('/routes/1'))
+ local stored =
res.body.node.value.plugins["limit-count"].redis_password
+ ngx.say(stored == "foobar" and "plaintext" or "encrypted")
+ }
+ }
+--- response_body
+foobar
+encrypted
+
+
+
+=== TEST 15: limit-req redis_password is encrypted in etcd
+--- yaml_config
+apisix:
+ data_encryption:
+ enable_encrypt_fields: true
+ keyring:
+ - edd1c9f0985e76a2
+--- config
+ location /t {
+ content_by_lua_block {
+ local json = require("toolkit.json")
+ local t = require("lib.test_admin").test
+ local code, body = t('/apisix/admin/routes/1',
+ ngx.HTTP_PUT,
+ [[{
+ "plugins": {
+ "limit-req": {
+ "rate": 1,
+ "burst": 0,
+ "key": "remote_addr",
+ "policy": "redis",
+ "redis_host": "127.0.0.1",
+ "redis_password": "foobar"
+ }
+ },
+ "upstream": {
+ "nodes": {"127.0.0.1:1980": 1},
+ "type": "roundrobin"
+ },
+ "uri": "/hello"
+ }]]
+ )
+ if code >= 300 then
+ ngx.status = code
+ ngx.say(body)
+ return
+ end
+
+ ngx.sleep(0.1)
+
+ local code, message, res = t('/apisix/admin/routes/1',
ngx.HTTP_GET)
+ res = json.decode(res)
+ ngx.say(res.value.plugins["limit-req"].redis_password)
+
+ local etcd = require("apisix.core.etcd")
+ local res = assert(etcd.get('/routes/1'))
+ local stored =
res.body.node.value.plugins["limit-req"].redis_password
+ ngx.say(stored == "foobar" and "plaintext" or "encrypted")
+ }
+ }
+--- response_body
+foobar
+encrypted
+
+
+
+=== TEST 16: limit-conn redis_password is encrypted in etcd
+--- yaml_config
+apisix:
+ data_encryption:
+ enable_encrypt_fields: true
+ keyring:
+ - edd1c9f0985e76a2
+--- config
+ location /t {
+ content_by_lua_block {
+ local json = require("toolkit.json")
+ local t = require("lib.test_admin").test
+ local code, body = t('/apisix/admin/routes/1',
+ ngx.HTTP_PUT,
+ [[{
+ "plugins": {
+ "limit-conn": {
+ "conn": 1,
+ "burst": 0,
+ "default_conn_delay": 0.1,
+ "key": "remote_addr",
+ "policy": "redis",
+ "redis_host": "127.0.0.1",
+ "redis_password": "foobar"
+ }
+ },
+ "upstream": {
+ "nodes": {"127.0.0.1:1980": 1},
+ "type": "roundrobin"
+ },
+ "uri": "/hello"
+ }]]
+ )
+ if code >= 300 then
+ ngx.status = code
+ ngx.say(body)
+ return
+ end
+
+ ngx.sleep(0.1)
+
+ local code, message, res = t('/apisix/admin/routes/1',
ngx.HTTP_GET)
+ res = json.decode(res)
+ ngx.say(res.value.plugins["limit-conn"].redis_password)
+
+ local etcd = require("apisix.core.etcd")
+ local res = assert(etcd.get('/routes/1'))
+ local stored =
res.body.node.value.plugins["limit-conn"].redis_password
+ ngx.say(stored == "foobar" and "plaintext" or "encrypted")
+ }
+ }
+--- response_body
+foobar
+encrypted