是否可以在HAProxy中检查HMAC有效性?理想情况下,如果HMAC有效,我想设置一个acl,以便可以在规则中使用它。
我们的Ubuntu 18.04构建服务器(运行Jenkins)位于防火墙后面,防火墙仅列出了特定的IP范围。
我们有一个HAProxy(1.8)实例,它接收所有入站请求并路由到适当的后端服务。
问题在于SonarCloud已将其Webhooks从一组定义的IP地址更改为使用HMAC来验证真实性。这意味着除非我们向所有互联网流量开放,否则Webhooks将被防火墙阻止。
https://sonarcloud.io/documentation/project-administration/webhooks/#securing-your-webhooks
如果我们可以配置HAProxy来验证HMAC,那么我们可以向所有流量打开服务器并使用HAProxy来验证这些请求(以及其他现有的IP白名单范围)。
答案 0 :(得分:1)
HAProxy本身并不执行HMAC,但是可以使用HAProxy的Lua集成来完成。
一种方法是找到一个可以满足所需HMAC风格的Lua库,然后在Lua中编写一个HAProxy转换器以获取适当的输入并计算摘要以进行比较。
我曾经使用带有Lua 5.x的HAProxy 1.6实现了类似的操作,其中客户端发送了使用HMAC-SHA1签名的URL,并且代理成功检查了其有效性。
不幸的是,我不再有权访问该代码,但我写了this HAProxy converter to do utf-8-aware URL-escaping (percent encoding) in Lua ...之所以在此提及,是因为它是使用Lua扩展HAProxy功能的一种完整方法,包括Lua代码。和HAProxy配置需要使用它,因此它可以帮助您寻求解决方案。
答案 1 :(得分:1)
感谢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 }