Skip to content

Commit

Permalink
Add multi-auth plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
Madhawa Gunasekara authored and Madhawa Gunasekara committed Nov 12, 2023
1 parent 105993f commit 9a3bd0d
Show file tree
Hide file tree
Showing 5 changed files with 337 additions and 0 deletions.
90 changes: 90 additions & 0 deletions apisix/plugins/multi-auth.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
--
-- 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 schema = {
type = "object",
title = "work with route or service object",
properties = {
auth_plugins = { type = "array", minItems = 2 },
hide_credentials = {
type = "boolean",
default = false,
}
},
required = { "auth_plugins" },
}


local plugin_name = "multi-auth"

local _M = {
version = 0.1,
priority = 2600,
type = 'auth',
name = plugin_name,
schema = schema
}

function _M.check_schema(conf)
core.log.info("multi-auth plugin access phase, conf: ", core.json.delay_encode(conf))
local ok, err = core.schema.check(schema, conf)
if not ok then
return false, err
end

local auth_plugins = conf.auth_plugins
for k, auth_plugin in pairs(auth_plugins) do
for key, value in pairs(auth_plugin) do
local auth = require("apisix.plugins." .. key)
if auth == nil then
return false, key .. " plugin did not found"
else
if auth.type ~= 'auth' then
return false, key .. " plugin is not supported"
end
end
end
end

return true
end

function _M.rewrite(conf, ctx)
local auth_plugins = conf.auth_plugins
local status_code
for k, auth_plugin in pairs(auth_plugins) do
for key, value in pairs(auth_plugin) do
local auth = require("apisix.plugins." .. key)
local auth_code, b = auth.rewrite(value, ctx)
status_code = auth_code
if auth_code == nil then
core.log.debug("Authentication is successful" .. key .. " plugin")
goto authenticated
else
core.log.warn("Authentication is failed" .. key .. " plugin, code: " .. auth_code)
end
end
end

:: authenticated ::
if status_code ~= nil then
return 401, { message = "Authorization Failed" }
end
end

return _M
1 change: 1 addition & 0 deletions conf/config-default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,7 @@ plugins: # plugin list (sorted by priority)
- uri-blocker # priority: 2900
- request-validation # priority: 2800
- chaitin-waf # priority: 2700
- multi-auth # priority: 2600
- openid-connect # priority: 2599
- cas-auth # priority: 2597
- authz-casbin # priority: 2560
Expand Down
1 change: 1 addition & 0 deletions t/admin/plugins.t
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ csrf
uri-blocker
request-validation
chaitin-waf
multi-auth
openid-connect
cas-auth
authz-casbin
Expand Down
1 change: 1 addition & 0 deletions t/debug/debug-mode.t
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ loaded plugin and sort by priority: 3000 name: ip-restriction
loaded plugin and sort by priority: 2990 name: referer-restriction
loaded plugin and sort by priority: 2900 name: uri-blocker
loaded plugin and sort by priority: 2800 name: request-validation
loaded plugin and sort by priority: 2600 name: multi-auth
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: 2530 name: hmac-auth
Expand Down
244 changes: 244 additions & 0 deletions t/plugin/multi-auth.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
#
# 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.
#
BEGIN {
$ENV{VAULT_TOKEN} = "root";
}

use t::APISIX 'no_plan';

repeat_each(2);
no_long_string();
no_root_location();
no_shuffle();
run_tests;

__DATA__

=== TEST 1: add consumer with basic-auth and key-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": "foo",
"plugins": {
"basic-auth": {
"username": "foo",
"password": "bar"
},
"key-auth": {
"key": "auth-one"
}
}
}]]
)
if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- request
GET /t
--- response_body
passed



=== TEST 2: enable multi auth plugin using admin api
--- 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": {
"multi-auth": {
"auth_plugins": [
{
"basic-auth": {}
},
{
"key-auth": {
"query": "apikey",
"hide_credentials": true,
"header": "apikey"
}
},
{
"jwt-auth": {
"cookie": "jwt",
"query": "jwt",
"hide_credentials": true,
"header": "authorization"
}
}
]
}
},
"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



=== TEST 3: verify, missing authorization
--- request
GET /hello
--- error_code: 401
--- response_body
{"message":"Authorization Failed"}



=== TEST 4: verify basic
--- request
GET /hello
--- more_headers
Authorization: Basic Zm9vOmJhcg==
--- response_body
hello world
--- error_log
find consumer foo



=== TEST 5: verify key
--- request
GET /hello
--- more_headers
apikey: auth-one
--- response_body
hello world



=== TEST 6: verify, invalid basic credentials
--- request
GET /hello
--- more_headers
Authorization: Basic YmFyOmJhcgo=
--- error_code: 401
--- response_body
{"message":"Authorization Failed."}



=== TEST 7: verify, invalid api key
--- request
GET /hello
--- more_headers
apikey: auth-two
--- error_code: 401
--- response_body
{"message":"Authorization Failed."}



=== TEST 8: enable multi auth plugin using admin api
--- 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": {
"multi-auth": { }
},
"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
--- error_code: 400
--- response_body
{"error_msg":"invalid plugins configuration: failed to check the configuration of plugin multi-auth err: property \"auth_plugins\" is required"}



=== TEST 9: enable multi auth plugin using admin api
--- 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": {
"multi-auth": {
"auth_plugins": [
{
"basic-auth": {}
}
]
}
},
"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
--- error_code: 400
--- response_body
{"error_msg":"invalid plugins configuration: failed to check the configuration of plugin multi-auth err: property \"auth_plugins\" validation failed: expect array to have at least 2 items"}

0 comments on commit 9a3bd0d

Please sign in to comment.