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/12/01 07:43:39 UTC
[apisix] branch master updated: feat: allow create consumers with
multiple auth plugins (#2898)
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 a63b6b8 feat: allow create consumers with multiple auth plugins (#2898)
a63b6b8 is described below
commit a63b6b8c6e08d8af2327450dbdd1d73a92c27393
Author: 罗泽轩 <sp...@gmail.com>
AuthorDate: Tue Dec 1 15:42:59 2020 +0800
feat: allow create consumers with multiple auth plugins (#2898)
Fix #2850
---
apisix/admin/consumers.lua | 3 -
apisix/consumer.lua | 2 -
apisix/init.lua | 4 +
doc/admin-api.md | 4 +-
doc/zh-cn/admin-api.md | 4 +-
t/config-center-yaml/stream-route.t | 1 -
t/node/consumer-plugin.t | 236 +++++++++++++++++++++++++++++-------
7 files changed, 204 insertions(+), 50 deletions(-)
diff --git a/apisix/admin/consumers.lua b/apisix/admin/consumers.lua
index feaa708..14bd5cb 100644
--- a/apisix/admin/consumers.lua
+++ b/apisix/admin/consumers.lua
@@ -49,9 +49,6 @@ local function check_conf(conf)
local plugin_obj = plugin.get(name)
if plugin_obj.type == 'auth' then
count_auth_plugin = count_auth_plugin + 1
- if count_auth_plugin > 1 then
- return nil, {error_msg = "only one auth plugin is allowed"}
- end
end
end
diff --git a/apisix/consumer.lua b/apisix/consumer.lua
index a631544..3163e29 100644
--- a/apisix/consumer.lua
+++ b/apisix/consumer.lua
@@ -57,8 +57,6 @@ local function plugin_consumer()
new_consumer.auth_conf = config
core.log.info("consumer:", core.json.delay_encode(new_consumer))
core.table.insert(plugins[name].nodes, new_consumer)
-
- break
end
end
diff --git a/apisix/init.lua b/apisix/init.lua
index 827a1fb..30b729e 100644
--- a/apisix/init.lua
+++ b/apisix/init.lua
@@ -516,6 +516,10 @@ function _M.http_access_phase()
api_ctx.consumer,
api_ctx
)
+
+ core.log.info("find consumer ", api_ctx.consumer.username,
+ ", config changed: ", changed)
+
if changed then
core.table.clear(api_ctx.plugins)
api_ctx.plugins = plugin.filter(route, api_ctx.plugins)
diff --git a/doc/admin-api.md b/doc/admin-api.md
index 51e70c5..ba23f7e 100644
--- a/doc/admin-api.md
+++ b/doc/admin-api.md
@@ -450,7 +450,7 @@ Config Example:
}
```
-The binding authentication and authorization plug-in is a bit special. When it needs to be used in conjunction with the consumer, it needs to provide user name, password and other information; on the other hand, when it is bound with route / service, it does not require any parameters. Because at this time, it is based on the user request data to infer which consumer the user corresponds to.
+The binding authentication plug-in is a bit special. When it needs to be used in conjunction with the consumer, it needs to provide user name, password and other information; on the other hand, when it is bound with route / service, it does not require any parameters. Because at this time, it is based on the user request data to infer which consumer the user corresponds to.
Example:
@@ -476,6 +476,8 @@ Date: Thu, 26 Dec 2019 08:17:49 GMT
{"node":{"value":{"username":"jack","plugins":{"key-auth":{"key":"auth-one"},"limit-count":{"time_window":60,"count":2,"rejected_code":503,"key":"remote_addr","policy":"local"}}},"createdIndex":64,"key":"\/apisix\/consumers\/jack","modifiedIndex":64},"prevNode":{"value":"{\"username\":\"jack\",\"plugins\":{\"key-auth\":{\"key\":\"auth-one\"},\"limit-count\":{\"time_window\":60,\"count\":2,\"rejected_code\":503,\"key\":\"remote_addr\",\"policy\":\"local\"}}}","createdIndex":63,"key":"\/ap [...]
```
+Since `v2.2`, we can bind multiple authentication plugins to the same consumer.
+
> Response Parameters
Return response from etcd currently.
diff --git a/doc/zh-cn/admin-api.md b/doc/zh-cn/admin-api.md
index 5dae7d5..1e7cc4e 100644
--- a/doc/zh-cn/admin-api.md
+++ b/doc/zh-cn/admin-api.md
@@ -463,7 +463,7 @@ consumer 对象 json 配置内容:
}
```
-绑定认证授权插件有些特别,当它需要与 consumer 联合使用时,需要提供用户名、密码等信息;另一方面,当它与 route/service 绑定时,是不需要任何参数的。因为这时候是根据用户请求数据来反向推出用户对应的是哪个 consumer
+绑定认证插件有些特别,当它需要与 consumer 联合使用时,需要提供用户名、密码等信息;另一方面,当它与 route/service 绑定时,是不需要任何参数的。因为这时候是根据用户请求数据来反向推出用户对应的是哪个 consumer
示例:
@@ -491,6 +491,8 @@ Date: Thu, 26 Dec 2019 08:17:49 GMT
{"node":{"value":{"username":"jack","plugins":{"key-auth":{"key":"auth-one"},"limit-count":{"time_window":60,"count":2,"rejected_code":503,"key":"remote_addr","policy":"local"}}},"createdIndex":64,"key":"\/apisix\/consumers\/jack","modifiedIndex":64},"prevNode":{"value":"{\"username\":\"jack\",\"plugins\":{\"key-auth\":{\"key\":\"auth-one\"},\"limit-count\":{\"time_window\":60,\"count\":2,\"rejected_code\":503,\"key\":\"remote_addr\",\"policy\":\"local\"}}}","createdIndex":63,"key":"\/ap [...]
```
+从 `v2.2` 版本之后,同一个 consumer 可以绑定多个认证插件。
+
> 应答参数
目前是直接返回与 etcd 交互后的结果。
diff --git a/t/config-center-yaml/stream-route.t b/t/config-center-yaml/stream-route.t
index 2046797..77d2dd9 100644
--- a/t/config-center-yaml/stream-route.t
+++ b/t/config-center-yaml/stream-route.t
@@ -48,7 +48,6 @@ run_tests();
__DATA__
-
=== TEST 1: sanity
--- apisix_yaml
stream_routes:
diff --git a/t/node/consumer-plugin.t b/t/node/consumer-plugin.t
index 2748b01..2764080 100644
--- a/t/node/consumer-plugin.t
+++ b/t/node/consumer-plugin.t
@@ -151,47 +151,7 @@ apikey: auth-one
-=== TEST 6: two auth plugins (not allow)
---- 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": {
- "limit-count": {
- "count": 2,
- "time_window": 60,
- "rejected_code": 503,
- "key": "remote_addr"
- },
- "key-auth": {
- "key": "auth-one"
- },
- "jwt-auth": {
- "key": "auth-one"
- }
- }
- }]]
- )
-
- ngx.status = code
- ngx.print(body)
- }
- }
---- request
-GET /t
---- error_code: 400
---- response_body
-{"error_msg":"only one auth plugin is allowed"}
---- no_error_log
-[error]
-
-
-
-=== TEST 7: missing auth plugins (not allow)
+=== TEST 6: missing auth plugins (not allow)
--- config
location /t {
content_by_lua_block {
@@ -225,7 +185,7 @@ GET /t
-=== TEST 8: use the new configuration after the consumer's configuration is updated
+=== TEST 7: use the new configuration after the consumer's configuration is updated
--- config
location /t {
content_by_lua_block {
@@ -289,3 +249,195 @@ GET /t
{"200":4,"503":1}
--- no_error_log
[error]
+
+
+
+=== TEST 8: consumer with multiple auth plugins
+--- 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": "John_Doe",
+ "desc": "new consumer",
+ "plugins": {
+ "key-auth": {
+ "key": "consumer-plugin-John_Doe"
+ },
+ "hmac-auth": {
+ "access_key": "my-access-key",
+ "secret_key": "my-secret-key",
+ "clock_skew": 1
+ }
+ }
+ }]],
+ [[{
+ "node": {
+ "value": {
+ "username": "John_Doe",
+ "desc": "new consumer",
+ "plugins": {
+ "key-auth": {
+ "key": "consumer-plugin-John_Doe"
+ },
+ "hmac-auth": {
+ "access_key": "my-access-key",
+ "secret_key": "my-secret-key",
+ "clock_skew": 1
+ }
+ }
+ }
+ },
+ "action": "set"
+ }]]
+ )
+
+ ngx.status = code
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 9: bind to routes
+--- 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": {
+ "key-auth": {}
+ },
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:1980": 1
+ },
+ "type": "roundrobin"
+ },
+ "uri": "/hello"
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.log(ngx.ERR, "failed to bind route 1")
+ ngx.status = code
+ ngx.say(body)
+ return
+ end
+
+ local code, body = t('/apisix/admin/routes/2',
+ ngx.HTTP_PUT,
+ [[{
+ "plugins": {
+ "hmac-auth": {}
+ },
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:1980": 1
+ },
+ "type": "roundrobin"
+ },
+ "uri": "/status"
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 10: hit consumer, key-auth
+--- request
+GET /hello
+--- more_headers
+apikey: consumer-plugin-John_Doe
+--- response_body
+hello world
+--- error_log
+find consumer John_Doe
+--- no_error_log
+[error]
+
+
+
+=== TEST 11: hit consumer, hmac-auth
+--- config
+location /t {
+ content_by_lua_block {
+ local ngx_time = ngx.time
+ local ngx_http_time = ngx.http_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 gmt = ngx_http_time(timestamp)
+ local access_key = "my-access-key"
+ local custom_header_a = "asld$%dfasf"
+ local custom_header_b = "23879fmsldfk"
+
+ local signing_string = {
+ "GET",
+ "/status",
+ "",
+ access_key,
+ gmt,
+ "x-custom-header-a:" .. custom_header_a,
+ "x-custom-header-b:" .. custom_header_b
+ }
+ signing_string = core.table.concat(signing_string, "\n") .. "\n"
+ core.log.info("signing_string:", signing_string)
+
+ 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["Date"] = gmt
+ 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('/status',
+ ngx.HTTP_GET,
+ nil,
+ nil,
+ headers
+ )
+
+ ngx.status = code
+ ngx.say(body)
+ }
+}
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+--- error_log
+find consumer John_Doe