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]