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

Reply via email to