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.
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:
HTTP01 challenges: An internet-reachable cluster.DNS01 challenges: API access to set DNS records.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
HTTP01challenge type, you provision a certificate for each service.
To enable automatic TLS certificate provisioning using a HTTP01 challenge, do the following:
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.
(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.servertohttps://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
(Optional) To validate that your ClusterIssuer was created successfully, run:
kubectl get clusterissuer letsencrypt-http01-issuer --output yaml
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
ingress_issuer to your ClusterIssuer name. For instance: ingress_issuer: tap-ingress-selfsigned
shared.ingress_issuer value then this value will be copied over to ingress_issuer CNRs value automatically.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.
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.
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:
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.
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.servertohttps://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.
To verify that your ClusterIssuer is created successfully, run:
kubectl get clusterissuer letsencrypt-dns-issuer --output yaml
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
ingress_issuer to your ClusterIssuer name. For instance: ingress_issuer: letsencrypt-dns-issuer
shared.ingress_issuer value then this value will be copied over to ingress_issuer CNRs value automatically.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..
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.
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
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.
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.