# # 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_root_location(); add_block_preprocessor(sub { my ($block) = @_; if (!defined $block->request) { $block->set_value("request", "GET /t"); } my $http_config = $block->http_config // <<_EOC_; server { listen 10420; location /api/login/oauth/access_token { content_by_lua_block { local json_encode = require("toolkit.json").encode ngx.req.read_body() local arg = ngx.req.get_post_args()["code"] local core = require("apisix.core") local log = core.log if arg == "wrong" then ngx.status = 200 ngx.say(json_encode({ access_token = "bbbbbbbbbb", expires_in = 0 })) return end ngx.status = 200 ngx.say(json_encode({ access_token = "aaaaaaaaaaaaaaaa", expires_in = 1000000 })) } } } _EOC_ $block->set_value("http_config", $http_config); }); run_tests(); __DATA__ === TEST 1: sanity --- config location /t { content_by_lua_block { local plugin = require("apisix.plugins.authz-casdoor") local fake_uri = "http://127.0.0.1:" .. ngx.var.server_port local callback_url = "http://127.0.0.1:" .. ngx.var.server_port .. "/anything/callback" local conf = { callback_url = callback_url, endpoint_addr = fake_uri, client_id = "7ceb9b7fda4a9061ec1c", client_secret = "3416238e1edf915eac08b8fe345b2b95cdba7e04" } local ok, err = plugin.check_schema(conf) if not ok then ngx.say(err) end local conf2 = { callback_url = callback_url .. "/?code=aaa", endpoint_addr = fake_uri, client_id = "7ceb9b7fda4a9061ec1c", client_secret = "3416238e1edf915eac08b8fe345b2b95cdba7e04" } ok, err = plugin.check_schema(conf2) if ok then ngx.say("err: shouldn't have passed sanity check") end local conf3 = { callback_url = callback_url, endpoint_addr = fake_uri .. "/", client_id = "7ceb9b7fda4a9061ec1c", client_secret = "3416238e1edf915eac08b8fe345b2b95cdba7e04" } ok, err = plugin.check_schema(conf3) if ok then ngx.say("err: shouldn't have passed sanity check") end ngx.say("done") } } --- response_body done === TEST 2: enable plugin test redirect --- config location /t { content_by_lua_block { local plugin = require("apisix.plugins.authz-casdoor") local t = require("lib.test_admin").test local fake_uri = "http://127.0.0.1:10420" local callback_url = "http://127.0.0.1:" .. ngx.var.server_port .. "/anything/callback" local code, body = t('/apisix/admin/routes/1', ngx.HTTP_PUT, [[{ "methods": ["GET"], "uri": "/anything/*", "plugins": { "authz-casdoor": { "callback_url":"]] .. callback_url .. [[", "endpoint_addr":"]] .. fake_uri .. [[", "client_id":"7ceb9b7fda4a9061ec1c", "client_secret":"3416238e1edf915eac08b8fe345b2b95cdba7e04" }, "proxy-rewrite": { "uri": "/echo" } }, "upstream": { "type": "roundrobin", "nodes": { "test.com:1980": 1 } } }]] ) if code >= 300 then ngx.say("failed to set up routing rule") end ngx.say("done") } } --- response_body done === TEST 3: test redirect --- config location /t { content_by_lua_block { local plugin = require("apisix.plugins.authz-casdoor") local t = require("lib.test_admin").test local code, body = t('/anything/d?param1=foo¶m2=bar', ngx.HTTP_GET, [[]]) if code ~= 302 then ngx.say("should have redirected") end ngx.say("done") } } --- response_body done === TEST 4: enable fake casdoor --- config location /t { content_by_lua_block { local t = require("lib.test_admin").test local code, body = t('/apisix/admin/routes/2', ngx.HTTP_PUT, [[{ "uri": "/api/login/oauth/access_token", "upstream": { "nodes": { "127.0.0.1:1980": 1 }, "type": "roundrobin" } }]] ) if code >= 300 then ngx.status = code end ngx.say(body) } } --- response_body passed === TEST 5: test fake casdoor --- config location /t { content_by_lua_block { local plugin = require("apisix.plugins.authz-casdoor") local t = require("lib.test_admin").test local httpc = require("resty.http").new() local cjson = require("cjson") local fake_uri = "http://127.0.0.1:10420/api/login/oauth/access_token" local res, err = httpc:request_uri(fake_uri, {method = "GET"}) if not res then ngx.say(err) end local data = cjson.decode(res.body) if not data then ngx.say("invalid res.body") end if not data.access_token == "aaaaaaaaaaaaaaaa" then ngx.say("invalid token") end ngx.say("done") } } --- response_body done === TEST 6: test code handling --- config location /t { content_by_lua_block { local plugin = require("apisix.plugins.authz-casdoor") local core = require("apisix.core") local log = core.log local t = require("lib.test_admin").test local cjson = require("cjson") local fake_uri = "http://127.0.0.1:" .. ngx.var.server_port .. "/anything/d?param1=foo¶m2=bar" local callback_url = "http://127.0.0.1:" .. ngx.var.server_port .. "/anything/callback?code=aaa&state=" local httpc = require("resty.http").new() local res1, err1 = httpc:request_uri(fake_uri, {method = "GET"}) if not res1 then ngx.say(err1) end local cookie = res1.headers["Set-Cookie"] local re_url = res1.headers["Location"] local m, err = ngx.re.match(re_url, "state=([0-9]*)") if err or not m then log.error(err) ngx.exit() end local state = m[1] local res2, err2 = httpc:request_uri(callback_url..state, { method = "GET", headers = {Cookie = cookie} }) if not res2 then ngx.say(err2) end if res2.status ~= 302 then log.error(res2.status) end local cookie2 = res2.headers["Set-Cookie"] local res3, err3 = httpc:request_uri(fake_uri, { method = "GET", headers = {Cookie = cookie2} }) if not res3 then ngx.say(err3) end if res3.status >= 300 then log.error(res3.status,res3.headers["Location"]) end ngx.say("done") } } --- response_body done === TEST 7: incorrect test code handling --- config location /t { content_by_lua_block { local plugin = require("apisix.plugins.authz-casdoor") local t = require("lib.test_admin").test local cjson = require("cjson") local callback_url = "http://127.0.0.1:" .. ngx.var.server_port .. "/anything/callback?code=aaa&state=bbb" local httpc = require("resty.http").new() local res1, err1 = httpc:request_uri(callback_url, {method = "GET"}) if res1.status ~= 503 then ngx.say(res1.status) end ngx.say("done") } } --- response_body done --- error_log no session found === TEST 8: incorrect state handling --- config location /t { content_by_lua_block { local plugin = require("apisix.plugins.authz-casdoor") local core = require("apisix.core") local log = core.log local t = require("lib.test_admin").test local cjson = require("cjson") local fake_uri = "http://127.0.0.1:" .. ngx.var.server_port .. "/anything/d?param1=foo¶m2=bar" local callback_url = "http://127.0.0.1:" .. ngx.var.server_port .. "/anything/callback?code=aaa&state=" local httpc = require("resty.http").new() local res1, err1 = httpc:request_uri(fake_uri, {method = "GET"}) if not res1 then ngx.say(err1) end local cookie = res1.headers["Set-Cookie"] local re_url = res1.headers["Location"] local m, err = ngx.re.match(re_url, "state=([0-9]*)") if err or not m then log.error(err) end local state = m[1]+10 local res2, err2 = httpc:request_uri(callback_url..state, { method = "GET", headers = {Cookie = cookie} }) if not res2 then ngx.say(err2) end if res2.status ~= 302 then log.error(res2.status) end local cookie2 = res2.headers["Set-Cookie"] local res3, err3 = httpc:request_uri(fake_uri, { method = "GET", headers = {Cookie = cookie2} }) if not res3 then ngx.say(err3) end if res3.status ~= 503 then log.error(res3.status) end ngx.say("done") } } --- response_body done --- error_log invalid state === TEST 9: test incorrect access_token --- config location /t { content_by_lua_block { local plugin = require("apisix.plugins.authz-casdoor") local core = require("apisix.core") local log = core.log local t = require("lib.test_admin").test local cjson = require("cjson") local fake_uri = "http://127.0.0.1:" .. ngx.var.server_port .. "/anything/d?param1=foo¶m2=bar" local callback_url = "http://127.0.0.1:" .. ngx.var.server_port .. "/anything/callback?code=wrong&state=" local httpc = require("resty.http").new() local res1, err1 = httpc:request_uri(fake_uri, {method = "GET"}) if not res1 then ngx.say(err1) end local cookie = res1.headers["Set-Cookie"] local re_url = res1.headers["Location"] local m, err = ngx.re.match(re_url, "state=([0-9]*)") if err or not m then log.error(err) ngx.exit() end local state = m[1] local res2, err2 = httpc:request_uri(callback_url..state, { method = "GET", headers = {Cookie = cookie} }) if not res2 then ngx.say(err2) end if res2.status ~= 302 then log.error(res2.status) end local cookie2 = res2.headers["Set-Cookie"] local res3, err3 = httpc:request_uri(fake_uri, { method = "GET", headers = {Cookie = cookie2} }) if not res3 then ngx.say(err3) end if res3.status ~= 503 then log.error(res3.status) end ngx.say("done") } } --- response_body done --- error_log failed when accessing token: invalid access_token === TEST 10: data encryption for client_secret --- yaml_config apisix: data_encryption: enable_encrypt_fields: true keyring: - edd1c9f0985e76a2 --- config location /t { content_by_lua_block { local json = require("toolkit.json") local t = require("lib.test_admin").test local callback_url = "http://127.0.0.1:" .. ngx.var.server_port .. "/anything/callback" local code, body = t('/apisix/admin/routes/1', ngx.HTTP_PUT, [[{ "methods": ["GET"], "uri": "/anything/*", "plugins": { "authz-casdoor": { "callback_url":"]] .. callback_url .. [[", "endpoint_addr": "http://127.0.0.1:10420", "client_id":"7ceb9b7fda4a9061ec1c", "client_secret":"3416238e1edf915eac08b8fe345b2b95cdba7e04" }, "proxy-rewrite": { "uri": "/echo" } }, "upstream": { "type": "roundrobin", "nodes": { "test.com:1980": 1 } } }]] ) if code >= 300 then ngx.status = code ngx.say(body) return end ngx.sleep(0.1) -- get plugin conf from admin api, password is decrypted local code, message, res = t('/apisix/admin/routes/1', ngx.HTTP_GET ) res = json.decode(res) if code >= 300 then ngx.status = code ngx.say(message) return end ngx.say(res.value.plugins["authz-casdoor"].client_secret) -- get plugin conf from etcd, password is encrypted local etcd = require("apisix.core.etcd") local res = assert(etcd.get('/routes/1')) ngx.say(res.body.node.value.plugins["authz-casdoor"].client_secret) } } --- response_body 3416238e1edf915eac08b8fe345b2b95cdba7e04 YUfqAO0kPXjZIoAbPSuryCkUDksEmwSq08UDTIUWolN6KQwEUrh72TazePueo4/S