0

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?

MastaP
  • 51
  • 1
  • 5

2 Answers2

0

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]
MastaP
  • 51
  • 1
  • 5
  • There is another [`verify`](http://cbonte.github.io/haproxy-dconv/2.3/configuration.html#5.1-verify) setting under [Bind](http://cbonte.github.io/haproxy-dconv/2.3/configuration.html#5) section which also lists the `optional` value. – Cigarette Smoking Man Feb 02 '21 at 13:15
0

You do have the right thought.

On the other hand, I think that there is a more readable writing.

In your /etc/hapee/hapee-lb.cfg

bind :443 ssl crt-list /etc/hapee/certs-file

In your /etc/hapee/certs-file

cert_example1.pem [verify optional ca-file /etc/hapee/certs/ca.crt]
cert_example2.pem

So you can easily list all your certificates and possibly the verify options according to your SNI.

Backend who match

backend
        http-request set-header X-SSL-Client-DN            %[ssl_c_s_dn]
        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]
antoninG
  • 21
  • 4
  • The thing is that I do not want HAProxy to check the validity of the client certificates. Behind HAProxy I have a Spring Boot application which has a dynamic truststore (which can be changed at runtime) and this app needs to perform certificate validation, not HAProxy. HAProxy just needs to forward the certificate in a header to the app – MastaP Jan 12 '21 at 11:56
  • I updated my answer with the backend to avoid misunderstandings – antoninG Jan 12 '21 at 18:45
  • In fact, your answer does not differ from my own answer below, with the exception of ca-file vs ca-list. The only misunderstanding is that ideally, I would like to totally omit the verification of client certificates on haproxy and delegate it to my application which stands after it – MastaP Jan 13 '21 at 15:00
  • The only way is to use "verify optional", haproxy will simply ask a cert to client without denying any connection when the cert is invalid or even not provided. – antoninG Jan 15 '21 at 14:58