Cert-manager: Cert-managert does not update an existing certificate

Created on 5 Nov 2018  路  4Comments  路  Source: jetstack/cert-manager

Describe the bug:

When I deploy a second TLS enabled ingress with a secretName that already exists, cert-manager does not update the certificate contains in this secret.

Expected behaviour:

Instead of only assuming because the secret exists, the certificate inside is correct, it should check that the new domain is covered by this certificate and if not add it as a SAN

Steps to reproduce the bug:

  1. Install ingress and cert-manager on a cluster with RBAC disabled :
helm install stable/nginx-ingress \
    --name router \
    --namespace kube-system \
    --set controller.replicaCount=2 \
    --set rbac.create=false

helm install stable/cert-manager \
    --name letsencrypt-prod \
    --namespace kube-system \
    --set ingressShim.defaultIssuerName=letsencrypt-prod \
    --set ingressShim.defaultIssuerKind=ClusterIssuer \
    --set rbac.create=false \
    --set serviceAccount.create=false

Create the cluster issue letsencrypt-prod.

Deploy a new ingress and the service behind. I am just printing the describe of the ingress :

$ kubectl -n prod describe ingress stocker-nodered
Name:             stocker-nodered
Namespace:        prod
Address:          
Default backend:  default-http-backend:80 (<none>)
TLS:
  star.mydomain.fr terminates stocker.mydomain.fr
Rules:
  Host                                           Path  Backends
  ----                                           ----  --------
  stocker.mydomain.fr  
                                                 /   stocker-nodered:1880 (<none>)
Annotations:
  kubernetes.io/ingress.class:              nginx
  kubernetes.io/tls-acme:                   true
  nginx.ingress.kubernetes.io/auth-realm:   Wow Wow!  Authentication Required
  nginx.ingress.kubernetes.io/auth-secret:  stocker-basic-auth
  nginx.ingress.kubernetes.io/auth-type:    basic
Events:
  Type    Reason             Age   From                      Message
  ----    ------             ----  ----                      -------
  Normal  CREATE             47m   nginx-ingress-controller  Ingress prod/stocker-nodered
  Normal  CREATE             47m   nginx-ingress-controller  Ingress prod/stocker-nodered
  Normal  CreateCertificate  47m   cert-manager              Successfully created Certificate "star.mydomain.fr"
  Normal  UPDATE             46m   nginx-ingress-controller  Ingress prod/stocker-nodered
  Normal  UPDATE             46m   nginx-ingress-controller  Ingress prod/stocker-nodered
  Normal  UpdateCertificate  33m   cert-manager              Successfully updated Certificate "star.mydomain.fr"
  Normal  UpdateCertificate  26m   cert-manager              Successfully updated Certificate "star.mydomain.fr"

If I create a new Ingress with :

rules:
  - host: enricher.mydomain.fr
    ...
    tls:
      - secretName: star.mydomain.fr

It does not update the existing star.mydomain.fr certificate :

1105 17:39:47.584039       1 leaderelection.go:175] attempting to acquire leader lease  kube-system/cert-manager-controller...
I1105 17:40:48.676278       1 leaderelection.go:184] successfully acquired lease kube-system/cert-manager-controller
I1105 17:40:48.676501       1 controller.go:68] Starting issuers controller
I1105 17:40:48.676603       1 controller.go:68] Starting certificates controller
I1105 17:40:48.676695       1 controller.go:68] Starting clusterissuers controller
I1105 17:40:48.679510       1 controller.go:68] Starting ingress-shim controller
I1105 17:40:48.776882       1 controller.go:140] clusterissuers controller: syncing item 'letsencrypt-prod'
I1105 17:40:48.777071       1 logger.go:88] Calling GetAccount
I1105 17:40:48.779684       1 controller.go:168] ingress-shim controller: syncing item 'prod/stocker-nodered'
I1105 17:40:48.779713       1 controller.go:168] ingress-shim controller: syncing item 'prod/water-flow-enricher-nodered'
I1105 17:40:48.779835       1 sync.go:140] Certificate "star.mydomain.fr" for ingress "enricher-nodered" already exists
I1105 17:40:48.779764       1 sync.go:140] Certificate "star.mydomain.fr" for ingress "stocker-nodered" already exists
I1105 17:40:48.780340       1 sync.go:143] Certificate "star.mydomain.fr" for ingress "stocker-nodered" is up to date

Note : I did not create star.mydomain.fr myself, it was created automatically by cert-manager for the first ingress stocker.mydomain.fr.

Anything else we need to know?:

Environment details::

  • Kubernetes version (e.g. v1.10.2): 1.11.3
  • Cloud-provider/provisioner (e.g. GKE, kops AWS, etc): Azure AKS
  • cert-manager version (e.g. v0.4.0): quay.io/jetstack/cert-manager-controller:v0.5.0
  • Install method (e.g. helm or static manifests): helm

/kind bug

Most helpful comment

Ah, I see now.

This is expected behaviour - you should either manually create your own Certificate resource (instead of using ingress-shim) that contains both hosts, or otherwise specify a different secretName for each ingress.

ingress-shim won't automatically merge the tls sections in the way you're expecting! 馃槵

All 4 comments

Could you include the full YAML manifests you are using here, instead of just describe output? It hides important things like annotations etc 馃槃

It'd be great if you could also extend your steps to reproduce to be a full set of example manifests, so we can attempt to reproduce ourselves and then build a check for this behaviour into our e2e testing suite 馃槃

Sorry for the late answer. This is an example of 2 ingress resources. I thought that the cert-manager would have recognize that he already generated a cert for the first one and just update the cert for the second one with a SAN.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    kubernetes.io/tls-acme: "true"
    nginx.ingress.kubernetes.io/auth-realm: "Wow Wow!  Authentication Required"
    nginx.ingress.kubernetes.io/auth-secret: enricher-nodered-basic-auth
    nginx.ingress.kubernetes.io/auth-type: basic
  labels:
    app: enricher-nodered
  name: enricher-nodered
  namespace: prod
spec:
  rules:
  - host: enricher-nodered.project.mydomain.fr
    http:
      paths:
      - backend:
          serviceName: enricher-nodered
          servicePort: 1880
        path: /
  tls:
  - hosts:
    - enricher-nodered.project.mydomain.fr
    secretName: star.project.mydomain.fr
status: {}
````

And the other one:

```yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    kubernetes.io/tls-acme: "true"
    nginx.ingress.kubernetes.io/auth-realm: "Wow Wow!  Authentication Required"
    nginx.ingress.kubernetes.io/auth-secret: stocker-nodered-basic-auth
    nginx.ingress.kubernetes.io/auth-type: basic
  labels:
    app: stocker-nodered
  name: stocker-nodered
  namespace: prod
spec:
  rules:
  - host: stocker-nodered.project.mydomain.fr
    http:
      paths:
      - backend:
          serviceName: stocker-nodered
          servicePort: 1880
        path: /
  tls:
  - hosts:
    - stocker-nodered.project.mydomain.fr
    secretName: star.project.mydomain.fr
status: {}

Ah, I see now.

This is expected behaviour - you should either manually create your own Certificate resource (instead of using ingress-shim) that contains both hosts, or otherwise specify a different secretName for each ingress.

ingress-shim won't automatically merge the tls sections in the way you're expecting! 馃槵

@munnerz : ok my bad, I thought that it would see that it had generated the previous one and makes an expand call to let'sencrypt to add the new SAN. Too bad. Anyway I went the road you are pointing out with one secret per certificate. Thanks for your answer.

Was this page helpful?
0 / 5 - 0 ratings