This is an automated email from the ASF dual-hosted git repository.

shreemaanabhishek 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 16b9d7e5b feat(standalone): reject configurations when configured with 
unknown plugin (#13046)
16b9d7e5b is described below

commit 16b9d7e5b611a729c6eb99d3fbca6c8bce71f494
Author: Shreemaan Abhishek <[email protected]>
AuthorDate: Mon Mar 2 17:10:34 2026 +0545

    feat(standalone): reject configurations when configured with unknown plugin 
(#13046)
---
 apisix/plugin.lua                      |   9 +-
 t/admin/standalone-plugin-validation.t | 256 +++++++++++++++++++++++++++++++++
 t/config-center-yaml/plugin.t          |  10 +-
 t/config-center-yaml/route.t           |   5 +-
 t/config-center-yaml/stream-route.t    |   4 +-
 5 files changed, 274 insertions(+), 10 deletions(-)

diff --git a/apisix/plugin.lua b/apisix/plugin.lua
index ab45b22f6..6e80877b9 100644
--- a/apisix/plugin.lua
+++ b/apisix/plugin.lua
@@ -1130,7 +1130,8 @@ _M.stream_check_schema = stream_check_schema
 
 function _M.plugin_checker(item, schema_type)
     if item.plugins then
-        local ok, err = check_schema(item.plugins, schema_type, true)
+        local skip_disabled_plugins = not (core.config.type == "yaml" or 
core.config.type == "json")
+        local ok, err = check_schema(item.plugins, schema_type, 
skip_disabled_plugins)
 
         if ok and enable_gde() then
             -- decrypt conf
@@ -1147,7 +1148,11 @@ end
 
 function _M.stream_plugin_checker(item, in_cp)
     if item.plugins then
-        return stream_check_schema(item.plugins, nil, not in_cp)
+        local skip_disabled_plugins = not in_cp
+        if core.config.type == "yaml" or core.config.type == "json" then
+            skip_disabled_plugins = false
+        end
+        return stream_check_schema(item.plugins, nil, skip_disabled_plugins)
     end
 
     return true
diff --git a/t/admin/standalone-plugin-validation.t 
b/t/admin/standalone-plugin-validation.t
new file mode 100644
index 000000000..187c1b2fb
--- /dev/null
+++ b/t/admin/standalone-plugin-validation.t
@@ -0,0 +1,256 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+use t::APISIX 'no_plan';
+
+repeat_each(1);
+no_long_string();
+no_root_location();
+
+add_block_preprocessor(sub {
+    my ($block) = @_;
+
+    if (!defined $block->yaml_config) {
+        $block->set_value("yaml_config", <<'_EOC_');
+apisix:
+    admin_key:
+        - name: admin
+          key: edd1c9f034335f136f87ad84b625c8f1
+          role: admin
+deployment:
+    role: data_plane
+    role_data_plane:
+        config_provider: yaml
+_EOC_
+    }
+
+    $block->set_value("stream_enable", 1);
+});
+
+run_tests();
+
+__DATA__
+
+=== TEST 1: missing plugin on route blocks route matching
+--- extra_yaml_config
+plugins:
+  - redirect
+--- apisix_yaml
+routes:
+  - id: 1
+    uri: /hello
+    plugins:
+      openid-connect:
+        client_id: x
+        client_secret: x
+        discovery: x
+        scope: openid email
+        bearer_only: false
+        realm: x
+    upstream:
+      type: roundrobin
+      nodes:
+        "127.0.0.1:1980": 1
+#END
+--- request
+GET /hello
+--- error_code: 404
+--- error_log
+unknown plugin [openid-connect]
+
+
+
+=== TEST 2: missing plugin on stream route blocks stream matching
+--- extra_yaml_config
+stream_plugins:
+  - ip-restriction
+--- apisix_yaml
+stream_routes:
+  - id: 1
+    server_port: 1985
+    plugins:
+      syslog:
+        host: 127.0.0.1
+        port: 514
+    upstream:
+      type: roundrobin
+      nodes:
+        "127.0.0.1:1995": 1
+#END
+--- config
+location /stream_request {
+    content_by_lua_block {
+        ngx.sleep(1)  -- wait for the stream route to take effect
+
+        local tcp_request = function(host, port)
+            local sock, err = ngx.socket.tcp()
+            assert(sock, err)
+
+            local ok, err = sock:connect(host, port)
+            if not ok then
+                ngx.say("connect to stream server error: ", err)
+                return
+            end
+            local bytes, err = sock:send("mmm")
+            if not bytes then
+                ngx.say("send stream request error: ", err)
+                return
+            end
+
+            local data, err = sock:receive("*a")
+            if not data then
+                sock:close()
+                ngx.say("receive stream response error: ", err)
+                return
+            end
+            sock:close()
+            ngx.print(data)
+        end
+
+        tcp_request("127.0.0.1", 1985)
+    }
+}
+--- request
+GET /stream_request
+--- response_body
+receive stream response error: connection reset by peer
+--- error_log
+unknown plugin [syslog]
+
+
+
+=== TEST 3: missing plugin on route blocks route matching (json)
+--- yaml_config
+apisix:
+    admin_key:
+        - name: admin
+          key: edd1c9f034335f136f87ad84b625c8f1
+          role: admin
+deployment:
+    role: data_plane
+    role_data_plane:
+        config_provider: json
+--- extra_yaml_config
+plugins:
+  - redirect
+--- apisix_json
+{
+  "routes": [
+    {
+      "id": "1",
+      "uri": "/hello",
+      "plugins": {
+        "openid-connect": {
+          "client_id": "x",
+          "client_secret": "x",
+          "discovery": "x",
+          "scope": "openid email",
+          "bearer_only": false,
+          "realm": "x"
+        }
+      },
+      "upstream": {
+        "type": "roundrobin",
+        "nodes": {
+          "127.0.0.1:1980": 1
+        }
+      }
+    }
+  ]
+}
+--- request
+GET /hello
+--- error_code: 404
+--- error_log
+unknown plugin [openid-connect]
+
+
+
+=== TEST 4: missing plugin on stream route blocks stream matching (json)
+--- yaml_config
+apisix:
+    admin_key:
+        - name: admin
+          key: edd1c9f034335f136f87ad84b625c8f1
+          role: admin
+deployment:
+    role: data_plane
+    role_data_plane:
+        config_provider: json
+--- extra_yaml_config
+stream_plugins:
+  - ip-restriction
+--- apisix_json
+{
+  "stream_routes": [
+    {
+      "id": "1",
+      "server_port": 1985,
+      "plugins": {
+        "syslog": {
+          "host": "127.0.0.1",
+          "port": 514
+        }
+      },
+      "upstream": {
+        "type": "roundrobin",
+        "nodes": {
+          "127.0.0.1:1995": 1
+        }
+      }
+    }
+  ]
+}
+--- config
+location /stream_request {
+    content_by_lua_block {
+        ngx.sleep(1)  -- wait for the stream route to take effect
+
+        local tcp_request = function(host, port)
+            local sock, err = ngx.socket.tcp()
+            assert(sock, err)
+
+            local ok, err = sock:connect(host, port)
+            if not ok then
+                ngx.say("connect to stream server error: ", err)
+                return
+            end
+            local bytes, err = sock:send("mmm")
+            if not bytes then
+                ngx.say("send stream request error: ", err)
+                return
+            end
+
+            local data, err = sock:receive("*a")
+            if not data then
+                sock:close()
+                ngx.say("receive stream response error: ", err)
+                return
+            end
+            sock:close()
+            ngx.print(data)
+        end
+
+        tcp_request("127.0.0.1", 1985)
+    }
+}
+--- request
+GET /stream_request
+--- response_body
+receive stream response error: connection reset by peer
+--- error_log
+unknown plugin [syslog]
diff --git a/t/config-center-yaml/plugin.t b/t/config-center-yaml/plugin.t
index fd3c35734..405884028 100644
--- a/t/config-center-yaml/plugin.t
+++ b/t/config-center-yaml/plugin.t
@@ -158,6 +158,8 @@ plugins:
 --- request
 GET /apisix/prometheus/metrics
 --- error_code: 404
+--- error_log
+err:unknown plugin [ip-restriction]
 
 
 
@@ -226,7 +228,7 @@ stream_plugins:
 --- request
 GET /t
 --- response_body
-hello world
+{"error_msg":"404 Route Not Found"}
 --- error_log
 use config_provider: yaml
 load(): new plugins: {}
@@ -261,8 +263,6 @@ plugins:
 --- request
 GET /t
 --- response_body
-hello world
---- no_error_log
-[error]
+{"error_msg":"404 Route Not Found"}
 --- error_log
-skipping check schema for disabled or unknown plugin [ip-restriction]. Enable 
the plugin or modify configuration
+failed to check item data of [routes] err:unknown plugin [ip-restriction]
diff --git a/t/config-center-yaml/route.t b/t/config-center-yaml/route.t
index 2da1397da..725f7c827 100644
--- a/t/config-center-yaml/route.t
+++ b/t/config-center-yaml/route.t
@@ -138,8 +138,11 @@ routes:
 #END
 --- request
 GET /hello
+--- error_code: 404
 --- response_body
-hello world
+{"error_msg":"404 Route Not Found"}
+--- error_log
+failed to check item data of [routes] err:unknown plugin
 
 
 
diff --git a/t/config-center-yaml/stream-route.t 
b/t/config-center-yaml/stream-route.t
index 6792b1bb9..a84c5f4d8 100644
--- a/t/config-center-yaml/stream-route.t
+++ b/t/config-center-yaml/stream-route.t
@@ -99,8 +99,8 @@ stream_routes:
         "127.0.0.1:1995": 1
       type: roundrobin
 #END
---- stream_response
-hello world
+--- error_log
+err:unknown plugin [x-rewrite]
 
 
 

Reply via email to