Skip to content

Commit

Permalink
feat(auth): add downstream IP auth method (#64)
Browse files Browse the repository at this point in the history
  • Loading branch information
flrgh committed Jul 3, 2023
1 parent 8f58e8f commit 55234bd
Show file tree
Hide file tree
Showing 20 changed files with 527 additions and 246 deletions.
1 change: 1 addition & 0 deletions .luacheckrc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ globals = {
"_TEST",
"ngx.config.is_console",
"ngx.run_worker_thread",
"table.unpack",
}

not_globals = {
Expand Down
1 change: 1 addition & 0 deletions doorbell-dev-1.rockspec
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ build = {
["doorbell.api.access"] = "lib/doorbell/api/access.lua",
["doorbell.api.schema"] = "lib/doorbell/api/schema.lua",
["doorbell.api.nginx"] = "lib/doorbell/api/nginx.lua",
["doorbell.api.auth-test"] = "lib/doorbell/api/auth-test.lua",

["doorbell.cache"] = "lib/doorbell/cache.lua",
["doorbell.cache.shared"] = "lib/doorbell/cache/shared.lua",
Expand Down
6 changes: 1 addition & 5 deletions lib/doorbell.lua
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,14 @@ local SHM = require("doorbell.shm").doorbell
local GLOBAL_REWRITE_MWARE = middleware.compile({
request.middleware.pre_handler,
router.on_match,
http.CORS.middleware,
})

local GLOBAL_AUTH_MWARE = middleware.compile({
auth.middleware,
})


local GLOBAL_PRE_HANDLER_MWARE = middleware.compile({
http.CORS.middleware,
})

-- keeping these in a single table ensures that we run init() and init_worker()
-- functions in a consistent order
local submodules = {
Expand Down Expand Up @@ -158,7 +155,6 @@ function _M.content()
handler = cors_preflight
end

GLOBAL_PRE_HANDLER_MWARE(ctx, route, match)
exec_route_middleware(PRE_HANDLER, ctx, route, match)

if not handler then
Expand Down
117 changes: 117 additions & 0 deletions lib/doorbell/api/auth-test.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
local routes = {}

local http = require "doorbell.http"
local mw = require "doorbell.middleware"
local request = require "doorbell.request"
local auth = require "doorbell.auth"
local util = require "doorbell.util"

local split = require("pl.stringx").split

local send = http.send

local MWARE = {
[mw.phase.REWRITE] = {
request.middleware.enable_logging,
},
}

local function parse_strategies(strategies)
local list = split(strategies, "+")
local strats = {}

for _, item in ipairs(list) do
if item == "proxy-ip" then
table.insert(strats, auth.TRUSTED_PROXY_IP)

elseif item == "downstream-ip" then
table.insert(strats, auth.TRUSTED_DOWNSTREAM_IP)

elseif item == "openid" then
table.insert(strats, auth.OPENID)

elseif item == "api-key" then
table.insert(strats, auth.API_KEY)

else
error("oops")
end
end

return strats, list
end

local function auth_test(ctx, match, all)
local strats, list = parse_strategies(match.strategies)

local handler = all and auth.require_all(util.unpack(strats))
or auth.require_any(util.unpack(strats))

local passed = handler(ctx)
local status = passed and 200 or ctx.auth_http_status
send(status, {
passed = passed,
tried = list,
error = ctx.auth_client_message,
jwt = ctx.jwt,
user = ctx.user,
trusted_proxy = not not ctx.is_trusted_proxy,
trusted_downstream = not not ctx.is_trusted_downstream,
})
end

local function auth_test_none(ctx)
send(200, {
passed = auth.require_none()(ctx),
jwt = ctx.jwt,
user = ctx.user,
trusted_proxy = not not ctx.is_trusted_proxy,
trusted_downstream = not not ctx.is_trusted_downstream,
})
end

routes["/auth-test/none"] = {
id = "auth-test-none",
description = "test authentication (none required)",
metrics_enabled = false,
content_type = "application/json",
auth_strategy = auth.require_none(),
middleware = MWARE,
---@param ctx doorbell.ctx
GET = function(ctx)
return auth_test_none(ctx)
end,

---@param ctx doorbell.ctx
OPTIONS = function(ctx)
return auth_test_none(ctx)
end,
}

routes["~^/auth-test/any/(?<strategies>.+)"] = {
id = "auth-test-any",
description = "test authentication (any required)",
metrics_enabled = false,
content_type = "application/json",
auth_strategy = auth.require_none(),
middleware = MWARE,
---@param ctx doorbell.ctx
GET = function(ctx, match)
return auth_test(ctx, match, false)
end,
}

routes["~^/auth-test/all/(?<strategies>.+)"] = {
id = "auth-test-all",
description = "test authentication (all required)",
metrics_enabled = false,
content_type = "application/json",
auth_strategy = auth.require_none(),
middleware = MWARE,
---@param ctx doorbell.ctx
GET = function(ctx, match)
return auth_test(ctx, match, true)
end,
}

return routes
Loading

0 comments on commit 55234bd

Please sign in to comment.