Configuring Automatic TLS Certificate Provisioning for Cloud Native Runtimes

Enabling Automatic TLS Certificate Provisioning

You can configure Cloud Native Runtimes to automatically obtain and renew TLS certificates for your workloads. Automatic TLS certificate provisioning allows you to secure your clusters and domains without manually generating or renewing certificates. Automatic TLS certificate provisioning reduces the manual certificate workload for admins and developers.

Cloud Native Runtimes supports both HTTP01 and DNS01 cert-manager challenge types. For more information about cert-manager challenge types, see ACME in the cert-manager documentation.

VMware recommends using Let’s Encrypt as your certificate authority. However, you can integrate Cloud Native Runtimes with any ACME compatible certificate authority.

Prerequisites

You can enable HTTPS with Automatic TLS certificate provisioning for Cloud Native Runtimes.

You need the following prerequisites to use secure HTTPS connections with automatic TLS certificate provisioning:

  • A cluster configured to use a custom domain. See Configuring External DNS with CNR.
  • A DNS provider configured with your domain name.
  • cert-manager version 1.0.0 or later. See Installing cert-manager for TLS certificates in the Knative documentation. If you are installing CNRs as part of TAP, then cert-manager should be already installed.
  • HTTP01 challenges: An internet-reachable cluster.
  • DNS01 challenges: API access to set DNS records.

Enable Auto TLS Using an HTTP01 Challenge

You can use the HTTP01 challenge type to validate a domain with Cloud Native Runtimes. The HTTP01 challenge requires that your load balancer be reachable from the internet via HTTP.

Note: With the HTTP01 challenge type, you provision a certificate for each service.

To enable automatic TLS certificate provisioning using a HTTP01 challenge, do the following:

  1. If you are installing CNRs as part of TAP, then a ClusterIssuer must have been already created for you. Check its status like so:
    kubectl get ClusterIssuer
    

    Look for a ClusterIssuer named tap-ingress-selfsigned. Its status should be READY True.

  2. (Optional) Create a cert-manager Issuer or ClusterIssuer for the HTTP01 challenge. See Issuer in the cert-manager documentation. The following example creates a ClusterIssuer using the Let’s Encrypt Certificate Authority. See Let’s Encrypt.

    Note: If you are following this guide just to test things out, you may want to set spec.acme.server to https://acme-staging-v02.api.letsencrypt.org/directory. This is the staging url, which will generate self-signed certs. It can be useful for testing without worrying about hitting quotas for your actual domain.

    To use a ClusterIssuer for the HTTP01 challenge, run:

    kubectl apply -f - <<EOF
    apiVersion: cert-manager.io/v1
    kind: ClusterIssuer
    metadata:
      name: letsencrypt-http01-issuer
    spec:
      acme:
        privateKeySecretRef:
          name: letsencrypt
        server: https://acme-v02.api.letsencrypt.org/directory
        solvers:
        - http01:
            ingress:
              class: contour
    EOF
    
  3. (Optional) To validate that your ClusterIssuer was created successfully, run:

    kubectl get clusterissuer letsencrypt-http01-issuer --output yaml
    
  4. If you are doing this as part of TAP, set up your tap-values with shared.ingress_issuer to tap-ingress-selfsigned. If you decided to create your own ClusterIssuer then set shared.ingress_issuer to the name of your ClusterIssuer you created. For instance: shared.ingress_issuer: letsencrypt-http01-issuer.

    shared:
     ingress_issuer: tap-ingress-selfsigned
    
    1. Alternatively, if you are installing CNRs as a standalone component, set the ingress_issuer to your ClusterIssuer name. For instance:
      ingress_issuer: tap-ingress-selfsigned
      
    2. If you set the shared.ingress_issuer value then this value will be copied over to ingress_issuer CNRs value automatically.
  5. By default, this will also configure Knative to redirect http requests to https. You may override this and stop traffic from getting redirected with the CNR property https_redirection set to false.

  6. Verify that your automatic TLS certificate instance is configured correctly by deploying a sample app.

    Deploy the sample app using the kn CLI. Run:

    kn service create hello-yeti -n ${WORKLOAD_NAMESPACE} \
      --image projects.registry.vmware.com/tanzu_serverless/hello-yeti@sha256:17d640edc48776cfc604a14fbabf1b4f88443acc580052eef3a753751ee31652 --env TARGET='hello-yeti'
    

    If you are verifying on Tanzu Mission Control or vSphere 7.0 with Tanzu, then add --user 1001 to the command above to run it as a non-root user.

    When you do kubectl get ksvc -n ${WORKLOAD_NAMESPACE} you should see something like this:

    NAME        URL                                                        LATESTCREATED     LATESTREADY      READY   REASON
    hello-yeti  https://hello-yeti.{WORKLOAD_NAMESPACE}.{custom-domain}    hello-yeti-00001  hello-yeti-00001 True    
    
    

    Note that the URL will be https in this case.

Provisioning certificates per namespace (wildcard certificates)

The DNS01 challenge validates that you control your domain’s DNS by accessing and updating your domain’s TXT record. You need to provide a cert-manager with your DNS API credentials. For a list of DNS01 providers supported for the ACME Issuer, see the cert-manager documentation.

Note

: Provisioning a certificate per namespace only works with DNS-01 challenge. This component cannot be used with HTTP-01 challenge.

: By default TAP does not come with a DNS-01 challenge type ClusterIssuer. If you want to use this feature you need to create one on your own.

To enable automatic TLS certificate provisioning using a DNS01 challenge, do the following:

  1. Set up credentials for cert-manager to access your DNS records. For information about setting up credentials for your ACME Issuer supported DNS provider, see Supported DNS01 providers in the cert-manager documentation. In the next step, you create an Issuer on cert-manager with the configuration you set up.

  2. Create a cert-manager Issuer or ClusterIssuer for DNS01 challenge on the cert-manager Issuer you set up in the previous step. The following example uses Let’s Encrypt and Google Cloud DNS. For information about other DNS providers supported by cert-manager, see the cert-manager documentation. The Issuer assumes that your Kubernetes secret holds credentials for the service account created.

    Note: If you are following this guide just to test things out, you may want to set spec.acme.server to https://acme-staging-v02.api.letsencrypt.org/directory. This is the staging url, which will generate self-signed certs. It can be useful for testing without worrying about hitting quotas for your actual domain.

    Run the following command to apply the ClusterIssuer:

    kubectl apply --filename - <<EOF
    apiVersion: cert-manager.io/v1
    kind: ClusterIssuer
    metadata:
      name: letsencrypt-dns-issuer
    spec:
      acme:
        server: https://acme-v02.api.letsencrypt.org/directory
        # This will register an issuer with LetsEncrypt.
        email: MY-EMAIL
        privateKeySecretRef:
          # Set privateKeySecretRef to any unused secret name.
          name: letsencrypt-dns-issuer
        solvers:
        - dns01:
            cloudDNS:
              project: $PROJECT_ID
              # Set this to the secret that we publish our service account key
              # in the previous step.
              serviceAccountSecretRef:
                name: cloud-dns-key
                key: key.json
    EOF
    

    Where MY-EMAIL is your email address.

  3. To verify that your ClusterIssuer is created successfully, run:

    kubectl get clusterissuer letsencrypt-dns-issuer --output yaml
    
  4. If you are doing this as part of TAP, set up your tap-values with shared.ingress_issuer to letsencrypt-dns-issuer.

    shared:
     ingress_issuer: letsencrypt-dns-issuer
    
    1. Alternatively, if you are installing CNRs as a standalone component, set the ingress_issuer to your ClusterIssuer name. For instance:
      ingress_issuer: letsencrypt-dns-issuer
      
    2. If you set the shared.ingress_issuer value then this value will be copied over to ingress_issuer CNRs value automatically.
  5. By default, this will also configure Knative to redirect http requests to https. You may override this and stop traffic from getting redirected with the CNR property https_redirection set to false..

  6. The per-namespace certificate manager uses namespace labels to select which namespaces should have a certificate provisioned. For more details on namespace selectors, see the Kubernetes documentation.

    To enable certificates for all namespaces except those with a particular name set the property namespace_selector to:

    namespace_selector: |
     matchExpressions:
     - key: "kubernetes.io/metadata.name"
       operator: "NotIn"
       values: ["tap-install", "kube-system", "kube-public", "kube-node-lease", "kapp-controller", "kapp-controller-packaging-global", "knative-serving", "secretgen-controller", "tanzu-system-ingress", "cert-manager"]
    

    With the above configuration, all namespaces that meet the condition will have their own TLS certificate provisioned.

  7. When you apply this configuration you will see a Certificate created in every namespace that matches the previous condition. Something like this:
    kubectl get certificate -A
    NAMESPACE              NAME                         READY   SECRET                       AGE
    default                default.{custom-domain}      True    default.{custom-domain}      60s
    dev-ns                 dev-ns.{custom-domain}       True    dev-ns.{custom-domain}       2m
    
  8. Verify that your automatic TLS certificate instance is configured correctly by deploying a sample app.

    Deploy the sample app using the kn CLI. Run:

    kn service create hello-yeti -n ${WORKLOAD_NAMESPACE} \
      --image projects.registry.vmware.com/tanzu_serverless/hello-yeti@sha256:17d640edc48776cfc604a14fbabf1b4f88443acc580052eef3a753751ee31652 --env TARGET='hello-yeti'
    

    If you are verifying on Tanzu Mission Control or vSphere 7.0 with Tanzu, then add --user 1001 to the command above to run it as a non-root user.

    When you do kubectl get ksvc -n ${WORKLOAD_NAMESPACE} you should see something like this:

    NAME        URL                                                        LATESTCREATED     LATESTREADY      READY   REASON
    hello-yeti  https://hello-yeti.{WORKLOAD_NAMESPACE}.{custom-domain}    hello-yeti-00001  hello-yeti-00001 True    
    
    

    Note that the URL will be https in this case.

Disabling Automatic TLS Certificate Provisioning

You can disable automatic TLS provisioning by setting shared.ingress_issuer or cnrs.ingress_issuer property inside the tap-values.yaml file to an empty string.

For example:

shared:
  ingress_issuer: ""

or

cnrs:
  ingress_issuer: ""

The cnrs.ingress_issuer property takes precedance over shared.ingress_issuer. Once auto TLS is disabled, the existing Knative services will be assigned an http endpoint instead of https. Any new service will also be created with an http endpoint.

Note: Removal of the ingress_issuer property instead of setting it to empty string will still apply a default ingress_issuer provided by TAP and will not disable auto TLS.

check-circle-line exclamation-circle-line close-line
Scroll to top icon