kes icon indicating copy to clipboard operation
kes copied to clipboard

unable to verify clients using haproxy as a TLS proxy

Open frogu opened this issue 3 years ago • 1 comments

Bug description

TLS proxy documentation states that a proxy such as nginx or haproxy may be used, but only nginx example is provided.

my haproxy configuration for the header http-request set-header X-Tls-Client-Cert %[ssl_c_der,base64]

my minio-kes (docker: minio/kes:v0.22.3) configuration for the proxy: (my.crt and my.key signed by CA, the cacert is available in the container)

tls:
    cert: /ssl/my.crt
    key: /ssl/my.key
    identities: 
      - redacted
      - redacted
    proxy:
        header:
            cert: X-Tls-Client-Cert

issues:

  1. the proxy can connect, but can not check /v1/status -> {"message":"no client certificate is present"}, I was forced to accept http400 as valid response for the healthcheck
  2. haproxy (in the version embedded in vmware nsx-v) can only send base64 or hex encoded DER certificate, without any newlines, does not have set-var exposed or url_enc available
  3. internal/proxy.go uses url.QueryUnescape which replaces "+" with " ", which makes it an invalid base64 string
  4. last 3 errors result in message: "invalid client certificate" without any indication at which moment the error occurred (query unescape, pem decode, x509 parse certificate)

Expected behavior

  • proxy identities should be allowed to call /v1/status
  • documentation updated with working haproxy config for setting the http header with the client certificate
  • proxy able to parse base64 encoded DER certificate
  • error message returned by server more informative

Additional context

  1. minio-kes docker v0.22.3
  2. Ubuntu 18.04.4 LTS (should not be relevant)
  3. x86_64
  4. Can not swap haproxy for nginx (because it is an internal vmware-nsx-v loadbalancer)

Ideas for solution

Provide another parser for base64 encoded DER certificate, and a configuration variable, to choose the parser. e.g. tls.proxy.header.content_format: X where X is one of "base64urlencPEM", "base64DER" or tls.proxy.header.generated_by: Y where Y is one of "nginx", "haproxy"

which chooses an appropriate parser.

frogu avatar Feb 21 '23 20:02 frogu

Thank you for the detailed description @frogu - I will look into this.

Your proposed configuration option for specifying the certificate encoding seems reasonable. I will do some additional analysis on how different Proxies / LBs behave.

aead avatar Feb 23 '23 21:02 aead