You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by sp...@apache.org on 2022/12/27 06:10:47 UTC

[apisix] branch master updated: feat: consumer-restriction plugin support consumer_group_id type (#8567)

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

spacewander 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 053c53a58 feat: consumer-restriction plugin support consumer_group_id type (#8567)
053c53a58 is described below

commit 053c53a588a371f83b3c18d8bd3a5ebcfbdd1298
Author: Ashing Zheng <ax...@gmail.com>
AuthorDate: Tue Dec 27 14:10:40 2022 +0800

    feat: consumer-restriction plugin support consumer_group_id type (#8567)
    
    Fixes https://github.com/apache/apisix/issues/8563
---
 apisix/plugins/consumer-restriction.lua        |   5 +-
 docs/en/latest/plugins/consumer-restriction.md |   3 +-
 docs/zh/latest/plugins/consumer-restriction.md |   3 +-
 t/plugin/consumer-restriction2.t               | 275 +++++++++++++++++++++++++
 4 files changed, 283 insertions(+), 3 deletions(-)

diff --git a/apisix/plugins/consumer-restriction.lua b/apisix/plugins/consumer-restriction.lua
index a9f7363a5..93f3b9f59 100644
--- a/apisix/plugins/consumer-restriction.lua
+++ b/apisix/plugins/consumer-restriction.lua
@@ -22,7 +22,7 @@ local schema = {
     properties = {
         type = {
             type = "string",
-            enum = {"consumer_name", "service_id", "route_id"},
+            enum = {"consumer_name", "service_id", "route_id", "consumer_group_id"},
             default = "consumer_name"
         },
         blacklist = {
@@ -79,6 +79,9 @@ local fetch_val_funcs = {
     end,
     ["consumer_name"] = function(ctx)
         return ctx.consumer_name
+    end,
+    ["consumer_group_id"] = function (ctx)
+        return ctx.consumer_group_id
     end
 }
 
diff --git a/docs/en/latest/plugins/consumer-restriction.md b/docs/en/latest/plugins/consumer-restriction.md
index 5b1fe10b0..d2daa0a40 100644
--- a/docs/en/latest/plugins/consumer-restriction.md
+++ b/docs/en/latest/plugins/consumer-restriction.md
@@ -34,7 +34,7 @@ The `consumer-restriction` Plugin allows users to set access restrictions based
 
 | Name               | Type          | Required | Default       | Valid values  | Description |
 |--------------------|---------------|----------|---------------|---------------|-------------|
-| type               | string        | False    | consumer_name | ["consumer_name", "service_id", "route_id"]  | Type of object to base the restriction on.  |
+| type               | string        | False    | consumer_name | ["consumer_name", "consumer_group_id", "service_id", "route_id"]  | Type of object to base the restriction on.  |
 | whitelist          | array[string] | True     |               |                                              | List of objects to whitelist. Has a higher priority than `allowed_by_methods`. |
 | blacklist          | array[string] | True     |               |                                              | List of objects to blacklist. Has a higher priority than `whitelist`.          |
 | rejected_code      | integer       | False    | 403           | [200,...]                                    | HTTP status code returned when the request is rejected.                        |
@@ -46,6 +46,7 @@ The `consumer-restriction` Plugin allows users to set access restrictions based
 The different values in the `type` attribute have these meanings:
 
 - `consumer_name`: Username of the Consumer to restrict access to a Route or a Service.
+- `consumer_group_id`: ID of the Consumer Group to restrict access to a Route or a Service.
 - `service_id`: ID of the Service to restrict access from a Consumer. Need to be used with an Authentication Plugin.
 - `route_id`: ID of the Route to restrict access from a Consumer.
 
diff --git a/docs/zh/latest/plugins/consumer-restriction.md b/docs/zh/latest/plugins/consumer-restriction.md
index c7926f12b..a2b885b46 100644
--- a/docs/zh/latest/plugins/consumer-restriction.md
+++ b/docs/zh/latest/plugins/consumer-restriction.md
@@ -34,7 +34,7 @@ description: Consumer Restriction 插件允许用户根据 Route、Service 或 C
 
 | 名称     | 类型          | 必选项   | 默认值            | 有效值                    | 描述                          |
 | --------- | ------------- | ------ | -----------------| -------------------------|------------------------|
-| type      | string    | 否    | consumer_name    | ["consumer_name", "service_id", "route_id"] | 支持设置访问限制的对象类型。 |
+| type      | string    | 否    | consumer_name    | ["consumer_name", "consumer_group_id", "service_id", "route_id"] | 支持设置访问限制的对象类型。 |
 | whitelist | array[string] | 是    |                  |                        | 加入白名单的对象,优先级高于 `allowed_by_methods`。 |
 | blacklist | array[string] | 是    |                  |                        | 加入黑名单的对象,优先级高于 `whitelist`。 |
 | rejected_code | integer   | 否    | 403              | [200,...]          | 当请求被拒绝时,返回的 HTTP 状态码。    |
@@ -46,6 +46,7 @@ description: Consumer Restriction 插件允许用户根据 Route、Service 或 C
 不同的 `type` 属性值分别代表以下含义:
 
 - `consumer_name`:把 Consumer 的 `username` 列入白名单或黑名单来限制 Consumer 对 Route 或 Service 的访问。
+- `consumer_group_id`: 把 Consumer Group 的 `id` 列入白名单或黑名单来限制 Consumer 对 Route 或 Service 的访问。
 - `service_id`:把 Service 的 `id` 列入白名单或黑名单来限制 Consumer 对 Service 的访问,需要结合授权插件一起使用。
 - `route_id`:把 Route 的 `id` 列入白名单或黑名单来限制 Consumer 对 Route 的访问。
 
diff --git a/t/plugin/consumer-restriction2.t b/t/plugin/consumer-restriction2.t
new file mode 100644
index 000000000..6fdba1daa
--- /dev/null
+++ b/t/plugin/consumer-restriction2.t
@@ -0,0 +1,275 @@
+#
+# 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_shuffle();
+no_root_location();
+
+run_tests;
+
+__DATA__
+
+=== TEST 1: create consumer group(group1)
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local code, body = t('/apisix/admin/consumer_groups/group1',
+                ngx.HTTP_PUT,
+                [[{
+                    "plugins": {}
+                }]]
+            )
+            if code >= 300 then
+                ngx.status = code
+            end
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+
+
+
+=== TEST 2: create consumer group(group2)
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local code, body = t('/apisix/admin/consumer_groups/group2',
+                ngx.HTTP_PUT,
+                [[{
+                    "plugins": {}
+                }]]
+            )
+            if code >= 300 then
+                ngx.status = code
+            end
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+
+
+
+=== TEST 3: consumer jack1 with consumer group(group1)
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local code, body = t('/apisix/admin/consumers',
+                ngx.HTTP_PUT,
+                [[{
+                    "username": "jack1",
+                    "plugins": {
+                        "basic-auth": {
+                            "username": "jack2019",
+                            "password": "123456"
+                        }
+                    },
+                    "group_id": "group1"
+                }]]
+                )
+            if code >= 300 then
+                ngx.status = code
+            end
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+
+
+
+=== TEST 4: consumer jack2 with consumer group(group2)
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local code, body = t('/apisix/admin/consumers',
+                ngx.HTTP_PUT,
+                [[{
+                    "username": "jack2",
+                    "plugins": {
+                        "basic-auth": {
+                            "username": "jack2020",
+                            "password": "123456"
+                        }
+                    },
+                    "group_id": "group2"
+                }]]
+                )
+            if code >= 300 then
+                ngx.status = code
+            end
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+
+
+
+=== TEST 5: set whitelist
+--- 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,
+                 [[{
+                        "uri": "/hello",
+                        "upstream": {
+                            "type": "roundrobin",
+                            "nodes": {
+                                "127.0.0.1:1980": 1
+                            }
+                        },
+                        "plugins": {
+                            "basic-auth": {},
+                            "consumer-restriction": {
+                                "type": "consumer_group_id",
+                                 "whitelist": [
+                                     "group1"
+                                 ]
+                            }
+                        }
+                }]]
+                )
+
+            if code >= 300 then
+                ngx.status = code
+            end
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+
+
+
+=== TEST 6: verify unauthorized
+--- request
+GET /hello
+--- error_code: 401
+--- response_body
+{"message":"Missing authorization in request"}
+
+
+
+=== TEST 7: verify jack1
+--- request
+GET /hello
+--- more_headers
+Authorization: Basic amFjazIwMTk6MTIzNDU2
+--- response_body
+hello world
+
+
+
+=== TEST 8: verify jack2
+--- request
+GET /hello
+--- more_headers
+Authorization: Basic amFjazIwMjA6MTIzNDU2
+--- error_code: 403
+--- response_body
+{"message":"The consumer_group_id is forbidden."}
+
+
+
+=== TEST 9: set blacklist
+--- 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,
+                 [[{
+                        "uri": "/hello",
+                        "upstream": {
+                            "type": "roundrobin",
+                            "nodes": {
+                                "127.0.0.1:1980": 1
+                            }
+                        },
+                        "plugins": {
+                            "basic-auth": {},
+                            "consumer-restriction": {
+                                 "type": "consumer_group_id",
+                                 "blacklist": [
+                                     "group1"
+                                 ],
+                                 "rejected_msg": "request is forbidden"
+                            }
+                        }
+                }]]
+                )
+
+            if code >= 300 then
+                ngx.status = code
+            end
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+
+
+
+=== TEST 10: verify unauthorized
+--- request
+GET /hello
+--- error_code: 401
+--- response_body
+{"message":"Missing authorization in request"}
+
+
+
+=== TEST 11: verify jack1
+--- request
+GET /hello
+--- more_headers
+Authorization: Basic amFjazIwMTk6MTIzNDU2
+--- error_code: 403
+--- response_body
+{"message":"request is forbidden"}
+
+
+
+=== TEST 12: verify jack2
+--- request
+GET /hello
+--- more_headers
+Authorization: Basic amFjazIwMjA6MTIzNDU2
+--- response_body
+hello world