Search code examples
kuberneteslets-encryptwildcard-subdomainkubernetes-ingresscert-manager

Wildcard SSL certificate with subdomain redirect in Kubernetes


I've configured my Kubernetes to use one wildcard SSL certificate to all my apps using cert-manager and letsencrypt, now the problem is that I can't configure subdomain redirects cause Ingress is kinda "stiff". Here's how I'm trying to achieve this:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-wildcard-ingress
  namespace: mynamespace
  annotations:
    kubernetes.io/ingress.class: nginx
    certmanager.k8s.io/cluster-issuer: letsencrypt-prod
    certmanager.k8s.io/acme-challenge-type: dns01
    certmanager.k8s.io/acme-dns01-provider: azuredns
    ingress.kubernetes.io/force-ssl-redirect: "true"
    ingress.kubernetes.io/ssl-redirect: "true"
spec:
  rules:
  - host: "domain.com"
    http:
      paths:
      - path: /
        backend:
          serviceName: some-service
          servicePort: 3000          
  - host: somesub.domain.com
    http:
      paths:
      - path: /
        backend:
          serviceName: some-other-service
          servicePort: 80
  - host: othersub.domain.com
    http:
      paths:
      - path: /
        backend:
          serviceName: one-more-service
          servicePort: 8080          
  - host: "*.domain.com"
    http:
      paths:
      - path: /
        backend:
          serviceName: default-service-to-all-other-non-mapped-subdomains
          servicePort: 8000          

  tls:
  - secretName: domain-com-tls
    hosts:         
     - "*.domain.com.br"

The problem is that Ingress ignores the declared subdomain redirects just because they're not listed in the "tls:hosts" section. And if I do put them there, it tries to issue the SSL certificate using the wildcard and the other subdomains as well in the same cert, which causes the issuer to refuse the order, saying the obvious: "subdomain.domain.com and *.domain.com are redundant"

Is there any other way that I can declare those redirects and force them to use my SSL wildcard certificate?


Solution

  • Well, for anyone who's having this kind of trouble, I've managed to solve it (not the best solution, but it's a start). For this, I'll be using cert-manager and letsencrypt.

    First, I've created a ClusterIssuer to issue for my certs with letsencrypt:

    apiVersion: certmanager.k8s.io/v1alpha1
    kind: ClusterIssuer
    metadata:      
      name: letsencrypt-prod-dns
    spec:
      acme:
        dns01:
          providers:
          - azuredns:
              clientID: MY_AZURE_CLIENT_ID
              clientSecretSecretRef:
                key: client-secret
                name: azure-secret
              hostedZoneName: mydomain.com
              resourceGroupName: MY_AZURE_RESOURCE_GROUP_NAME
              subscriptionID: MY_AZURE_SUBSCRIPTION_ID
              tenantID: MY_AZURE_TENANT_ID
            name: azuredns
        email: somemail@mydomain.com
        privateKeySecretRef:
          key: ""
          name: letsencrypt-prod-dns
        server: https://acme-v02.api.letsencrypt.org/directory
    

    Then I've created a fallback ingress to all my subdomains (this one will be the cert generator):

    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      annotations:
        certmanager.k8s.io/acme-challenge-type: dns01
        certmanager.k8s.io/acme-dns01-provider: azuredns
        certmanager.k8s.io/cluster-issuer: letsencrypt-prod-dns
        ingress.kubernetes.io/force-ssl-redirect: "true"
        ingress.kubernetes.io/ssl-redirect: "true"    
        kubernetes.io/ingress.class: nginx    
      name: wildcard-ingress
      namespace: some-namespace  
    spec:
      rules:
      - host: '*.mydomain.com'
        http:
          paths:
          - backend:
              serviceName: some-default-service
              servicePort: 80
            path: /      
      tls:
      - hosts:
        - '*.mydomain.com'
        - mydomain.com
        secretName: wildcard-mydomain-com-tls
    

    Notice that I've declared at the TLS section the wildcard AND the absolute paths, so the cert will be valid for the URLs without subdomains too.

    At this point, any requests to your domain, will be redirected to "some-default-service" with SSL(cert-manager will issue for a new cert as soon as you create the fallback ingress. This can take a while once cert-manager dns01 issuer is not mature yet), great!!!

    But, what if you need to redirect some specific subdomain to another service? No problem (since they're running on the same namespace), all you have to do is to create a new ingress to your subdomain, pointing it to your existing wildcard-mydomain-com-tls cert secret:

    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      annotations:
        ingress.kubernetes.io/force-ssl-redirect: "false"
        ingress.kubernetes.io/ssl-redirect: "true"
        kubernetes.io/ingress.class: nginx
      name: somesubdomain-ingress
      namespace: some-namespace
    spec:
      rules:
      - host: somesubdomain.mydomain.com
        http:
          paths:
          - backend:
              serviceName: some-other-service
              servicePort: 8080
            path: /        
      tls:
      - hosts:
        - somesubdomain.mydomain.com
        secretName: wildcard-mydomain-com-tls
    

    Easy peasy lemon squeezy!!! Now your somesubdomain.mydomain.com overrides your fallback rule and sends the user to another app. The only thing you should notice here is that the secret is valid only for "some-namespace" namespace, if you need to use this cert in another namespace, you could:

    1. Copy the secret from namespace "some-namespace" to "other-namespace". If you do this, remember that cert-manager will NOT renew this cert automatically for "other-namespace", so, you'd have to copy the secret again, every time your cert expires.
    2. Recreate the fallback ingress to every namespace you have, so you'd have a new cert for each of them. This approach is more ingress verbose, but, it's fully automatic.

    I guess that's it. Hope someone out there can benefit from this info.

    Cheers