Skip to content

Commit

Permalink
tenant verify and validate plugins (#93)
Browse files Browse the repository at this point in the history
* feat(bk-tenant-*.lua): add bk-tenant-verify and bk-tenant-validate plugins

* feat(bk-components/bkauth.lua): add get app tenant info from bkauth

* feat(bk-components): add bkauth and bkuser, get tenant info of app/user

* test(bk-tenant-*.lua): add unittests

* feat(workflows/apisix.yml): enable for ft_tenant branch

* fix(ci/dockerfile.apisix-test-nginx): image build failed, the lua lib lualdap archived

* refactor(bk-components): refactor all api calls, and add unittest

* fix(lint): fix lints

* fix(review): fix comments
  • Loading branch information
wklken authored Dec 18, 2024
1 parent 50779ad commit 81dd05b
Show file tree
Hide file tree
Showing 28 changed files with 2,098 additions and 438 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/apisix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,22 @@ name: apisix ci

on:
push:
branches: [ master, release/* ]
branches: [ master, release/*, ft_tenant ]
paths: ['src/apisix/**']
pull_request:
branches: [ master, release/* ]
branches: [ master, release/*, ft_tenant ]
paths: ['src/apisix/**']

jobs:

build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: '3.7.15'
python-version: '3.11.10'
cache: 'pip'
cache-dependency-path: 'src/apisix/requirements.txt'
- name: Install dependencies
Expand Down
2 changes: 2 additions & 0 deletions src/apisix/ci/Dockerfile.apisix-test-nginx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ RUN wget https://github.com/apache/apisix/archive/refs/tags/${APISIX_VERSION}.ta
ARG CODE_DIR=/codes/apisix-${APISIX_VERSION}
RUN sed -i 's#yum install -y openresty openresty-debug openresty-openssl111-debug-devel pcre pcre-devel#yum install -y openresty openresty-debug-1.25.3.2-1.el7.x86_64 openresty-openssl111-debug-devel pcre pcre-devel --skip-broken#g' ${CODE_DIR}/ci/centos7-ci.sh
RUN sed -i 's|https://registry.npm.taobao.org|https://registry.npmmirror.com|g' ${CODE_DIR}/t/plugin/grpc-web/package-lock.json
# fix archived libs in luarocks
RUN sed -i 's|lualdap = 1.2.6-1|lualdap = 1.4.0-1|g' ${CODE_DIR}/rockspec/apisix-master-0.rockspec
RUN cd ${CODE_DIR} && bash ./ci/centos7-ci.sh install_dependencies
RUN cp -r ${CODE_DIR}/t /usr/local/apisix/

Expand Down
8 changes: 0 additions & 8 deletions src/apisix/editions/ee/plugins/bk-cache/access-token.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
--
local core = require("apisix.core")
local access_token_define = require("apisix.plugins.bk-define.access-token")
-- local bkauth_component = require("apisix.plugins.bk-components.bkauth")
local ssm_component = require("apisix.plugins.bk-components.ssm")
local lru_new = require("resty.lrucache").new

Expand All @@ -41,13 +40,6 @@ local _M = {}
local function get_access_token(access_token)
local err

-- local bkauth_token, err = bkauth_component.verify_access_token(access_token)
-- if bkauth_token ~= nil then
-- return {
-- token = access_token_define.new(bkauth_token.bk_app_code, bkauth_token.username, bkauth_token.expires_in)
-- }
-- end

if ssm_component.is_configured() then
local ssm_token
ssm_token, err = ssm_component.verify_access_token(access_token)
Expand Down
4 changes: 4 additions & 0 deletions src/apisix/editions/ee/plugins/bk-cache/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,15 @@ local access_token_cache = require("apisix.plugins.bk-cache.access-token")
local app_account_cache = require("apisix.plugins.bk-cache.app-account")
local jwt_key_cache = require("apisix.plugins.bk-cache.jwt-key")
local bk_token_cache = require("apisix.plugins.bk-cache.bk-token")
local bk_app_tenant_cache = require("apisix.plugins.bk-cache.app-tenant-info")
local bk_user_tenant_cache = require("apisix.plugins.bk-cache.user-tenant-info")

return {
get_access_token = access_token_cache.get_access_token,
verify_app_secret = app_account_cache.verify_app_secret,
list_app_secrets = app_account_cache.list_app_secrets,
get_jwt_public_key = jwt_key_cache.get_jwt_public_key,
get_username_by_bk_token = bk_token_cache.get_username_by_bk_token,
get_user_tenant_info = bk_user_tenant_cache.get_user_tenant_info,
get_app_tenant_info = bk_app_tenant_cache.get_app_tenant_info,
}
87 changes: 43 additions & 44 deletions src/apisix/editions/ee/plugins/bk-components/bklogin.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,34 +15,63 @@
-- We undertake not to change the open source license (MIT license) applicable
-- to the current version of the project delivered to anyone in the future.
--
local uuid = require("resty.jit-uuid")
local pl_types = require("pl.types")
local http = require("resty.http")
local core = require("apisix.core")

local bk_core = require("apisix.plugins.bk-core.init")
local bk_components_utils = require("apisix.plugins.bk-components.utils")

local string_format = string.format

local IS_LOGIN_URL = "/login/api/v2/is_login/"
local VERIFY_BK_TOKEN_URL = "/api/v3/apigw/bk-tokens/verify/"

local BKLOGIN_TIMEOUT_MS = 5 * 1000

local _M = {
host = bk_core.config.get_login_addr(),
}

function _M.get_username_by_bk_token(bk_token)
if pl_types.is_empty(_M.host) then
local function bklogin_do_request(host, path, params, request_id)
if pl_types.is_empty(host) then
return nil, "server error: login host is not configured."
end

local url = bk_core.url.url_single_joining_slash(_M.host, IS_LOGIN_URL)
local url = bk_core.url.url_single_joining_slash(host, path)
local res, err = bk_components_utils.handle_request(url, params, BKLOGIN_TIMEOUT_MS, true)
if err ~= nil then
-- if connection refused, return directly, without wrap(for the fallback cache upon layer)
if err == "connection refused" then
core.log.error("failed to request third-party api, url: %s, err: %s, response: nil", url, err)
return nil, err
end

local new_err = string_format(
"failed to request third-party api, url: %s, request_id: %s, err: %s",
url, request_id, err
)
core.log.error(new_err)
return nil, new_err
end

local result
result, err = bk_components_utils.parse_response_json(res.body)
if err ~= nil then
local new_err = string_format(
"failed to request third-party api, %s, request_id: %s, status: %s, response: %s, err: %s",
url, request_id, res.status, res.body, err
)
core.log.error(new_err)
return nil, new_err
end

return result, nil
end

local http_client = http.new()
http_client:set_timeout(BKLOGIN_TIMEOUT_MS)
local res, err = http_client:request_uri(
url, {
function _M.get_username_by_bk_token(bk_token)
local request_id = uuid.generate_v4()
local path = VERIFY_BK_TOKEN_URL
local params = {
method = "GET",
query = core.string.encode_args(
{
Expand All @@ -53,47 +82,17 @@ function _M.get_username_by_bk_token(bk_token)
headers = {
["Content-Type"] = "application/x-www-form-urlencoded",
},
}
)

-- retry if some connection error, while the bklogin in bk-user 2.x
if err == "closed" or err == "connection reset by peer" then
res, err = http_client:request_uri(
url, {
method = "GET",
query = core.string.encode_args(
{
bk_token = bk_token,
}
),
ssl_verify = false,
headers = {
["Content-Type"] = "application/x-www-form-urlencoded",
},
}
)
end
}

-- if the ssm is down, return the raw error
if err == "connection refused" then
core.log.error("failed to request url: %s, err: %s, response: nil", url, err)
local result, err = bklogin_do_request(_M.host, path, params, request_id)
if err ~= nil then
return nil, err
end

local result, _err = bk_components_utils.parse_response(res, err, true)
if result == nil then
core.log.error(
string_format(
"failed to request %s, err: %s, status: %s, response: %s", url, _err, res and res.status,
res and res.body
)
)
return nil, string_format("failed to request third-party api, url: %s, err: %s", url, _err)
end

if result.bk_error_code ~= 0 then
return {
error_message = string_format("bk_token is invalid, url: %s, code: %s", url, result.bk_error_code),
error_message = string_format("bk_token is invalid,host: %s, path: %s, code: %s",
_M.host, path, result.bk_error_code),
}
end

Expand Down
91 changes: 55 additions & 36 deletions src/apisix/editions/ee/plugins/bk-components/ssm.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
-- to the current version of the project delivered to anyone in the future.
--
local pl_types = require("pl.types")
local http = require("resty.http")
local uuid = require("resty.jit-uuid")
local core = require("apisix.core")

local bk_core = require("apisix.plugins.bk-core.init")
Expand All @@ -39,51 +39,70 @@ function _M.is_configured()
return not pl_types.is_empty(_M.host)
end

function _M.verify_access_token(access_token)
if pl_types.is_empty(_M.host) then
local function ssm_do_request(host, path, params, request_id)
if pl_types.is_empty(host) then
return nil, "server error: ssm host is not configured."
end

local url = bk_core.url.url_single_joining_slash(_M.host, VERIFY_ACCESS_TOKEN_URL)

local http_client = http.new()
http_client:set_timeout(SSM_TIMEOUT_MS)
local res, err = http_client:request_uri(
url, {
method = "POST",
body = core.json.encode(
{
access_token = access_token,
}
),
ssl_verify = false,
headers = {
["X-Bk-App-Code"] = _M.app_code,
["X-Bk-App-Secret"] = _M.app_secret,
["Content-Type"] = "application/json",
},
}
)
local url = bk_core.url.url_single_joining_slash(host, path)
local res, err = bk_components_utils.handle_request(url, params, SSM_TIMEOUT_MS, true)
if err ~= nil then
-- if connection refused, return directly, without wrap(for the fallback cache upon layer)
if err == "connection refused" then
core.log.error("failed to request third-party api, url: %s, err: %s, response: nil", url, err)
return nil, err
end

-- if the ssm is down, return the raw error
if err == "connection refused" then
core.log.error("failed to request url: %s, err: %s, response: nil", url, err)
return nil, err
local new_err = string_format(
"failed to request third-party api, url: %s, request_id: %s, err: %s",
url, request_id, err
)
core.log.error(new_err)
return nil, new_err
end

local result, _err = bk_components_utils.parse_response(res, err, true)
if result == nil then
core.log.error(
string_format(
"failed to request %s, err: %s, status: %s, response: %s", url, _err, res and res.status,
res and res.body
)
local result
result, err = bk_components_utils.parse_response_json(res.body)
if err ~= nil then
local new_err = string_format(
"failed to request third-party api, url: %s, request_id: %s, status: %s, response: %s, err: %s",
url, request_id, res.status, res.body, err
)
return nil, string_format("failed to request third-party api, url: %s, err: %s", url, _err)
core.log.error(new_err)
return nil, new_err
end

if result.code ~= 0 then
return nil, string_format("ssm error message: %s, url: %s, code: %s", result.message, url, result.code)
local new_err = string_format(
"failed to request third-party api, url: %s, request_id: %s, result.code!=0, status: %s, response: %s",
url, request_id, res.status, res.body
)
core.log.error(new_err)
return nil, new_err
end

return result, nil
end

function _M.verify_access_token(access_token)
local request_id = uuid.generate_v4()
local path = VERIFY_ACCESS_TOKEN_URL
local params = {
method = "POST",
body = core.json.encode({
access_token = access_token,
}),
ssl_verify = false,
headers = {
["X-Bk-App-Code"] = _M.app_code,
["X-Bk-App-Secret"] = _M.app_secret,
["X-Request-Id"] = request_id,
["Content-Type"] = "application/json",
},
}
local result, err = ssm_do_request(_M.host, path, params, request_id)
if err ~= nil then
return nil, err
end

return {
Expand Down
35 changes: 4 additions & 31 deletions src/apisix/editions/ee/tests/bk-components/test-bklogin.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
-- to the current version of the project delivered to anyone in the future.
--
local core = require("apisix.core")
local http = require("resty.http")
local bklogin = require("apisix.plugins.bk-components.bklogin")
local bk_components_utils = require("apisix.plugins.bk-components.utils")

describe(
"bklogin", function()
Expand All @@ -30,22 +30,16 @@ describe(
response_err = nil

stub(
http, "new", function()
return {
set_timeout = function(self, timeout)
end,
request_uri = function(self, url, params)
return response, response_err
end,
}
bk_components_utils, "handle_request", function()
return response, response_err
end
)
end
)

after_each(
function()
http.new:revert()
bk_components_utils.handle_request:revert()
end
)

Expand Down Expand Up @@ -73,27 +67,6 @@ describe(
end
)

it(
"bk_error_code is not 0", function()
response = {
status = 200,
body = core.json.encode(
{
bk_error_code = 1,
bk_error_msg = "error",
data = {},
}
),
}
response_err = nil

local result, err = bklogin.get_username_by_bk_token("fake-bk-token")
assert.is_nil(result.username)
assert.is_true(core.string.has_prefix(result.error_message, "bk_token is invalid"))
assert.is_nil(err)
end
)

it(
"success", function()
response = {
Expand Down
Loading

0 comments on commit 81dd05b

Please sign in to comment.