nginx-ingress, cert-manager, and default wildcard certificates

Friday, January 28, 2022

I have quite a few internal only services running on my Kubernetes cluster. For all these services I wanted to use SSL, but using the default method of getting an ACME certificate from Let’s Encrypt (HTTP-01) wouldn’t work due to my setup. I also didn’t want to have to generate a certificate for every service I decided to spin up. Using cert-manager I was able to generate an ACME wildcard certificate and then set it to the default certificate on the nginx-ingress.

First install cert-manager using helm.

$ helm repo add jetstack https://charts.jetstack.io
$ helm repo update
$ helm install cert-manager jetstack/cert-manager --namespace cert-manager --version v1.6.1 --set installCRDs=true --set prometheus.enabled=false

Next, look at the cert-manager documentation to see if your DNS provider works with cert-manager. Depending on your DNS provider your setup here will look different. As an example I will show my setup using Cloudflare.

First I had to create a secret that had my Cloudflare API key set in it:

apiVersion: v1
kind: Secret
metadata:
  name: cloudflare-api-token-secret
type: Opaque
stringData:
  api-token: lksdjlfksjdlkfjslkfdj

Then I created an issuer that used Cloudflare as the DNS solver:

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
  namespace: cert-manager
spec:
  acme:
    # The ACME server URL
    server: https://acme-v02.api.letsencrypt.org/directory
    # Email address used for ACME registration
    email: [email protected]
    # Name of a secret used to store the ACME account private key
    privateKeySecretRef:
      name: letsencrypt-prod
    # Enable the HTTP-01 challenge provider
    solvers:
    - dns01:
        cloudflare:
          email: [email protected]
          apiTokenSecretRef:
            name: cloudflare-api-token-secret
            key: api-token 

Here is where it deviates from the normal usage of cert-manager and ingresses. Instead of specifying a HTTPS entry on every one of my ingress resources, I created a general wildcard certificate:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: binaryronin-wildcard
spec:
  secretName: binaryronin-wildcard
  dnsNames:
  - '*.binaryronin.io'
  issuerRef:
    name: letsencrypt-prod
    kind: ClusterIssuer 

Then, I edited the nginx deployment and set the certificate as the default certificate:

...
spec:
  containers:
  - args:
    - --default-ssl-certificate=cert-manager/binaryronin-wildcard
devopskubernetessslinfrastructure

Using TinyDB JSON with S3