Hello,
I have configured haproxy (2.4.3 as docker container) to validate the token via lua script against Keycloak server. Otherwise it has been working ok, but now I detected problem with files larger than the tune.bufsize
configuration.
I’m using this library to connect the Keycloak server: GitHub - haproxytech/haproxy-lua-http: Simple Lua HTTP helper && client for use with HAPro. The script seems to run fine and token is validated.
The error returned is 500 Internal Server Error and the request is never forwarded to the api-server. If the multipart file is smaller or bufsize is increased, everything works without any problems.
Is this a bug or am I missing some option here?
global
lua-load /usr/local/etc/haproxy/authorize.lua
maxconn 50000
log stdout local0
user haproxy
group haproxy
nbthread 4
cpu-map auto:1/1-4 0-3
ssl-default-bind-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
defaults
timeout connect 10s
timeout client 30s
timeout server 30s
timeout tunnel 1h
log global
mode http
option httplog
maxconn 3000s
option http-keep-alive
resolvers mydns
parse-resolv-conf
frontend localhost
bind *:8443 ssl crt /usr/local/etc/certs/cert.pem
http-request redirect scheme https unless { ssl_fc }
http-request set-header X-Forwarded-Proto https
# ACL for target
acl is_api path_beg /api/
http-request set-var(req.token) hdr(authorization)
http-request lua.authorize keycloak keycloak1 testrealm if is_api
# ACL for token
acl is_valid_organization var(req.token_ok) -m bool
acl is_authenticated var(req.is_authenticated) -m bool
# Deny if not authenticated for api
http-request deny if !is_authenticated
use_backend api if is_api
backend api
option forwardfor
server server1 apiserver:8080 check resolvers mydns
backend keycloak
option forwardfor
server keycloak1 keycloak:8080 check resolvers mydns
local http = require('http')
local function main(txn, backend, server, realm)
-- extract authorization and host headers
local token = txn.get_var(txn, "req.token")
local host_header = txn.sf:req_fhdr("host")
if token == nil then
core.log(6, "No authorization token found")
do return end
end
core.Info(token)
-- Create url for keycloak token validation
local url =
"http://" .. core.backends[backend].servers[server]:get_addr() ..
"/auth/realms/" .. realm .. "/protocol/openid-connect/userinfo"
-- Validate the token, authorization header is copied from client. host-header also needs to be copied and x-forwarded-proto set to https
-- for token issuer matching
local res, err = http.get {
url = url,
headers = {
authorization = token,
host = host_header,
["x-forwarded-proto"] = "https"
}
}
if res then
core.Info(tostring(res.content))
if res.status_code == 200 then
txn:set_var("req.is_authenticated", true)
core.Info("Token validated. Checking access rights.")
local json = res:json();
local path = txn.sf:path() .. "/"
if json.organization ~= nil then
local pattern = "^/.*/" .. json.organization .. "/"
core.Info(pattern)
core.Info(string.match(path, pattern))
if string.match(path, pattern) ~= nil
then
txn:set_var("req.token_ok", true)
end
end
else
core.Info("Token not valid!")
txn:set_var("req.is_authenticated", false)
end
end
end
core.register_action("authorize", {"http-req"}, main, 3)