summaryrefslogtreecommitdiff
path: root/internal/suites/example/compose/haproxy/auth-request.lua
diff options
context:
space:
mode:
authorClément Michaud <clement.michaud34@gmail.com>2020-05-06 03:50:37 +0200
committerGitHub <noreply@github.com>2020-05-06 11:50:37 +1000
commitaf5754bcab4ec4e1e4ce7c0947cd0f32274b1cdd (patch)
tree38538e5e76d3f05bc2c2bcd70f357fe001937cec /internal/suites/example/compose/haproxy/auth-request.lua
parentcc06ab6c18acbf8d2d1b33d8af15d77b7b31f216 (diff)
[MISC] Add coverage for Remote-User and Remote-Groups (#982)
* Fix dev workflow. * Fix dev workflow. * Cover Remote-User and Remote-Groups using Traefik. * Cover Remote-User and Remote-Groups using HAProxy. * Fix redirection after unauthorized response when using HAProxy. Co-authored-by: Amir Zarrinkafsh <nightah@me.com>
Diffstat (limited to 'internal/suites/example/compose/haproxy/auth-request.lua')
-rw-r--r--internal/suites/example/compose/haproxy/auth-request.lua103
1 files changed, 103 insertions, 0 deletions
diff --git a/internal/suites/example/compose/haproxy/auth-request.lua b/internal/suites/example/compose/haproxy/auth-request.lua
new file mode 100644
index 000000000..debb81958
--- /dev/null
+++ b/internal/suites/example/compose/haproxy/auth-request.lua
@@ -0,0 +1,103 @@
+-- The MIT License (MIT)
+--
+-- Copyright (c) 2018 Tim Düsterhus
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a copy
+-- of this software and associated documentation files (the "Software"), to deal
+-- in the Software without restriction, including without limitation the rights
+-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+-- copies of the Software, and to permit persons to whom the Software is
+-- furnished to do so, subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included in all
+-- copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+-- SOFTWARE.
+
+local http = require("socket.http")
+
+core.register_action("auth-request", { "http-req" }, function(txn, be, path)
+ txn:set_var("txn.auth_response_successful", false)
+
+ -- Check whether the given backend exists.
+ if core.backends[be] == nil then
+ txn:Alert("Unknown auth-request backend '" .. be .. "'")
+ txn:set_var("txn.auth_response_code", 500)
+ return
+ end
+
+ -- Check whether the given backend has servers that
+ -- are not `DOWN`.
+ local addr = nil
+ for name, server in pairs(core.backends[be].servers) do
+ local status = server:get_stats()['status']
+ if status == "no check" or status:find("UP") == 1 then
+ addr = server:get_addr()
+ break
+ end
+ end
+ if addr == nil then
+ txn:Warning("No servers available for auth-request backend: '" .. be .. "'")
+ txn:set_var("txn.auth_response_code", 500)
+ return
+ end
+
+ -- Transform table of request headers from haproxy's to
+ -- socket.http's format.
+ local headers = {}
+ for header, values in pairs(txn.http:req_get_headers()) do
+ if header ~= 'content-length' then
+ for i, v in pairs(values) do
+ if headers[header] == nil then
+ headers[header] = v
+ else
+ headers[header] = headers[header] .. ", " .. v
+ end
+ end
+ end
+ end
+
+ -- Make request to backend.
+ local b, c, h = http.request {
+ url = "http://" .. addr .. path,
+ headers = headers,
+ create = core.tcp,
+ -- Disable redirects, because DNS does not work here.
+ redirect = false,
+ -- We do not check body, so HEAD
+ method = "HEAD",
+ }
+
+ -- Check whether we received a valid HTTP response.
+ if b == nil then
+ txn:Warning("Failure in auth-request backend '" .. be .. "': " .. c)
+ txn:set_var("txn.auth_response_code", 500)
+ return
+ end
+
+ txn:set_var("txn.auth_response_code", c)
+
+ -- 2xx: Allow request.
+ if 200 <= c and c < 300 then
+ if h["remote-user"] then
+ txn:set_var("txn.auth_user", h["remote-user"])
+ end
+ if h["remote-groups"] then
+ txn:set_var("txn.auth_groups", h["remote-groups"])
+ end
+ txn:set_var("txn.auth_response_successful", true)
+ -- Don't allow other codes.
+ -- Codes with Location: Passthrough location at redirect.
+ elseif c == 301 or c == 302 or c == 303 or c == 307 or c == 308 then
+ txn:set_var("txn.auth_response_location", h["location"])
+ -- 401 / 403: Do nothing, everything else: log.
+ elseif c ~= 401 and c ~= 403 then
+ txn:Warning("Invalid status code in auth-request backend '" .. be .. "': " .. c)
+ end
+end, 2) \ No newline at end of file