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