Is it possible to check HMAC validity in HAProxy? Ideally I'd like to set an acl if the HMAC is valid so I can use this in rules.
Our Ubuntu 18.04 build server (running Jenkins) sits behind a firewall with only specific IP ranges white-listed.
We have an HAProxy (1.8) instance receiving all inbound requests and routing to the appropriate backend service.
The problem is SonarCloud have changed their webhooks from a defined set of IP addresses to using HMAC to validate authenticity. This means the webhooks are blocked by the firewall unless we open it to all internet traffic.
https://sonarcloud.io/documentation/project-administration/webhooks/#securing-your-webhooks
If we can congifure HAProxy to validate the HMAC then we can open the server to all traffic & use HAProxy to validate these requests (as well as other existing IP whitelisted ranges).
Thanks to Michael for the pointer to HAProxy/Lua integration. My solution noted here for reference.
Created the following Lua script (hmac_validate.lua):
hmac = require('openssl.hmac')
local function tohex(s)
return (string.gsub(s, ".", function (c)
return string.format("%.2x", string.byte(c))
end))
end -- tohex
function validate_sonar_hmac(txn, hmac_header_key, hmac_secret)
local payload = txn.req:dup() -- take a copy of the request content
local body = string.sub(payload,string.find(payload,"\r\n\r\n")+4) -- strip off the headers
local signature = txn.sf:req_fhdr(hmac_header_key) -- get the HMAC signature sent on the request
-- calculate hmac from body & secret
local sc_hmac = hmac.new(hmac_secret, "sha256")
local calculated_signature = tohex(sc_hmac:final(body))
local signatures_match = calculated_signature == signature
if not signatures_match then
core.Alert("Sonar Cloud HMAC signature mismatch - received '"..signature.."' but calculated '"..calculated_signature.."'")
end
txn:set_var("req.sonar_request_valid", signatures_match)
end;
core.register_action("validate-sonar-hmac", {"http-req"}, validate_sonar_hmac, 2)
HA Proxy config changed to add these lines:
global
lua-load /etc/haproxy/hmac_validate.lua
frontend
acl sonarcloud hdr(X-Sonar-Webhook-HMAC-SHA256) -m found
http-request lua.validate-sonar-hmac X-Sonar-Webhook-HMAC-SHA256 {{ sonarcloud_hmac_secret }} if sonarcloud
http-request deny if sonarcloud !{ var(req.sonar_request_valid) -m bool }