Traefik ignores TLSOptions

I'm using traefik helm, deployed using Pulumi. I must disable TLS 1.0, 11 and some ciphers but I can't get it to work.

I am providing the --entrypoints.websecure.http.tls.options=default parameter, and creating the TLSOptions (both called "tls-options" as this is what the ingressRoute mentions and "default").

But I still get TLS 1.0 and 1.1 supported (as well as the ciphers) in sslyze or other tools.

This is the chart:

chart: "traefik",
fetchOpts: { repo: "https://helm.traefik.io/traefik", version: "12.0.7" },
values: {
logs: {
  general: {
    format: "json",
    level: "ERROR"
  },
  access: {
    enabled: true,
    format: "json",
    fields: {
      headers: {
        names: {
          "X-Request-ID": "keep",
          "X-Tenant-ID": "keep"
        }
      }
    }
  }
},
ingressRoute: {
  dashboard: { enabled: false }
},

providers: {
  kubernetesCRD: { allowCrossNamespace: true }
},

deployment: {
  replicas: 3
},

service: {
  annotations: {
    "service.beta.kubernetes.io/aws-load-balancer-backend-protocol": "tcp",
    "service.beta.kubernetes.io/aws-load-balancer-ssl-cert": stampCertificate.certificateArn,
    "service.beta.kubernetes.io/aws-load-balancer-ssl-ports": "443",
    "service.beta.kubernetes.io/aws-load-balancer-access-log-enabled": "true",
    "service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout": "180",
    "service.beta.kubernetes.io/aws-load-balancer-access-log-emit-interval": "60",
    "service.beta.kubernetes.io/aws-load-balancer-access-log-s3-bucket-name": stampLogBucketName,
    "service.beta.kubernetes.io/aws-load-balancer-type": "external",
    "service.beta.kubernetes.io/aws-load-balancer-nlb-target-type": "instance",
    "service.beta.kubernetes.io/aws-load-balancer-scheme": "internet-facing"
  }
},
tlsOptions: {
  "tls-options": {
    minVersion: "VersionTLS12",
    sniStrict: true,
    cipherSuites: [
      // These suites are consider safe. We check with sslyze
      // TLS 1.3
      "TLS_AES_256_GCM_SHA384",
      "TLS_AES_128_GCM_SHA256",
      "TLS_CHACHA20_POLY1305_SHA256",

      // TLS 1.2
      "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
      "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
      "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
      "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
      "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
      "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",

      // Downgrade attack prevention (RFC 7507)
      "TLS_FALLBACK_SCSV"
    ]
  },
  default: {
    minVersion: "VersionTLS12",
    sniStrict: true,
    cipherSuites: [
      // These suites are consider safe. We check with sslyze
      // TLS 1.3
      "TLS_AES_256_GCM_SHA384",
      "TLS_AES_128_GCM_SHA256",
      "TLS_CHACHA20_POLY1305_SHA256",

      // TLS 1.2
      "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
      "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
      "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
      "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
      "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
      "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",

      // Downgrade attack prevention (RFC 7507)
      "TLS_FALLBACK_SCSV"
    ]
  }
},
additionalArguments: ["--log.level=DEBUG", "--entrypoints.websecure.http.tls.options=default"],

And this is the TLSOptions created:

apiVersion: traefik.containo.us/v1alpha1
kind: TLSOption
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      ...
  creationTimestamp: "2024-01-28T15:44:21Z"
  generation: 1
  labels:
    app.kubernetes.io/instance: traefik
    app.kubernetes.io/managed-by: pulumi
    app.kubernetes.io/name: traefik
    helm.sh/chart: traefik-12.0.7
  name: tls-options
  namespace: default
  resourceVersion: "44775082"
  uid: 0e7b948a-866a-469f-8967-f83b5acde8ee
spec:
  cipherSuites:
  - TLS_AES_256_GCM_SHA384
  - TLS_AES_128_GCM_SHA256
  - TLS_CHACHA20_POLY1305_SHA256
  - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
  - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
  - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
  - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
  - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  - TLS_FALLBACK_SCSV
  minVersion: VersionTLS12
  sniStrict: true

This is an example of one ingressRoutes:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      ...
  creationTimestamp: "2023-12-26T09:49:51Z"
  generation: 2
  labels:
    app.kubernetes.io/instance: tool-dev2
  name: http-tool-ingress-routes
  namespace: backend
  resourceVersion: "42089552"
  uid: 30033267-9462-4056-bb82-c42564d01f04
spec:
  entryPoints:
  - websecure
  routes:
  - kind: Rule
    match: Method(`GET`, `POST`, `OPTIONS`)
    middlewares:
    - name: secured
      namespace: default
    services:
    - name: tool-webserver
      port: 5000
  tls:
    options:
      name: tls-options
      namespace: default

I don't know if it's this but I still get these warnings:

traefik-79d98984d7-p2lhc:{"entryPointName":"websecure","level":"warning","msg":"No domain found in rule Method(`GET`, `POST`, `OPTIONS`), the TLS options applied for this router will depend on the SNI of each request","routerName":"backend-http-tool-ingress-routes-90480f2ea506b7dfd67c@kubernetescrd",

Would love some help

2 Likes

It seems like you are dealing with configuring TLS options for Traefik using Helm and Pulumi.

To disable TLS 1.0 and 1.1 and configure specific ciphers, you need to ensure that Traefik is correctly configured with the desired TLS options.

Here are some steps you can take:

First you need to ensure that the Helm chart you are using supports the customization of TLS options. and the examine the Helm chart's values or documentation to confirm whether it provides options for specifying TLS configurations.

In your Pulumi script, make sure you are correctly passing the TLS options to Traefik. It seems like you are using the --entrypoints.websecure.http.tls.options=default parameter. Double-check this parameter to ensure it's correctly formatted and applied.

Next is to ensure that you are providing the TLS options correctly. It's important to confirm that the provided TLS Options are affecting Traefik's configuration. Now verify that the TLS options are being applied to the appropriate entrypoints.

Here is an example of how you might configure TLS Options:

const tlsOptions = {
    "default": {
        "minVersion": "VersionTLS12",
        "cipherSuites": [
            "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
            "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
            // Add more desired ciphers
        ]
    }
};

// Pass tlsOptions to Traefik during deployment
// ...

Now you need to ensure that the version of Traefik you are using supports the TLS options you are trying to configure. Newer versions may have additional features or changes in configuration syntax.

Now, use Traefik logs to check whether the TLS options are being applied as expected. You can also inspect the generated Traefik configuration to see if the TLS settings are correctly reflected.

const traefikDeployment = new k8s.apps.v1.Deployment("traefik-deployment", {
    // ... other configurations
    template: {
        spec: {
            // ... other pod spec configurations
            containers: [
                {
                    // ... traefik container configurations
                    args: [
                        // ... other args
                        "--log.level=DEBUG", // Add debug level logging
                    ],
                },
            ],
        },
    },
});

Now, after deploying Traefik with the desired configurations, perform tests using tools like sslyze or online SSL/TLS testing services to verify that TLS 1.0 and 1.1 are disabled, and the desired ciphers are in use.