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]