We are currently in the process of adopting the AKS baseline project for our cloud platform. As a part of this adoption, we are try to replace the Kubernetes manifest-based installation of Traefik with the Traefik Helm chart. Originally, using the manifest approach to installing Traefik, we configured certificates by mounting them into the Traefik container and pointing to them via the traefik.toml file:
[tls] [[tls.certificates]] certFile = "/certs/tls.crt" keyFile = "/certs/tls.key" stores = ["default"] [tls.stores] [tls.stores.default] [tls.stores.default.defaultCertificate] certFile = "/certs/tls.crt" keyFile = "/certs/tls.key" [tls.options.default] minVersion = "VersionTLS12" sniStrict = true
As you can see, we have strict SNI enabled. In order to use the same certificate by default across all ingress routes, unless another certificate is specified, we have been required to point to the certificate twice.
Now we try to do this the Kubernetes CRD-way. Strict SNI is configured via a TLSOption resource:
apiVersion: traefik.containo.us/v1alpha1 kind: TLSOption metadata: name: default labels: app.kubernetes.io/name: traefik helm.sh/chart: traefik-10.19.4 app.kubernetes.io/managed-by: Helm spec: minVersion: VersionTLS12 sniStrict: true
For the certificate, we understand that we can use a TLSStore resource:
apiVersion: traefik.containo.us/v1alpha1 kind: TLSStore metadata: name: default labels: app.kubernetes.io/name: traefik helm.sh/chart: traefik-10.19.4 app.kubernetes.io/managed-by: Helm spec: defaultCertificate: secretName: "our-certificate-secret"
But as one might expect, this does not work as long as strict SNI is enabled. If we disable strict SNI, the certificate works as expected. We can see in the source code that Traefik explicitly skips checking the default certificate for a hostname match if strict SNI is enabled. So the question is, how does one replicate the following piece of configuration with Traefik CRDs and/or the cli arguments:
[tls] [[tls.certificates]] certFile = "/certs/tls.crt" keyFile = "/certs/tls.key" stores = ["default"]
Furthermore, we have noticed that if we configure a single IngressRoute to use our certificate, that certificate also becomes available to other IngressRoutes. For instance, the following:
apiVersion: traefik.containo.us/v1alpha1 kind: IngressRoute metadata: name: "traefik-ping" annotations: kubernetes.io/ingress.class: "traefik-internal" spec: entryPoints: - websecure routes: - kind: Rule match: Host(`something.something`) && Path(`/ping`) services: - kind: Service name: "traefik-ping" namespace: "traefik" port: 9000 tls: secretName: "our-certificate-secret"
Will also enable other IngressRoutes without a tls section to use the same certificate (assuming the certificate matches the hostnames). We do not like this approach to making our certificate available, since it means that deleting the ping route will break TLS for other unrelated IngressRoutes.
Note: Our Traefik ping IngressRoute is only available on a private virtual network behind our client-facing gateways.