You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by me...@apache.org on 2020/09/19 10:21:30 UTC

[apisix] branch master updated: feature: `consumer` provides access to a collection of `service` (#2241)

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

membphis 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 e94a5b3  feature: `consumer` provides access to a collection of `service`  (#2241)
e94a5b3 is described below

commit e94a5b3f584024744c7c602984f70fedd37a9f7e
Author: Firstsawyou <52...@users.noreply.github.com>
AuthorDate: Sat Sep 19 18:21:21 2020 +0800

    feature: `consumer` provides access to a collection of `service`  (#2241)
    
    * test: add more test cases.
    
    Co-authored-by: Yuansheng Wang <me...@gmail.com>
---
 apisix/init.lua                         |   2 +
 apisix/plugins/consumer-restriction.lua |  33 +-
 t/plugin/consumer-restriction.t         | 711 +++++++++++++++++++++++++++++++-
 3 files changed, 735 insertions(+), 11 deletions(-)

diff --git a/apisix/init.lua b/apisix/init.lua
index 63275c1..9f8b38b 100644
--- a/apisix/init.lua
+++ b/apisix/init.lua
@@ -403,11 +403,13 @@ function _M.http_access_phase()
         api_ctx.conf_type = "route&service"
         api_ctx.conf_version = route.modifiedIndex .. "&" .. service.modifiedIndex
         api_ctx.conf_id = route.value.id .. "&" .. service.value.id
+        api_ctx.service_id = service.value.id
     else
         api_ctx.conf_type = "route"
         api_ctx.conf_version = route.modifiedIndex
         api_ctx.conf_id = route.value.id
     end
+    api_ctx.route_id = route.value.id
 
     local enable_websocket
     local up_id = route.value.upstream_id
diff --git a/apisix/plugins/consumer-restriction.lua b/apisix/plugins/consumer-restriction.lua
index 912e212..f80e096 100644
--- a/apisix/plugins/consumer-restriction.lua
+++ b/apisix/plugins/consumer-restriction.lua
@@ -20,6 +20,11 @@ local core      = require("apisix.core")
 local schema = {
     type = "object",
     properties = {
+        type = {
+            type = "string",
+            enum = {"consumer_name", "service_id"},
+            default = "consumer_name"
+        },
         whitelist = {
             type = "array",
             items = {type = "string"},
@@ -29,7 +34,8 @@ local schema = {
             type = "array",
             items = {type = "string"},
             minItems = 1
-        }
+        },
+        rejected_code = {type = "integer", minimum = 200, default = 403}
     },
     oneOf = {
         {required = {"whitelist"}},
@@ -37,10 +43,8 @@ local schema = {
     }
 }
 
-
 local plugin_name = "consumer-restriction"
 
-
 local _M = {
     version = 0.1,
     priority = 2400,
@@ -48,6 +52,15 @@ local _M = {
     schema = schema,
 }
 
+local fetch_val_funcs = {
+    ["service_id"] = function(ctx)
+        return ctx.service_id
+    end,
+    ["consumer_name"] = function(ctx)
+        return ctx.consumer_id
+    end
+}
+
 local function is_include(value, tab)
     for k,v in ipairs(tab) do
         if v == value then
@@ -57,6 +70,7 @@ local function is_include(value, tab)
     return false
 end
 
+
 function _M.check_schema(conf)
     local ok, err = core.schema.check(schema, conf)
 
@@ -67,26 +81,29 @@ function _M.check_schema(conf)
     return true
 end
 
+
 function _M.access(conf, ctx)
-    if not ctx.consumer then
-        return 401, { message = "Missing authentication or identity verification." }
+    local value = fetch_val_funcs[conf.type](ctx)
+    if not value then
+        return 401, { message = "Missing authentication or identity verification."}
     end
+    core.log.info("value: ", value)
 
     local block = false
     if conf.blacklist and #conf.blacklist > 0 then
-        if is_include(ctx.consumer.username, conf.blacklist) then
+        if is_include(value, conf.blacklist) then
             block = true
         end
     end
 
     if conf.whitelist and #conf.whitelist > 0 then
-        if not is_include(ctx.consumer.username, conf.whitelist) then
+        if not is_include(value, conf.whitelist) then
             block = true
         end
     end
 
     if block then
-        return 403, { message = "The consumer is not allowed" }
+        return conf.rejected_code, { message = "The " .. conf.type .. " is forbidden." }
     end
 end
 
diff --git a/t/plugin/consumer-restriction.t b/t/plugin/consumer-restriction.t
index 57bbed3..69708ea 100644
--- a/t/plugin/consumer-restriction.t
+++ b/t/plugin/consumer-restriction.t
@@ -47,7 +47,7 @@ __DATA__
 --- request
 GET /t
 --- response_body
-{"whitelist":["jack1","jack2"]}
+{"rejected_code":403,"type":"consumer_name","whitelist":["jack1","jack2"]}
 --- no_error_log
 [error]
 
@@ -237,7 +237,7 @@ GET /hello
 Authorization: Basic amFjazIwMjA6MTIzNDU2
 --- error_code: 403
 --- response_body
-{"message":"The consumer is not allowed"}
+{"message":"The consumer_name is forbidden."}
 --- no_error_log
 [error]
 
@@ -302,7 +302,7 @@ GET /hello
 Authorization: Basic amFjazIwMTk6MTIzNDU2
 --- error_code: 403
 --- response_body
-{"message":"The consumer is not allowed"}
+{"message":"The consumer_name is forbidden."}
 --- no_error_log
 [error]
 
@@ -540,3 +540,708 @@ GET /hello
 hello world
 --- no_error_log
 [error]
+
+
+
+=== TEST 25: create service (id:1)
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local code, body = t('/apisix/admin/services/1',
+                 ngx.HTTP_PUT,
+                 [[{
+                    "upstream": {
+                        "nodes": {
+                            "127.0.0.1:1980": 1
+                        },
+                        "type": "roundrobin"
+                    },
+                    "desc": "new service 001"
+                }]],
+                [[{
+                    "node": {
+                        "value": {
+                            "upstream": {
+                                "nodes": {
+                                    "127.0.0.1:1980": 1
+                                },
+                                "type": "roundrobin"
+                            },
+                            "desc": "new service 001"
+                        },
+                        "key": "/apisix/services/1"
+                    },
+                    "action": "set"
+                }]]
+                )
+
+            ngx.status = code
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 26: add consumer with plugin hmac-auth and consumer-restriction, and set whitelist
+--- 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": "jack",
+                    "plugins": {
+                        "hmac-auth": {
+                            "access_key": "my-access-key",
+                            "secret_key": "my-secret-key"
+                        },
+                        "consumer-restriction": {
+                            "type": "service_id",
+                            "whitelist": [ "1" ],
+                            "rejected_code": 401
+                        }
+                    }
+                }]],
+                [[{
+                    "node": {
+                        "value": {
+                            "username": "jack",
+                            "plugins": {
+                                "hmac-auth": {
+                                    "access_key": "my-access-key",
+                                    "secret_key": "my-secret-key",
+                                    "algorithm": "hmac-sha256",
+                                    "clock_skew": 300
+                                },
+                                "consumer-restriction": {
+                                    "type": "service_id",
+                                    "whitelist": [ "1" ],
+                                    "rejected_code": 401
+                                }
+                            }
+                        }
+                    },
+                    "action": "set"
+                }]]
+                )
+
+            ngx.status = code
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 27: Route binding `hmac-auth` plug-in and whitelist `service_id`
+--- 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,
+                [[{
+                    "methods": ["GET"],
+                    "upstream": {
+                        "nodes": {
+                            "127.0.0.1:1980": 1
+                        },
+                        "type": "roundrobin"
+                    },
+                    "service_id": 1,
+                    "uri": "/hello",
+                    "plugins": {
+                        "hmac-auth": {}
+                    }
+
+                }]],
+                [[{
+                    "node": {
+                        "value": {
+                            "methods": [
+                                "GET"
+                            ],
+                            "uri": "/hello",
+                            "upstream": {
+                                "nodes": {
+                                    "127.0.0.1:1980": 1
+                                },
+                                "type": "roundrobin"
+                            },
+                            "service_id": 1,
+                            "plugins": {
+                                "hmac-auth": {}
+                            }
+                        },
+                        "key": "/apisix/routes/1"
+                    },
+                    "action": "set"
+                }]]
+                )
+
+            ngx.status = code
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 28: verify: valid whitelist `service_id`
+--- config
+location /t {
+    content_by_lua_block {
+        local ngx_time   = ngx.time
+        local core = require("apisix.core")
+        local t = require("lib.test_admin")
+        local hmac = require("resty.hmac")
+        local ngx_encode_base64 = ngx.encode_base64
+
+        local secret_key = "my-secret-key"
+        local timestamp = ngx_time()
+        local access_key = "my-access-key"
+        local custom_header_a = "asld$%dfasf"
+        local custom_header_b = "23879fmsldfk"
+
+        local signing_string = "GET" .. "/hello" ..  "" ..
+            access_key .. timestamp .. custom_header_a .. custom_header_b
+
+        local signature = hmac:new(secret_key, hmac.ALGOS.SHA256):final(signing_string)
+        core.log.info("signature:", ngx_encode_base64(signature))
+        local headers = {}
+        headers["X-HMAC-SIGNATURE"] = ngx_encode_base64(signature)
+        headers["X-HMAC-ALGORITHM"] = "hmac-sha256"
+        headers["X-HMAC-TIMESTAMP"] = timestamp
+        headers["X-HMAC-ACCESS-KEY"] = access_key
+        headers["X-HMAC-SIGNED-HEADERS"] = "x-custom-header-a;x-custom-header-b"
+        headers["x-custom-header-a"] = custom_header_a
+        headers["x-custom-header-b"] = custom_header_b
+
+        local code, body = t.test('/hello',
+            ngx.HTTP_GET,
+            "",
+            nil,
+            headers
+        )
+
+        ngx.status = code
+        ngx.say(body)
+    }
+}
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 29: create service (id:2)
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local code, body = t('/apisix/admin/services/2',
+                 ngx.HTTP_PUT,
+                 [[{
+                    "upstream": {
+                        "nodes": {
+                            "127.0.0.1:1980": 1
+                        },
+                        "type": "roundrobin"
+                    },
+                    "desc": "new service 002"
+                }]],
+                [[{
+                    "node": {
+                        "value": {
+                            "upstream": {
+                                "nodes": {
+                                    "127.0.0.1:1980": 1
+                                },
+                                "type": "roundrobin"
+                            },
+                            "desc": "new service 002"
+                        },
+                        "key": "/apisix/services/2"
+                    },
+                    "action": "set"
+                }]]
+                )
+
+            ngx.status = code
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 30: Route binding `hmac-auth` plug-in and invalid whitelist `service_id`
+--- 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,
+                [[{
+                    "methods": ["GET"],
+                    "upstream": {
+                        "nodes": {
+                            "127.0.0.1:1980": 1
+                        },
+                        "type": "roundrobin"
+                    },
+                    "service_id": 2,
+                    "uri": "/hello",
+                    "plugins": {
+                        "hmac-auth": {}
+                    }
+
+                }]],
+                [[{
+                    "node": {
+                        "value": {
+                            "methods": [
+                                "GET"
+                            ],
+                            "uri": "/hello",
+                            "upstream": {
+                                "nodes": {
+                                    "127.0.0.1:1980": 1
+                                },
+                                "type": "roundrobin"
+                            },
+                            "service_id": 2,
+                            "plugins": {
+                                "hmac-auth": {}
+                            }
+                        },
+                        "key": "/apisix/routes/1"
+                    },
+                    "action": "set"
+                }]]
+                )
+
+            ngx.status = code
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 31: verify: invalid whitelist `service_id`
+--- config
+location /t {
+    content_by_lua_block {
+        local ngx_time   = ngx.time
+        local core = require("apisix.core")
+        local t = require("lib.test_admin")
+        local hmac = require("resty.hmac")
+        local ngx_encode_base64 = ngx.encode_base64
+
+        local secret_key = "my-secret-key"
+        local timestamp = ngx_time()
+        local access_key = "my-access-key"
+        local custom_header_a = "asld$%dfasf"
+        local custom_header_b = "23879fmsldfk"
+
+        local signing_string = "GET" .. "/hello" ..  "" ..
+            access_key .. timestamp .. custom_header_a .. custom_header_b
+
+        local signature = hmac:new(secret_key, hmac.ALGOS.SHA256):final(signing_string)
+        core.log.info("signature:", ngx_encode_base64(signature))
+        local headers = {}
+        headers["X-HMAC-SIGNATURE"] = ngx_encode_base64(signature)
+        headers["X-HMAC-ALGORITHM"] = "hmac-sha256"
+        headers["X-HMAC-TIMESTAMP"] = timestamp
+        headers["X-HMAC-ACCESS-KEY"] = access_key
+        headers["X-HMAC-SIGNED-HEADERS"] = "x-custom-header-a;x-custom-header-b"
+        headers["x-custom-header-a"] = custom_header_a
+        headers["x-custom-header-b"] = custom_header_b
+
+        local code, body = t.test('/hello',
+            ngx.HTTP_GET,
+            "",
+            nil,
+            headers
+        )
+        if code >= 300 then
+            ngx.status = code
+        end
+        
+        ngx.say(body)
+    }
+}
+--- request
+GET /t
+--- error_code: 401
+--- response_body eval
+qr/\{"message":"The service_id is forbidden."\}/
+--- no_error_log
+[error]
+
+
+
+=== TEST 32: add consumer with plugin hmac-auth and consumer-restriction, and set blacklist
+--- 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": "jack",
+                    "plugins": {
+                        "hmac-auth": {
+                            "access_key": "my-access-key",
+                            "secret_key": "my-secret-key"
+                        },
+                        "consumer-restriction": {
+                            "type": "service_id",
+                            "blacklist": [ "1" ],
+                            "rejected_code": 401
+                        }
+                    }
+                }]],
+                [[{
+                    "node": {
+                        "value": {
+                            "username": "jack",
+                            "plugins": {
+                                "hmac-auth": {
+                                    "access_key": "my-access-key",
+                                    "secret_key": "my-secret-key",
+                                    "algorithm": "hmac-sha256",
+                                    "clock_skew": 300
+                                },
+                                "consumer-restriction": {
+                                    "type": "service_id",
+                                    "blacklist": [ "1" ],
+                                    "rejected_code": 401
+                                }
+                            }
+                        }
+                    },
+                    "action": "set"
+                }]]
+                )
+
+            ngx.status = code
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 33: Route binding `hmac-auth` plug-in and blacklist `service_id`
+--- 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,
+                [[{
+                    "methods": ["GET"],
+                    "upstream": {
+                        "nodes": {
+                            "127.0.0.1:1980": 1
+                        },
+                        "type": "roundrobin"
+                    },
+                    "service_id": 1,
+                    "uri": "/hello",
+                    "plugins": {
+                        "hmac-auth": {}
+                    }
+
+                }]],
+                [[{
+                    "node": {
+                        "value": {
+                            "methods": [
+                                "GET"
+                            ],
+                            "uri": "/hello",
+                            "upstream": {
+                                "nodes": {
+                                    "127.0.0.1:1980": 1
+                                },
+                                "type": "roundrobin"
+                            },
+                            "service_id": 1,
+                            "plugins": {
+                                "hmac-auth": {}
+                            }
+                        },
+                        "key": "/apisix/routes/1"
+                    },
+                    "action": "set"
+                }]]
+                )
+
+            ngx.status = code
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 34: verify: valid blacklist `service_id`
+--- config
+location /t {
+    content_by_lua_block {
+        local ngx_time   = ngx.time
+        local core = require("apisix.core")
+        local t = require("lib.test_admin")
+        local hmac = require("resty.hmac")
+        local ngx_encode_base64 = ngx.encode_base64
+
+        local secret_key = "my-secret-key"
+        local timestamp = ngx_time()
+        local access_key = "my-access-key"
+        local custom_header_a = "asld$%dfasf"
+        local custom_header_b = "23879fmsldfk"
+
+        local signing_string = "GET" .. "/hello" ..  "" ..
+            access_key .. timestamp .. custom_header_a .. custom_header_b
+
+        local signature = hmac:new(secret_key, hmac.ALGOS.SHA256):final(signing_string)
+        core.log.info("signature:", ngx_encode_base64(signature))
+        local headers = {}
+        headers["X-HMAC-SIGNATURE"] = ngx_encode_base64(signature)
+        headers["X-HMAC-ALGORITHM"] = "hmac-sha256"
+        headers["X-HMAC-TIMESTAMP"] = timestamp
+        headers["X-HMAC-ACCESS-KEY"] = access_key
+        headers["X-HMAC-SIGNED-HEADERS"] = "x-custom-header-a;x-custom-header-b"
+        headers["x-custom-header-a"] = custom_header_a
+        headers["x-custom-header-b"] = custom_header_b
+
+        local code, body = t.test('/hello',
+            ngx.HTTP_GET,
+            "",
+            nil,
+            headers
+        )
+
+        ngx.status = code
+        ngx.say(body)
+    }
+}
+--- request
+GET /t
+--- error_code: 401
+--- response_body eval
+qr/\{"message":"The service_id is forbidden."\}/
+--- no_error_log
+[error]
+
+
+=== TEST 35: Route binding `hmac-auth` plug-in and invalid blacklist `service_id`
+--- 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,
+                [[{
+                    "methods": ["GET"],
+                    "upstream": {
+                        "nodes": {
+                            "127.0.0.1:1980": 1
+                        },
+                        "type": "roundrobin"
+                    },
+                    "service_id": 2,
+                    "uri": "/hello",
+                    "plugins": {
+                        "hmac-auth": {}
+                    }
+
+                }]],
+                [[{
+                    "node": {
+                        "value": {
+                            "methods": [
+                                "GET"
+                            ],
+                            "uri": "/hello",
+                            "upstream": {
+                                "nodes": {
+                                    "127.0.0.1:1980": 1
+                                },
+                                "type": "roundrobin"
+                            },
+                            "service_id": 2,
+                            "plugins": {
+                                "hmac-auth": {}
+                            }
+                        },
+                        "key": "/apisix/routes/1"
+                    },
+                    "action": "set"
+                }]]
+                )
+
+            ngx.status = code
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 36: verify: invalid blacklist `service_id`
+--- config
+location /t {
+    content_by_lua_block {
+        local ngx_time   = ngx.time
+        local core = require("apisix.core")
+        local t = require("lib.test_admin")
+        local hmac = require("resty.hmac")
+        local ngx_encode_base64 = ngx.encode_base64
+
+        local secret_key = "my-secret-key"
+        local timestamp = ngx_time()
+        local access_key = "my-access-key"
+        local custom_header_a = "asld$%dfasf"
+        local custom_header_b = "23879fmsldfk"
+
+        local signing_string = "GET" .. "/hello" ..  "" ..
+            access_key .. timestamp .. custom_header_a .. custom_header_b
+
+        local signature = hmac:new(secret_key, hmac.ALGOS.SHA256):final(signing_string)
+        core.log.info("signature:", ngx_encode_base64(signature))
+        local headers = {}
+        headers["X-HMAC-SIGNATURE"] = ngx_encode_base64(signature)
+        headers["X-HMAC-ALGORITHM"] = "hmac-sha256"
+        headers["X-HMAC-TIMESTAMP"] = timestamp
+        headers["X-HMAC-ACCESS-KEY"] = access_key
+        headers["X-HMAC-SIGNED-HEADERS"] = "x-custom-header-a;x-custom-header-b"
+        headers["x-custom-header-a"] = custom_header_a
+        headers["x-custom-header-b"] = custom_header_b
+
+        local code, body = t.test('/hello',
+            ngx.HTTP_GET,
+            "",
+            nil,
+            headers
+        )
+
+        ngx.status = code
+        ngx.say(body)
+    }
+}
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 37: delete: route (id: 1)
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local code, body = t( '/apisix/admin/routes/1', ngx.HTTP_DELETE )
+
+            ngx.status = code
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 38: delete: `service_id` is 1
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local code, body = t( '/apisix/admin/services/1', ngx.HTTP_DELETE )
+
+            ngx.status = code
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 39: delete: `service_id` is 2
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local code, body = t( '/apisix/admin/services/2', ngx.HTTP_DELETE )
+
+            ngx.status = code
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]