From eaef37a0bf0e22b30199a5ada009c87866922e90 Mon Sep 17 00:00:00 2001 From: Yuansheng Date: Wed, 17 Jun 2020 21:39:51 +0800 Subject: [PATCH 01/11] feature: implemented plugin `uri-blocklist` . --- apisix/plugins/uri-blocklist.lua | 84 ++++++++++++++ conf/config.yaml | 1 + t/plugin/uri-blocklist.t | 191 +++++++++++++++++++++++++++++++ 3 files changed, 276 insertions(+) create mode 100644 apisix/plugins/uri-blocklist.lua create mode 100644 t/plugin/uri-blocklist.t diff --git a/apisix/plugins/uri-blocklist.lua b/apisix/plugins/uri-blocklist.lua new file mode 100644 index 000000000000..799efed9fd41 --- /dev/null +++ b/apisix/plugins/uri-blocklist.lua @@ -0,0 +1,84 @@ +-- +-- 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. +-- +local core = require("apisix.core") +local re_compile = require("resty.core.regex").re_match_compile +local re_find = ngx.re.find + +local schema = { + type = "object", + properties = { + filter_rules = { + type = "array", + items = { + type = "string", + minLength = 1, + maxLength = 4096, + }, + uniqueItems = true + }, + rejected_code = { + type = "integer", + minimum = 200, + default = 403 + }, + }, + required = {"filter_rules"}, +} + + +local plugin_name = "uri-blocklist" + +local _M = { + version = 0.1, + priority = 0, -- TODO: add a type field, may be a good idea + name = plugin_name, + schema = schema, +} + + +function _M.check_schema(conf) + local ok, err = core.schema.check(schema, conf) + if not ok then + return false, err + end + + local filter_rules = {} + for i, re_rule in ipairs(conf.filter_rules) do + local ok, err = re_compile(re_rule, "j") + -- core.log.warn("ok: ", tostring(ok), " err: ", tostring(err), " re_rule: ", re_rule) + if not ok then + return false, err + end + filter_rules[i] = re_rule + end + + conf.filter_rules_concat = core.table.concat(filter_rules, "|") + core.log.info("concat filter_rules: ", conf.filter_rules_concat) + return true +end + + +function _M.rewrite(conf, ctx) + core.log.info("uri: ", ctx.var.request_uri) + local from = re_find(ctx.var.request_uri, conf.filter_rules_concat, "jo") + if from then + core.response.exit(conf.rejected_code) + end +end + + +return _M diff --git a/conf/config.yaml b/conf/config.yaml index d640ef79521f..66b451ac3f3a 100644 --- a/conf/config.yaml +++ b/conf/config.yaml @@ -168,6 +168,7 @@ plugins: # plugin list - skywalking - echo - authz-keycloak + - uri-blocklist stream_plugins: - mqtt-proxy diff --git a/t/plugin/uri-blocklist.t b/t/plugin/uri-blocklist.t new file mode 100644 index 000000000000..6f59027cab36 --- /dev/null +++ b/t/plugin/uri-blocklist.t @@ -0,0 +1,191 @@ +# +# 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(2); +no_long_string(); +no_root_location(); +no_shuffle(); + +run_tests; + +__DATA__ + +=== TEST 1: invalid regular expression +--- config +location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "plugins": { + "uri-blocklist": { + "filter_rules": [".+("] + } + }, + "uri": "/hello" + }]]) + + if code >= 300 then + ngx.status = code + end + ngx.print(body) + } +} +--- request +GET /t +--- error_code: 400 +--- response_body +{"error_msg":"failed to check the configuration of plugin uri-blocklist err: pcre_compile() failed: missing ) in \".+(\""} +--- no_error_log +[error] + + + +=== TEST 2: multiple valid rules +--- config +location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "plugins": { + "uri-blocklist": { + "filter_rules": ["^a", "^b"] + } + }, + "uri": "/hello" + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } +} +--- request +GET /t +--- response_body +passed +--- no_error_log +[error] +--- error_log +concat filter_rules: ^a|^b, + + + +=== TEST 3: multiple rules(include one invalid rule) +--- config +location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "plugins": { + "uri-blocklist": { + "filter_rules": ["^a", "^b("] + } + }, + "uri": "/hello" + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.print(body) + } +} +--- request +GET /t +--- error_code: 400 +--- response_body +{"error_msg":"failed to check the configuration of plugin uri-blocklist err: pcre_compile() failed: missing ) in \"^b(\""} +--- no_error_log +[error] + + + +=== TEST 4: sanity +--- config +location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "plugins": { + "uri-blocklist": { + "filter_rules": ["aa"] + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/hello" + }]], + [[{ + "node": { + "value": { + "plugins": { + "uri-blocklist": { + "filter_rules": ["aa"] + } + } + } + } + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } +} +--- request +GET /t +--- response_body +passed +--- no_error_log +[error] +--- error_log +concat filter_rules: aa, + + + +=== TEST 5: hit blocklist +--- request +GET /hello?aa=1 +--- error_code: 403 +--- no_error_log +[error] + + + +=== TEST 6: miss blocklist +--- request +GET /hello?bb=2 +--- no_error_log +[error] From c2f4e552261787014dd2217573db46b58a3af81e Mon Sep 17 00:00:00 2001 From: Yuansheng Date: Wed, 17 Jun 2020 22:05:28 +0800 Subject: [PATCH 02/11] doc --- doc/plugins/uri-blocklist.md | 96 ++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 doc/plugins/uri-blocklist.md diff --git a/doc/plugins/uri-blocklist.md b/doc/plugins/uri-blocklist.md new file mode 100644 index 000000000000..dd093e7e10dc --- /dev/null +++ b/doc/plugins/uri-blocklist.md @@ -0,0 +1,96 @@ + + +[Chinese](uri-blocklist.md) + +# Summary + +- [**Name**](#name) +- [**Attributes**](#attributes) +- [**How To Enable**](#how-to-enable) +- [**Test Plugin**](#test-plugin) +- [**Disable Plugin**](#disable-plugin) + +## Name + +The plugin helps we intercept user requests, we only need to indicate the blocklist. + +## Attributes + +|Name |Requirement |Description| +|--------- |--------|-----------| +|filter_rules |required|Regular filter rule array. Each of these items is a regular rule. If the current request URI hits any one of them, set the response code to rejected_code to exit the current user request. Example: `["root.exe", "root.m+"]`.| +|rejected_code |optional|The HTTP status code returned when the request URI hit any of `filter_rule`, default `403`.| + +## How To Enable + +Here's an example, enable the `uri blocklist` plugin on the specified route: + +```shell +curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' +{ + "uri": "/*", + "plugins": { + "uri-blocklist": { + "filter_rules": ["root.exe", "root.m+"] + } + }, + "upstream": { + "type": "roundrobin", + "nodes": { + "127.0.0.1:1980": 1 + } + } +}' +``` + +## Test Plugin + +```shell +$ curl -i http://127.0.0.1:9080/root.exe?a=a +HTTP/1.1 403 Forbidden +Date: Wed, 17 Jun 2020 13:55:41 GMT +Content-Type: text/html; charset=utf-8 +Content-Length: 150 +Connection: keep-alive +Server: APISIX web server + +... ... +``` + +## Disable Plugin + +When you want to disable the `uri blocklist` plugin, it is very simple, + you can delete the corresponding json configuration in the plugin configuration, + no need to restart the service, it will take effect immediately: + +```shell +curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' +{ + "uri": "/*", + "upstream": { + "type": "roundrobin", + "nodes": { + "127.0.0.1:1980": 1 + } + } +}' +``` + +The `uri blocklist` plugin has been disabled now. It works for other plugins. From ac5e1fd2ee80bea307133fd6d49926df094340ee Mon Sep 17 00:00:00 2001 From: Yuansheng Date: Wed, 17 Jun 2020 22:06:45 +0800 Subject: [PATCH 03/11] change: code style. --- apisix/plugins/uri-blocklist.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/apisix/plugins/uri-blocklist.lua b/apisix/plugins/uri-blocklist.lua index 799efed9fd41..27a1dda7f5bc 100644 --- a/apisix/plugins/uri-blocklist.lua +++ b/apisix/plugins/uri-blocklist.lua @@ -17,6 +17,7 @@ local core = require("apisix.core") local re_compile = require("resty.core.regex").re_match_compile local re_find = ngx.re.find +local ipairs = ipairs local schema = { type = "object", From e80cccbe3623086475b6eb76c09174cf950230fc Mon Sep 17 00:00:00 2001 From: Yuansheng Date: Wed, 17 Jun 2020 22:11:31 +0800 Subject: [PATCH 04/11] test: small points. --- apisix/plugins/uri-blocklist.lua | 2 +- t/admin/plugins.t | 2 +- t/debug/debug-mode.t | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apisix/plugins/uri-blocklist.lua b/apisix/plugins/uri-blocklist.lua index 27a1dda7f5bc..985d6d90b27e 100644 --- a/apisix/plugins/uri-blocklist.lua +++ b/apisix/plugins/uri-blocklist.lua @@ -45,7 +45,7 @@ local plugin_name = "uri-blocklist" local _M = { version = 0.1, - priority = 0, -- TODO: add a type field, may be a good idea + priority = 2900, name = plugin_name, schema = schema, } diff --git a/t/admin/plugins.t b/t/admin/plugins.t index 1a5f06e8031d..3a803b4fe3f8 100644 --- a/t/admin/plugins.t +++ b/t/admin/plugins.t @@ -30,7 +30,7 @@ __DATA__ --- request GET /apisix/admin/plugins/list --- response_body_like eval -qr/\["limit-req","limit-count","limit-conn","key-auth","basic-auth","prometheus","node-status","jwt-auth","zipkin","ip-restriction","grpc-transcode","serverless-pre-function","serverless-post-function","openid-connect","proxy-rewrite","redirect","response-rewrite","fault-injection","udp-logger","wolf-rbac","proxy-cache","tcp-logger","proxy-mirror","kafka-logger","cors","consumer-restriction","syslog","batch-requests","http-logger","skywalking","echo","authz-keycloak"\]/ +qr/\["limit-req","limit-count","limit-conn","key-auth","basic-auth","prometheus","node-status","jwt-auth","zipkin","ip-restriction","grpc-transcode","serverless-pre-function","serverless-post-function","openid-connect","proxy-rewrite","redirect","response-rewrite","fault-injection","udp-logger","wolf-rbac","proxy-cache","tcp-logger","proxy-mirror","kafka-logger","cors","consumer-restriction","syslog","batch-requests","http-logger","skywalking","echo","authz-keycloak","uri-blocklist"\]/ --- no_error_log [error] diff --git a/t/debug/debug-mode.t b/t/debug/debug-mode.t index 2924cdc3e9a6..a41305269c72 100644 --- a/t/debug/debug-mode.t +++ b/t/debug/debug-mode.t @@ -60,6 +60,7 @@ loaded plugin and sort by priority: 10000 name: serverless-pre-function loaded plugin and sort by priority: 4010 name: batch-requests loaded plugin and sort by priority: 4000 name: cors loaded plugin and sort by priority: 3000 name: ip-restriction +loaded plugin and sort by priority: 2900 name: uri-blocklist loaded plugin and sort by priority: 2599 name: openid-connect loaded plugin and sort by priority: 2555 name: wolf-rbac loaded plugin and sort by priority: 2520 name: basic-auth From 8bab1cac9ab9559337f131201f667bf78d0a9ec2 Mon Sep 17 00:00:00 2001 From: Yuansheng Wang Date: Thu, 18 Jun 2020 09:36:35 +0800 Subject: [PATCH 05/11] change: name style. --- .../{uri-blocklist.lua => uri-blocker.lua} | 2 +- conf/config.yaml | 4 +- doc/README.md | 4 +- doc/README_CN.md | 68 +++++++++++++++++++ .../{uri-blocklist.md => uri-blocker.md} | 14 ++-- t/admin/plugins.t | 2 +- t/debug/debug-mode.t | 2 +- t/plugin/{uri-blocklist.t => uri-blocker.t} | 14 ++-- 8 files changed, 90 insertions(+), 20 deletions(-) rename apisix/plugins/{uri-blocklist.lua => uri-blocker.lua} (98%) create mode 100644 doc/README_CN.md rename doc/plugins/{uri-blocklist.md => uri-blocker.md} (80%) rename t/plugin/{uri-blocklist.t => uri-blocker.t} (92%) diff --git a/apisix/plugins/uri-blocklist.lua b/apisix/plugins/uri-blocker.lua similarity index 98% rename from apisix/plugins/uri-blocklist.lua rename to apisix/plugins/uri-blocker.lua index 985d6d90b27e..9a6bd2401003 100644 --- a/apisix/plugins/uri-blocklist.lua +++ b/apisix/plugins/uri-blocker.lua @@ -41,7 +41,7 @@ local schema = { } -local plugin_name = "uri-blocklist" +local plugin_name = "uri-blocker" local _M = { version = 0.1, diff --git a/conf/config.yaml b/conf/config.yaml index 66b451ac3f3a..cee95a601019 100644 --- a/conf/config.yaml +++ b/conf/config.yaml @@ -95,7 +95,7 @@ apisix: ssl_ciphers: "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA" key_encrypt_salt: "edd1c9f0985e76a2" # If not set, will save origin ssl key into etcd. # If set this, must be a string of length 16. And it will encrypt ssl key with AES-128-CBC - # !!! So do not change it after saving your ssl, it can't decrypt the ssl keys have be saved if you change !! + # !!! So do not change it after saving your ssl, it can't decrypt the ssl keys have be saved if you change !! # discovery: eureka # service discovery center nginx_config: # config for render the template to genarate nginx.conf error_log: "logs/error.log" @@ -168,7 +168,7 @@ plugins: # plugin list - skywalking - echo - authz-keycloak - - uri-blocklist + - uri-blocker stream_plugins: - mqtt-proxy diff --git a/doc/README.md b/doc/README.md index 042012d8a12a..3f9142adc04d 100644 --- a/doc/README.md +++ b/doc/README.md @@ -65,10 +65,12 @@ Plugins * [kafka-logger](plugins/kafka-logger.md): Log requests to External Kafka servers. * [cors](plugins/cors.md): Enable CORS(Cross-origin resource sharing) for your API. * [batch-requests](plugins/batch-requests.md): Allow you send mutiple http api via **http pipeline**. -* [authz-keycloak](plugins/authz-keycloak.md): Authorization with Keycloak Identity Server +* [authz-keycloak](plugins/authz-keycloak.md): Authorization with Keycloak Identity Server. +* [uri-blocker](plugins/uri-blocker.md): Block client request by URI. Deploy to the Cloud ======= + ### AWS The recommended approach is to deploy APISIX with [AWS CDK](https://aws.amazon.com/cdk/) on [AWS Fargate](https://aws.amazon.com/fargate/) which helps you decouple the APISIX layer and the upstream layer on top of a fully-managed and secure serverless container compute environment with autoscaling capabilities. diff --git a/doc/README_CN.md b/doc/README_CN.md new file mode 100644 index 000000000000..97b0880742a9 --- /dev/null +++ b/doc/README_CN.md @@ -0,0 +1,68 @@ + +[English](README.md) + +Reference document +================== + +* [APISIX 说明](../README_CN.md) +* [架构设计](architecture-design-cn.md) +* [压力测试](benchmark-cn.md) +* [如何构建 Apache APISIX](how-to-build-cn.md) +* [健康检查](health-check.md): 支持对上游节点的主动和被动健康检查,在负载均衡时自动过滤掉不健康的节点。 +* Router(路由) + * [radixtree](router-radixtree.md) +* [独立运行模型](stand-alone-cn.md): 支持从本地 yaml 格式的配置文件启动,更适合 Kubernetes(k8s) 体系。 +* [TCP/UDP 动态代理](stream-proxy-cn.md) +* [管理 API](admin-api-cn.md) +* [变更日志](../CHANGELOG_CN.md) +* [代码风格](../CODE_STYLE.md) +* [常见问答](../FAQ_CN.md) + +插件 +=== + +* [插件热加载](plugins-cn.md):无需重启服务,完成插件热加载或卸载。 +* [HTTPS](https-cn.md):根据 TLS 扩展字段 SNI(Server Name Indication) 动态加载证书。 +* [动态负载均衡](architecture-design-cn.md#upstream):跨多个上游服务的动态负载均衡,目前已支持 round-robin 和一致性哈希算法。 +* [key-auth](plugins/key-auth-cn.md):基于 Key Authentication 的用户认证。 +* [JWT-auth](plugins/jwt-auth-cn.md):基于 [JWT](https://jwt.io/) (JSON Web Tokens) Authentication 的用户认证。 +* [basic-auth](plugins/basic-auth-cn.md):基于 basic auth 的用户认证。 +* [wolf-rbac](plugins/wolf-rbac-cn.md) 基于 *RBAC* 的用户认证及授权。 +* [limit-count](plugins/limit-count-cn.md):基于“固定窗口”的限速实现。 +* [limit-req](plugins/limit-req-cn.md):基于漏桶原理的请求限速实现。 +* [limit-conn](plugins/limit-conn-cn.md):限制并发请求(或并发连接)。 +* [proxy-rewrite](plugins/proxy-rewrite-cn.md): 支持自定义修改 proxy 到上游的信息。 +* [prometheus](plugins/prometheus-cn.md):以 Prometheus 格式导出 APISIX 自身的状态信息,方便被外部 Prometheus 服务抓取。 +* [OpenTracing](plugins/zipkin-cn.md):支持 Zikpin 和 Apache SkyWalking。 +* [grpc-transcode](plugins/grpc-transcode-cn.md):REST <--> gRPC 转码。 +* [serverless](plugins/serverless-cn.md):允许在 APISIX 中的不同阶段动态运行 Lua 代码。 +* [ip-restriction](plugins/ip-restriction-cn.md): IP 黑白名单。 +* [openid-connect](plugins/oauth.md) +* [redirect](plugins/redirect-cn.md): URI 重定向。 +* [response-rewrite](plugins/response-rewrite-cn.md): 支持自定义修改返回内容的 `status code`、`body`、`headers`。 +* [fault-injection](plugins/fault-injection-cn.md):故障注入,可以返回指定的响应体、响应码和响应时间,从而提供了不同的失败场景下处理的能力,例如服务失败、服务过载、服务高延时等。 +* [proxy-cache](plugins/proxy-cache-cn.md):代理缓存插件提供缓存后端响应数据的能力。 +* [proxy-mirror](plugins/proxy-mirror-cn.md):代理镜像插件提供镜像客户端请求的能力。 +* [udp-logger](plugins/udp-logger.md): 将请求记录到UDP服务器。 +* [tcp-logger](plugins/tcp-logger.md): 将请求记录到TCP服务器。 +* [kafka-logger](plugins/kafka-logger-cn.md): 将请求记录到外部Kafka服务器。 +* [cors](plugins/cors-cn.md): 为你的API启用CORS。 +* [batch-requests](plugins/batch-requests-cn.md): 以 **http pipeline** 的方式在网关一次性发起多个 `http` 请求。 +* [uri-blocker](plugins/uri-blocker.md): 根据 URI 拦截用户请求。 diff --git a/doc/plugins/uri-blocklist.md b/doc/plugins/uri-blocker.md similarity index 80% rename from doc/plugins/uri-blocklist.md rename to doc/plugins/uri-blocker.md index dd093e7e10dc..35000c890c80 100644 --- a/doc/plugins/uri-blocklist.md +++ b/doc/plugins/uri-blocker.md @@ -17,7 +17,7 @@ # --> -[Chinese](uri-blocklist.md) +[Chinese](uri-blocker.md) # Summary @@ -29,25 +29,25 @@ ## Name -The plugin helps we intercept user requests, we only need to indicate the blocklist. +The plugin helps we intercept user requests, we only need to indicate the `block_rules`. ## Attributes |Name |Requirement |Description| |--------- |--------|-----------| -|filter_rules |required|Regular filter rule array. Each of these items is a regular rule. If the current request URI hits any one of them, set the response code to rejected_code to exit the current user request. Example: `["root.exe", "root.m+"]`.| +|block_rules |required|Regular filter rule array. Each of these items is a regular rule. If the current request URI hits any one of them, set the response code to rejected_code to exit the current user request. Example: `["root.exe", "root.m+"]`.| |rejected_code |optional|The HTTP status code returned when the request URI hit any of `filter_rule`, default `403`.| ## How To Enable -Here's an example, enable the `uri blocklist` plugin on the specified route: +Here's an example, enable the `uri blocker` plugin on the specified route: ```shell curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "uri": "/*", "plugins": { - "uri-blocklist": { + "uri-blocker": { "filter_rules": ["root.exe", "root.m+"] } }, @@ -76,7 +76,7 @@ Server: APISIX web server ## Disable Plugin -When you want to disable the `uri blocklist` plugin, it is very simple, +When you want to disable the `uri blocker` plugin, it is very simple, you can delete the corresponding json configuration in the plugin configuration, no need to restart the service, it will take effect immediately: @@ -93,4 +93,4 @@ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f13 }' ``` -The `uri blocklist` plugin has been disabled now. It works for other plugins. +The `uri blocker` plugin has been disabled now. It works for other plugins. diff --git a/t/admin/plugins.t b/t/admin/plugins.t index 3a803b4fe3f8..b134b97df731 100644 --- a/t/admin/plugins.t +++ b/t/admin/plugins.t @@ -30,7 +30,7 @@ __DATA__ --- request GET /apisix/admin/plugins/list --- response_body_like eval -qr/\["limit-req","limit-count","limit-conn","key-auth","basic-auth","prometheus","node-status","jwt-auth","zipkin","ip-restriction","grpc-transcode","serverless-pre-function","serverless-post-function","openid-connect","proxy-rewrite","redirect","response-rewrite","fault-injection","udp-logger","wolf-rbac","proxy-cache","tcp-logger","proxy-mirror","kafka-logger","cors","consumer-restriction","syslog","batch-requests","http-logger","skywalking","echo","authz-keycloak","uri-blocklist"\]/ +qr/\["limit-req","limit-count","limit-conn","key-auth","basic-auth","prometheus","node-status","jwt-auth","zipkin","ip-restriction","grpc-transcode","serverless-pre-function","serverless-post-function","openid-connect","proxy-rewrite","redirect","response-rewrite","fault-injection","udp-logger","wolf-rbac","proxy-cache","tcp-logger","proxy-mirror","kafka-logger","cors","consumer-restriction","syslog","batch-requests","http-logger","skywalking","echo","authz-keycloak","uri-blocker"\]/ --- no_error_log [error] diff --git a/t/debug/debug-mode.t b/t/debug/debug-mode.t index a41305269c72..05534e13e35b 100644 --- a/t/debug/debug-mode.t +++ b/t/debug/debug-mode.t @@ -60,7 +60,7 @@ loaded plugin and sort by priority: 10000 name: serverless-pre-function loaded plugin and sort by priority: 4010 name: batch-requests loaded plugin and sort by priority: 4000 name: cors loaded plugin and sort by priority: 3000 name: ip-restriction -loaded plugin and sort by priority: 2900 name: uri-blocklist +loaded plugin and sort by priority: 2900 name: uri-blocker loaded plugin and sort by priority: 2599 name: openid-connect loaded plugin and sort by priority: 2555 name: wolf-rbac loaded plugin and sort by priority: 2520 name: basic-auth diff --git a/t/plugin/uri-blocklist.t b/t/plugin/uri-blocker.t similarity index 92% rename from t/plugin/uri-blocklist.t rename to t/plugin/uri-blocker.t index 6f59027cab36..daab3cd9a004 100644 --- a/t/plugin/uri-blocklist.t +++ b/t/plugin/uri-blocker.t @@ -34,7 +34,7 @@ location /t { ngx.HTTP_PUT, [[{ "plugins": { - "uri-blocklist": { + "uri-blocker": { "filter_rules": [".+("] } }, @@ -51,7 +51,7 @@ location /t { GET /t --- error_code: 400 --- response_body -{"error_msg":"failed to check the configuration of plugin uri-blocklist err: pcre_compile() failed: missing ) in \".+(\""} +{"error_msg":"failed to check the configuration of plugin uri-blocker err: pcre_compile() failed: missing ) in \".+(\""} --- no_error_log [error] @@ -66,7 +66,7 @@ location /t { ngx.HTTP_PUT, [[{ "plugins": { - "uri-blocklist": { + "uri-blocker": { "filter_rules": ["^a", "^b"] } }, @@ -100,7 +100,7 @@ location /t { ngx.HTTP_PUT, [[{ "plugins": { - "uri-blocklist": { + "uri-blocker": { "filter_rules": ["^a", "^b("] } }, @@ -118,7 +118,7 @@ location /t { GET /t --- error_code: 400 --- response_body -{"error_msg":"failed to check the configuration of plugin uri-blocklist err: pcre_compile() failed: missing ) in \"^b(\""} +{"error_msg":"failed to check the configuration of plugin uri-blocker err: pcre_compile() failed: missing ) in \"^b(\""} --- no_error_log [error] @@ -133,7 +133,7 @@ location /t { ngx.HTTP_PUT, [[{ "plugins": { - "uri-blocklist": { + "uri-blocker": { "filter_rules": ["aa"] } }, @@ -149,7 +149,7 @@ location /t { "node": { "value": { "plugins": { - "uri-blocklist": { + "uri-blocker": { "filter_rules": ["aa"] } } From a4fb6a6404f7b44f08a268302a74b8dd5ad06b88 Mon Sep 17 00:00:00 2001 From: Yuansheng Wang Date: Thu, 18 Jun 2020 09:39:02 +0800 Subject: [PATCH 06/11] change: name style. --- apisix/plugins/uri-blocker.lua | 16 ++++++++-------- doc/plugins/uri-blocker.md | 2 +- t/plugin/uri-blocker.t | 14 +++++++------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/apisix/plugins/uri-blocker.lua b/apisix/plugins/uri-blocker.lua index 9a6bd2401003..c9d5bddb3b4c 100644 --- a/apisix/plugins/uri-blocker.lua +++ b/apisix/plugins/uri-blocker.lua @@ -22,7 +22,7 @@ local ipairs = ipairs local schema = { type = "object", properties = { - filter_rules = { + block_rules = { type = "array", items = { type = "string", @@ -37,7 +37,7 @@ local schema = { default = 403 }, }, - required = {"filter_rules"}, + required = {"block_rules"}, } @@ -57,25 +57,25 @@ function _M.check_schema(conf) return false, err end - local filter_rules = {} - for i, re_rule in ipairs(conf.filter_rules) do + local block_rules = {} + for i, re_rule in ipairs(conf.block_rules) do local ok, err = re_compile(re_rule, "j") -- core.log.warn("ok: ", tostring(ok), " err: ", tostring(err), " re_rule: ", re_rule) if not ok then return false, err end - filter_rules[i] = re_rule + block_rules[i] = re_rule end - conf.filter_rules_concat = core.table.concat(filter_rules, "|") - core.log.info("concat filter_rules: ", conf.filter_rules_concat) + conf.block_rules_concat = core.table.concat(block_rules, "|") + core.log.info("concat block_rules: ", conf.block_rules_concat) return true end function _M.rewrite(conf, ctx) core.log.info("uri: ", ctx.var.request_uri) - local from = re_find(ctx.var.request_uri, conf.filter_rules_concat, "jo") + local from = re_find(ctx.var.request_uri, conf.block_rules_concat, "jo") if from then core.response.exit(conf.rejected_code) end diff --git a/doc/plugins/uri-blocker.md b/doc/plugins/uri-blocker.md index 35000c890c80..270f3039c2d0 100644 --- a/doc/plugins/uri-blocker.md +++ b/doc/plugins/uri-blocker.md @@ -48,7 +48,7 @@ curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335 "uri": "/*", "plugins": { "uri-blocker": { - "filter_rules": ["root.exe", "root.m+"] + "block_rules": ["root.exe", "root.m+"] } }, "upstream": { diff --git a/t/plugin/uri-blocker.t b/t/plugin/uri-blocker.t index daab3cd9a004..59030845b084 100644 --- a/t/plugin/uri-blocker.t +++ b/t/plugin/uri-blocker.t @@ -35,7 +35,7 @@ location /t { [[{ "plugins": { "uri-blocker": { - "filter_rules": [".+("] + "block_rules": [".+("] } }, "uri": "/hello" @@ -67,7 +67,7 @@ location /t { [[{ "plugins": { "uri-blocker": { - "filter_rules": ["^a", "^b"] + "block_rules": ["^a", "^b"] } }, "uri": "/hello" @@ -87,7 +87,7 @@ passed --- no_error_log [error] --- error_log -concat filter_rules: ^a|^b, +concat block_rules: ^a|^b, @@ -101,7 +101,7 @@ location /t { [[{ "plugins": { "uri-blocker": { - "filter_rules": ["^a", "^b("] + "block_rules": ["^a", "^b("] } }, "uri": "/hello" @@ -134,7 +134,7 @@ location /t { [[{ "plugins": { "uri-blocker": { - "filter_rules": ["aa"] + "block_rules": ["aa"] } }, "upstream": { @@ -150,7 +150,7 @@ location /t { "value": { "plugins": { "uri-blocker": { - "filter_rules": ["aa"] + "block_rules": ["aa"] } } } @@ -171,7 +171,7 @@ passed --- no_error_log [error] --- error_log -concat filter_rules: aa, +concat block_rules: aa, From eb40c664ff8b227192291553374264b2c33b32c7 Mon Sep 17 00:00:00 2001 From: YuanSheng Wang Date: Sat, 20 Jun 2020 08:40:10 +0800 Subject: [PATCH 07/11] Update uri-blocker.lua --- apisix/plugins/uri-blocker.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/apisix/plugins/uri-blocker.lua b/apisix/plugins/uri-blocker.lua index c9d5bddb3b4c..ab5b6828e772 100644 --- a/apisix/plugins/uri-blocker.lua +++ b/apisix/plugins/uri-blocker.lua @@ -75,6 +75,7 @@ end function _M.rewrite(conf, ctx) core.log.info("uri: ", ctx.var.request_uri) + core.log.info("block uri rules: ", conf.block_rules_concat) local from = re_find(ctx.var.request_uri, conf.block_rules_concat, "jo") if from then core.response.exit(conf.rejected_code) From 4e98e60c70f04f62c9d01a3671e55dfdeaf63d5b Mon Sep 17 00:00:00 2001 From: Yuansheng Date: Sat, 20 Jun 2020 10:17:11 +0800 Subject: [PATCH 08/11] doc: new style. --- doc/README_CN.md | 68 --------------------------------------------- doc/zh-cn/README.md | 1 + 2 files changed, 1 insertion(+), 68 deletions(-) delete mode 100644 doc/README_CN.md diff --git a/doc/README_CN.md b/doc/README_CN.md deleted file mode 100644 index 97b0880742a9..000000000000 --- a/doc/README_CN.md +++ /dev/null @@ -1,68 +0,0 @@ - -[English](README.md) - -Reference document -================== - -* [APISIX 说明](../README_CN.md) -* [架构设计](architecture-design-cn.md) -* [压力测试](benchmark-cn.md) -* [如何构建 Apache APISIX](how-to-build-cn.md) -* [健康检查](health-check.md): 支持对上游节点的主动和被动健康检查,在负载均衡时自动过滤掉不健康的节点。 -* Router(路由) - * [radixtree](router-radixtree.md) -* [独立运行模型](stand-alone-cn.md): 支持从本地 yaml 格式的配置文件启动,更适合 Kubernetes(k8s) 体系。 -* [TCP/UDP 动态代理](stream-proxy-cn.md) -* [管理 API](admin-api-cn.md) -* [变更日志](../CHANGELOG_CN.md) -* [代码风格](../CODE_STYLE.md) -* [常见问答](../FAQ_CN.md) - -插件 -=== - -* [插件热加载](plugins-cn.md):无需重启服务,完成插件热加载或卸载。 -* [HTTPS](https-cn.md):根据 TLS 扩展字段 SNI(Server Name Indication) 动态加载证书。 -* [动态负载均衡](architecture-design-cn.md#upstream):跨多个上游服务的动态负载均衡,目前已支持 round-robin 和一致性哈希算法。 -* [key-auth](plugins/key-auth-cn.md):基于 Key Authentication 的用户认证。 -* [JWT-auth](plugins/jwt-auth-cn.md):基于 [JWT](https://jwt.io/) (JSON Web Tokens) Authentication 的用户认证。 -* [basic-auth](plugins/basic-auth-cn.md):基于 basic auth 的用户认证。 -* [wolf-rbac](plugins/wolf-rbac-cn.md) 基于 *RBAC* 的用户认证及授权。 -* [limit-count](plugins/limit-count-cn.md):基于“固定窗口”的限速实现。 -* [limit-req](plugins/limit-req-cn.md):基于漏桶原理的请求限速实现。 -* [limit-conn](plugins/limit-conn-cn.md):限制并发请求(或并发连接)。 -* [proxy-rewrite](plugins/proxy-rewrite-cn.md): 支持自定义修改 proxy 到上游的信息。 -* [prometheus](plugins/prometheus-cn.md):以 Prometheus 格式导出 APISIX 自身的状态信息,方便被外部 Prometheus 服务抓取。 -* [OpenTracing](plugins/zipkin-cn.md):支持 Zikpin 和 Apache SkyWalking。 -* [grpc-transcode](plugins/grpc-transcode-cn.md):REST <--> gRPC 转码。 -* [serverless](plugins/serverless-cn.md):允许在 APISIX 中的不同阶段动态运行 Lua 代码。 -* [ip-restriction](plugins/ip-restriction-cn.md): IP 黑白名单。 -* [openid-connect](plugins/oauth.md) -* [redirect](plugins/redirect-cn.md): URI 重定向。 -* [response-rewrite](plugins/response-rewrite-cn.md): 支持自定义修改返回内容的 `status code`、`body`、`headers`。 -* [fault-injection](plugins/fault-injection-cn.md):故障注入,可以返回指定的响应体、响应码和响应时间,从而提供了不同的失败场景下处理的能力,例如服务失败、服务过载、服务高延时等。 -* [proxy-cache](plugins/proxy-cache-cn.md):代理缓存插件提供缓存后端响应数据的能力。 -* [proxy-mirror](plugins/proxy-mirror-cn.md):代理镜像插件提供镜像客户端请求的能力。 -* [udp-logger](plugins/udp-logger.md): 将请求记录到UDP服务器。 -* [tcp-logger](plugins/tcp-logger.md): 将请求记录到TCP服务器。 -* [kafka-logger](plugins/kafka-logger-cn.md): 将请求记录到外部Kafka服务器。 -* [cors](plugins/cors-cn.md): 为你的API启用CORS。 -* [batch-requests](plugins/batch-requests-cn.md): 以 **http pipeline** 的方式在网关一次性发起多个 `http` 请求。 -* [uri-blocker](plugins/uri-blocker.md): 根据 URI 拦截用户请求。 diff --git a/doc/zh-cn/README.md b/doc/zh-cn/README.md index 2d9965cb33fa..9b2c6c5a0f33 100644 --- a/doc/zh-cn/README.md +++ b/doc/zh-cn/README.md @@ -67,3 +67,4 @@ Reference document * [cors](plugins/cors.md): 为你的API启用 CORS * [batch-requests](plugins/batch-requests.md): 以 **http pipeline** 的方式在网关一次性发起多个 `http` 请求。 * [authz-keycloak](plugins/authz-keycloak-cn.md): 支持 Keycloak 身份认证服务器 +* [uri-blocker](plugins/uri-blocker.md): 根据 URI 拦截用户请求。 From dd8241398181e6d00f3385e2f5685c4fe8084787 Mon Sep 17 00:00:00 2001 From: Yuansheng Date: Sat, 20 Jun 2020 10:24:00 +0800 Subject: [PATCH 09/11] test: added more test cases. --- t/plugin/uri-blocker.t | 79 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 77 insertions(+), 2 deletions(-) diff --git a/t/plugin/uri-blocker.t b/t/plugin/uri-blocker.t index 59030845b084..5f10640e4a66 100644 --- a/t/plugin/uri-blocker.t +++ b/t/plugin/uri-blocker.t @@ -175,7 +175,7 @@ concat block_rules: aa, -=== TEST 5: hit blocklist +=== TEST 5: hit block rule --- request GET /hello?aa=1 --- error_code: 403 @@ -184,8 +184,83 @@ GET /hello?aa=1 -=== TEST 6: miss blocklist +=== TEST 6: miss block rule --- request GET /hello?bb=2 --- no_error_log [error] + + + +=== TEST 7: multiple block rules +--- config +location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "plugins": { + "uri-blocker": { + "block_rules": ["aa", "bb", "c\\d+"] + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/hello" + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } +} +--- request +GET /t +--- response_body +passed +--- no_error_log +[error] +--- error_log +concat block_rules: aa|bb|c\d+, + + + +=== TEST 8: hit block rule +--- request +GET /hello?x=bb +--- error_code: 403 +--- no_error_log +[error] + + + +=== TEST 9: hit block rule +--- request +GET /hello?bb=2 +--- error_code: 403 +--- no_error_log +[error] + + + +=== TEST 10: hit block rule +--- request +GET /hello?c1=2 +--- error_code: 403 +--- no_error_log +[error] + + + +=== TEST 11: not hit block rule +--- request +GET /hello?cc=2 +--- no_error_log +[error] From 06b994efcafaa360c1e67232a592ae6b81c2a7cc Mon Sep 17 00:00:00 2001 From: Yuansheng Wang Date: Mon, 22 Jun 2020 14:14:06 +0800 Subject: [PATCH 10/11] doc: udpate readme.md --- README.md | 3 ++- README_CN.md | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index da9ccf16de28..3572484d373b 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,8 @@ A/B testing, canary release, blue-green deployment, limit rate, defense against - [Limit-count](doc/plugins/limit-count.md) - [Limit-concurrency](doc/plugins/limit-conn.md) - Anti-ReDoS(Regular expression Denial of Service): Built-in policies to Anti ReDoS without configuration. - - [CORS](doc/plugins/cors.md) + - [CORS](doc/plugins/cors.md) Enable CORS(Cross-origin resource sharing) for your API. + - [uri-blocker](plugins/uri-blocker.md): Block client request by URI. - **OPS friendly** - OpenTracing: support [Apache Skywalking](doc/plugins/skywalking.md) and [Zipkin](doc/plugins/zipkin.md) diff --git a/README_CN.md b/README_CN.md index 1fbd99814699..637c3a6db67c 100644 --- a/README_CN.md +++ b/README_CN.md @@ -90,7 +90,8 @@ A/B 测试、金丝雀发布(灰度发布)、蓝绿部署、限流限速、抵 - [限制请求数](doc/zh-cn/plugins/limit-count.md) - [限制并发](doc/zh-cn/plugins/limit-conn.md) - 防御 ReDoS(正则表达式拒绝服务):内置策略,无需配置即可抵御 ReDoS。 - - [CORS](doc/zh-cn/plugins/cors.md) + - [CORS](doc/zh-cn/plugins/cors.md):为你的API启用 CORS. + - [uri-blocker](plugins/uri-blocker.md):根据 URI 拦截用户请求. - **运维友好** - OpenTracing 可观测性: 支持 [Apache Skywalking](doc/zh-cn/plugins/skywalking.md) 和 [Zipkin](doc/zh-cn/plugins/zipkin.md)。 From 863cb97728d2361e01d42f2cab156c21069b1513 Mon Sep 17 00:00:00 2001 From: Yuansheng Wang Date: Mon, 22 Jun 2020 14:15:02 +0800 Subject: [PATCH 11/11] doc: use Chinese dot. --- README_CN.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README_CN.md b/README_CN.md index 637c3a6db67c..408fc2227a1b 100644 --- a/README_CN.md +++ b/README_CN.md @@ -90,8 +90,8 @@ A/B 测试、金丝雀发布(灰度发布)、蓝绿部署、限流限速、抵 - [限制请求数](doc/zh-cn/plugins/limit-count.md) - [限制并发](doc/zh-cn/plugins/limit-conn.md) - 防御 ReDoS(正则表达式拒绝服务):内置策略,无需配置即可抵御 ReDoS。 - - [CORS](doc/zh-cn/plugins/cors.md):为你的API启用 CORS. - - [uri-blocker](plugins/uri-blocker.md):根据 URI 拦截用户请求. + - [CORS](doc/zh-cn/plugins/cors.md):为你的API启用 CORS。 + - [uri-blocker](plugins/uri-blocker.md):根据 URI 拦截用户请求。 - **运维友好** - OpenTracing 可观测性: 支持 [Apache Skywalking](doc/zh-cn/plugins/skywalking.md) 和 [Zipkin](doc/zh-cn/plugins/zipkin.md)。