I have a mutual-TLS setup with HAProxy terminating incoming SSL connections. I need to perform client certificates validation on the backend, not on haproxy side since we have a dynamic truststore and I cannot just set a single ca-file and delegate all the validation logic to haproxy. Regular setup works fine (where haproxy validates a client cert against CA cert):
bind *:443 ssl crt /etc/certs/haproxy.pem verify required ca-file /etc/certs/ca.crt
http-request redirect scheme https unless { ssl_fc }
http-request set-header X-SSL-ClientCert %{+Q}[ssl_c_der,base64]
Backend receives X-SSL-ClientCert
correctly, but this is not enough.
If verify required ca-file /etc/certs/ca.crt
is removed to skip validation on haproxy, X-SSL-ClientCert
is empty when read on the backend, that is, HAProxy does not set the header with the client certificate anymore. Any ideas on how to fix this?
Okay, after some tinkering I stumbled upon the following:
HAProxy documentation https://cbonte.github.io/haproxy-dconv/2.3/configuration.html#5.2-verify states two options for verify
: [none|required]
, but it seems there is an undocumented option, namely, optional
which seems to do the trick:
bind *:443 ssl crt /etc/certs/haproxy.pem verify optional ca-file /etc/certs/ca.crt
http-request set-header X-SSL-Client-Cert %{+Q}[ssl_c_der,base64]
http-request set-header X-SSL-Client-CN %{+Q}[ssl_c_s_dn(cn)]
http-request set-header X-SSL-Client-Verify %[ssl_c_verify]