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 59ab7ef8bf fix(admin): encrypt the inline upstream client key of a 
stream route (#13833)
59ab7ef8bf is described below

commit 59ab7ef8bfebc3ccb2a2acd97874498724a563c8
Author: Nic <[email protected]>
AuthorDate: Tue Aug 18 11:44:44 2026 +0800

    fix(admin): encrypt the inline upstream client key of a stream route 
(#13833)
---
 apisix/admin/stream_routes.lua |  7 ++++++
 t/admin/stream-routes.t        | 50 ++++++++++++++++++++++++++++++++++++++++++
 t/stream-node/upstream-mtls.t  | 47 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 104 insertions(+)

diff --git a/apisix/admin/stream_routes.lua b/apisix/admin/stream_routes.lua
index d4a79ac889..9bd94906b2 100644
--- a/apisix/admin/stream_routes.lua
+++ b/apisix/admin/stream_routes.lua
@@ -16,6 +16,7 @@
 --
 local core = require("apisix.core")
 local resource = require("apisix.admin.resource")
+local apisix_upstream = require("apisix.upstream")
 local stream_route_checker = 
require("apisix.stream.router.ip_port").stream_route_checker
 local tostring = tostring
 local ipairs = ipairs
@@ -151,12 +152,18 @@ local function delete_checker(id)
 end
 
 
+local function encrypt_conf(id, conf)
+    apisix_upstream.encrypt_conf(conf.upstream)
+end
+
+
 return resource.new({
     name = "stream_routes",
     kind = "stream route",
     schema = core.schema.stream_route,
     checker = check_conf,
     delete_checker = delete_checker,
+    encrypt_conf = encrypt_conf,
     unsupported_methods = { "patch" },
     list_filter_fields = {
         service_id = true,
diff --git a/t/admin/stream-routes.t b/t/admin/stream-routes.t
index 7ce694ccd3..8efc3da31a 100644
--- a/t/admin/stream-routes.t
+++ b/t/admin/stream-routes.t
@@ -654,3 +654,53 @@ passed
 GET /t
 --- response_body
 passed
+
+
+
+=== TEST 18: an inline upstream client key is encrypted at rest
+--- config
+    location /t {
+        content_by_lua_block {
+            local core = require("apisix.core")
+            local etcd = require("apisix.core.etcd")
+            local t = require("lib.test_admin")
+
+            local ssl_cert = t.read_file("t/certs/apisix.crt")
+            local ssl_key = t.read_file("t/certs/apisix.key")
+            local code, body = t.test('/apisix/admin/stream_routes/enc',
+                ngx.HTTP_PUT,
+                core.json.encode({
+                    remote_addr = "127.0.0.1",
+                    upstream = {
+                        nodes = { ["127.0.0.1:8080"] = 1 },
+                        type = "roundrobin",
+                        scheme = "tls",
+                        tls = {
+                            client_cert = ssl_cert,
+                            client_key = ssl_key,
+                        },
+                    },
+                })
+            )
+            if code >= 300 then
+                ngx.status = code
+                ngx.say(body)
+                return
+            end
+
+            local res = assert(etcd.get('/stream_routes/enc'))
+            local stored = res.body.node.value.upstream.tls.client_key
+            assert(not core.string.find(stored, "PRIVATE KEY"),
+                   "the client key must be encrypted at rest")
+
+            code, body = t.test('/apisix/admin/stream_routes/enc', 
ngx.HTTP_GET)
+            assert(code == 200, "the admin API must return the stream route")
+            assert(not core.string.find(body, "PRIVATE KEY"),
+                   "the admin API must not return the plaintext client key")
+            ngx.say("encrypted")
+        }
+    }
+--- request
+GET /t
+--- response_body
+encrypted
diff --git a/t/stream-node/upstream-mtls.t b/t/stream-node/upstream-mtls.t
index fd4c753f84..186ea86f7a 100644
--- a/t/stream-node/upstream-mtls.t
+++ b/t/stream-node/upstream-mtls.t
@@ -218,3 +218,50 @@ mmm
 hello mtls upstream
 --- no_error_log
 [error]
+
+
+
+=== TEST 7: set stream_route with an inline upstream carrying the client cert
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin")
+            local json = require("toolkit.json")
+            local ssl_cert = t.read_file("t/certs/mtls_client.crt")
+            local ssl_key = t.read_file("t/certs/mtls_client.key")
+
+            local code, body = t.test('/apisix/admin/stream_routes/1',
+                ngx.HTTP_PUT,
+                json.encode({
+                    remote_addr = "127.0.0.1",
+                    upstream = {
+                        scheme = "tls",
+                        type = "roundrobin",
+                        nodes = { ["127.0.0.1:8765"] = 1 },
+                        tls = {
+                            client_cert = ssl_cert,
+                            client_key = ssl_key,
+                        },
+                    },
+                })
+            )
+            if code >= 300 then
+                ngx.status = code
+            end
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+
+
+
+=== TEST 8: hit route, the encrypted inline client key still completes the 
handshake
+--- stream_request
+mmm
+--- stream_response
+hello mtls upstream
+--- no_error_log
+[error]

Reply via email to