感谢 Michael 提供指向 HAProxy/Lua 集成的指针。我的解决方案在这里注明以供参考。
创建了以下 Lua 脚本 (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 代理配置更改为添加以下行:
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 }