Optional client certificates in Kubernetes not working

Hi team,

I have setup a Kubernetes cluster with Traefik and Let's Encrypt. I have deployed my services with corresponding ingress resources and everything was working fine.

Now, I got a new requirement: One of the backend services requires client certificates.
However:

  • no other service requires client certificates
  • the client certificates are dynamic, self signed certificates. Similar to Github where the user can configure SSH keys, my users can add their public keys to the application, so it's not possible for me to configure a root CA in traefik

I have checked the docs and came across this: https://docs.traefik.io/configuration/entrypoints/#tls-mutual-authentication
From what I understand optional = true is exactly what I need.
So, I have updated my helm generated toml file in the config map and recreated the traefik pod.
The toml file looks like this:

$ kubectl describe configmap traefik -n kube-system
Name:         traefik
Namespace:    kube-system
Labels:       app=traefik
              chart=traefik-1.69.1
              heritage=Tiller
              release=traefik
Annotations:  <none>

Data
====
traefik.toml:
----
# traefik.toml
logLevel = "DEBUG"
defaultEntryPoints = ["http","https"]
insecureSkipVerify = true
[entryPoints]
  [entryPoints.http]
  address = ":80"
  compress = false
  [entryPoints.https]
  address = ":443"
  compress = false
    [entryPoints.https.tls]
      [entryPoints.https.tls.ClientCA]
      optional = true
  [entryPoints.traefik]
  address = ":8080"
[ping]
entryPoint = "http"
[kubernetes]
[traefikLog]
  format = "json"
[acme]
email = "daniel.hilgarth.ext@xxx.com"
storage = "/acme/acme.json"
entryPoint = "https"
onHostRule = true
  [acme.tlsChallenge]
[api]
  entryPoint = "traefik"
  dashboard = true

Events:  <none>

I verified in the pod's log that it actually is using this configuration.

But, it is not working. I am seeing these messages in the log:

{"level":"error","msg":"failed to create the forwarder for frontend http-https_config.xxx.de/test/test: failed to create RoundTripper for frontend http-https_config.xxx.de/test/test: failed to create TLSClientConfig: no TLS provided. Skipping frontend http-https_config.xxx.de/test/test...","time":"2019-07-08T17:16:08Z"}

How to configure traefik for it to work?

Thanks,
Daniel

Hello @dhilgarth,

When you configured your ClientCA, you did not provide any certificates to verify with.

If there are no certificates to verify with, Traefik cannot configure auth.

From the docs:

[entryPoints]
  [entryPoints.https]
  address = ":443"
  [entryPoints.https.tls]
    [entryPoints.https.tls.ClientCA]
    files = ["tests/clientca1.crt", "tests/clientca2.crt"]
    optional = false

From your original specs:

 it's not possible for me to configure a root CA in Traefik

If you cannot configure a certificate to verify with, then auth is not possible.

In Traefik v2, you can configure a route to be TCP, in which case the client can communicate directly with your backend, but v2 is currently in alpha, and does not have all features implemented.

I hope that helps clear up the behavior you are seeing.

Thanks for your answer.
From the docs:

TLS Mutual Authentication can be optional or not. If it's optional , Traefik will authorize connection with certificates not signed by a specified Certificate Authority (CA)

To me, this reads like, when optional is true, Traefik will accept a connection if:

  • no client certificate is present
  • a client certificate is present, but Traefik will not actually verify the CA. So as soon as the client certificate is valid, Traefik should accept the connection

If this understanding is incorrect, then what is the meaning of the quoted documentation?

The TCP feature of Traefik v2 doesn't help, because I still want Traefik to handle the server certificate with Let's Encrypt.

Thanks for clarifying things

Hi @dhilgarth,

The current documentation is incorrect.
When optional is true, Traefik will accept a connection if:

  • no client certificate is present
  • a client certificate is present AND is signed by a CA listed in clienCA.files

Some improvements on the matter are currently being worked on: Expand Client Auth Type configuration.

Thanks for the clarification. That explains what I am seeing.