Created
January 9, 2019 12:15
-
-
Save bzed/e1e6c76e98225f997062c57aacecd2fd to your computer and use it in GitHub Desktop.
haproxy pem formatted ssl client cert fetch - ssl_c_pem - like ssl_c_der
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require("base64") | |
core.register_fetches("ssl_c_pem", function(txn) | |
local der = txn.f:ssl_c_der() | |
local wrap = ('.'):rep(64); | |
local envelope = "-----BEGIN %s-----\n%s\n-----END %s-----\n" | |
local typ = "CERTIFICATE"; | |
der = base64.encode(data); | |
return string.format(envelope, typ, der:gsub(wrap, '%0\n', (#der-1)/64), typ); | |
end) |
Where does the 'data' variable on line 9 get defined?
For folks finding this many years later, here is a working example
function client_cert(txn, t)
local der = txn.f:ssl_c_der()
local chain_der = txn.f:ssl_c_chain_der()
if type(der) == 'nil' then
return
end
local pem_w_chain = "-----BEGIN CERTIFICATE-----"
pem_w_chain = pem_w_chain .. "\n"
pem_w_chain = pem_w_chain .. txn.c:base64(der)
pem_w_chain = pem_w_chain .. "\n"
pem_w_chain = pem_w_chain .. "-----END CERTIFICATE-----"
pem_w_chain = txn.c:url_enc(pem_w_chain, "query")
if t == "req" then
txn.http:req_add_header("X-SSL-Client-Cert", pem_w_chain)
end
if t == "res" then
txn.http:res_add_header("X-SSL-Client-Cert", pem_w_chain)
end
if type(chain_der) ~= 'nil' then
local pem_w_chain = "-----BEGIN CERTIFICATE-----"
pem_w_chain = pem_w_chain .. "\n"
pem_w_chain = pem_w_chain .. txn.c:base64(chain_der)
pem_w_chain = pem_w_chain .. "\n"
pem_w_chain = pem_w_chain .. "-----END CERTIFICATE-----"
pem_w_chain = txn.c:url_enc(pem_w_chain, "query")
if t == "req" then
txn.http:req_add_header("X-SSL-Client-Cert", pem_w_chain)
end
if t == "res" then
txn.http:res_add_header("X-SSL-Client-Cert", pem_w_chain)
end
end
end
core.register_action("clientcert", { "http-req", "http-res" }, client_cert, 1)
This will add the X-SSL-Client-Cert
header to the request or response with the contents of the header being URL encoded PEM of the client certificate and chain.
You can use it in your haproxy config under a frontend like so
http-request lua.clientcert "req"
http-response lua.clientcert "res"
If you are using this header in hashicorp vault for example you'll want this config on the listener
x_forwarded_for_client_cert_header = "X-SSL-Client-Cert"
x_forwarded_for_client_cert_header_decoders = "URL,DER"
For folks finding this many years later, here is a working example
nice, thank you very much! Can't even remember which haproxy version we used back then :)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I forgot to mention that I installed base64 from luarocks:
https://luarocks.org/modules/iskolbin/base64
Before that I had this error message:
[ALERT] 108/233244 (20196) : parsing [/etc/haproxy/haproxy.conf:14] : lua runtime error: /etc/haproxy/ssl_c_der.lua:1: module 'base64' not found:
no field package.preload['base64']
no file '/usr/share/lua/5.3/base64.lua'
no file '/usr/share/lua/5.3/base64/init.lua'
no file '/usr/lib64/lua/5.3/base64.lua'
no file '/usr/lib64/lua/5.3/base64/init.lua'
no file './base64.lua'
no file './base64/init.lua'
no file '/usr/lib64/lua/5.3/base64.so'
no file '/usr/lib64/lua/5.3/loadall.so'
no file './base64.so'