IngressRoute without "secretName" field yields 404 response

When I use a Kubernetes IngressRoute object that lacks a "spec.tls.secretName" field, Traefik refuses to route requests to the backend servers, responding to requests with HTTP status code 404. If I populate the "spec.tls.secretName" field, Traefik does route the requests to the backend servers.

Here are the pertinent manifests, attempting to capture requests below the /dashboard path, stripping that prefix, and routing the requests to servers selected by the myns/mysvc Kubernetes Service.

apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: strip-mysvc-prefix
  namespace: myns
spec:
  stripPrefix:
    prefixes:
    - /dashboard
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: mysvc
  namespace: myns
spec:
  routes:
  - kind: Rule
    match: PathPrefix(`/dashboard`)
    services:
    - name: mysvc
      port: 443
      scheme: https
    middlewares:
    - name: strip-mysvc-prefix
      namespace: myns
  tls:
    # Uncomment this to make this work.
    #secretName: mysvc-tls

My dynamic Traefik configuration specifies a default server certificate. I have confirmed that Traefik uses that certificate. I also have the "serversTransport.insecureSkipVerify" field set to true in my static configuration, to allow Traefik to talk to my upstream proxy targets without necessarily needing to trust those servers.

I've tried omitting the "tls" field entirely in the IngressRoute. Doing so also yields a 404 response. Is it possible to have Traefik route to servers with an IngressRoute object like this, but without specifying a certificate to use? I'd like to have Traefik use a default server certificate to terminate TLS, inspect the URL, and route to my servers, most of which will also use HTTPS.

The problem appears to be with how Traefik parses and interprets the IngressRouteSpec struct's "TCP" field. If we just write the following YAML, the Go YAML parser considers the value to be empty, and unmarshals the "TCP" field as a nil pointer.

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: example
  namespace: default
spec:
  # ...
  tls:

Traefik still responds with status code 404 for that route.

If we include the "spec.tls.options" field, though, then the YAML parser yields a non-nil *TLS value for the "TCP" field:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: example
  namespace: default
spec:
  # ...
  tls:
    options:

We can also include an option name, so long as it's empty:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: example
  namespace: default
spec:
  # ...
  tls:
    options:
      name: ""

With the latter two IngressRoute objects, Traefik logs the complaint repeatedly:

level=debug msg="Skipping TLS sub-section: No secret name provided" providerName=kubernetescrd

However, the route works as intended. Traefik no longer responds with the 404 status code to the same HTTP requests.

It looks like this subtlety would go away if Traefik would accept an otherwise-empty "spec.tls" field as indicative that the route should be served via HTTPS. Perhaps we should remove the "omitempty" struct tag field for the IngressRouteSpec.TLS field.

Does this warrant filing a GitHub issue, or do you consider this to be working as intended?

Hello @seh,

The following snippets:

spec:
  tls:
spec:
  # ...
  tls:
    options:

are not valid yaml, as the fields do not have values.

Either omit the tls field entirely, or use tls:{}, which should allow processing as normal.

Thanks for pointing that out. I started with the empty "secretName" field, then worked back up the tree, seeing what still produced a working route. Interestingly, Traefik (really, the Go YAML parsing library) doesn't complain about parsing those documents.

It surprised me that setting the "spec.routes.serivces.scheme" field to "https" wasn't enough to convince Traefik to serve this route over HTTPS, but I guess that's just telling it what to use in between the proxy and the backend server, and not telling it how to serve the proxy front end.

Is it correct, then, that the intended design is that an IngressRoute indicates that it wishes to be served over HTTPS by including a "spec.tls" field, and if it doesn't include that field, then it's indicating that HTTP will suffice?