TLS certificates
Use TLS certificates with your managed DNS service
Most ingress controllers support TLS termination in-cluster.
For that, they need access to the TLS Certificate and Private Key.
By default, the ingress
Resource Definition resource will reference a tls-cert
resource with the same Resource ID as the dns
it is routing from.
In order to satisfy that, the simplest thing to do is to create a tls-cert
Resource Definition with the same matching criteria as that for the DNS resource definition.
Static TLS certificates
If you have a static wildcard certificate that you want to use, it can be injected by using the humanitec/template
driver.
You will need a template defining the Secret manifest that will contain the certificate and also specify the secret name it will be injected with.
The following examples assume that you have a wildcard certificate for *.example.com
and that you want to inject it into the tls-cert
resource with the same ID as the dns
resource.
Init template
The init template is used to generate the tlsSecretName
field that will be used by the ingress
resource to reference the tls-cert
resource.
tlsSecretName: {{ .id }}-tls
Manifests template
The manifest’s template is used to generate the Secret manifest that will be injected into the cluster.
tls_secret.yaml:
location: namespace
data:
apiVersion: v1
kind: Secret
type: kubernetes.io/tls
metadata:
name: {{ .init.tlsSecretName }}
data:
tls.crt: {{ .outputs.secrets.tls_crt | b64enc }}
tls.key: {{ .outputs.secrets.tls_key | b64enc }}
Values template
The values template is used to generate the tls-cert
resource definition.
tls_secret_name: {{ .init.tlsSecretName }}
Secrets template
The secret’s template is used to generate the actual certificate and private key.
tls_crt: |
-----BEGIN CERTIFICATE-----
MIIDITCCAWiqrIdx2rPPn+G+gKO7SBH9UynjDKgpSela3+XnaVXMP9sbdpE60LEJ
...
ojSzdq6OvLABJKxE6N0ukQPiW8NXQvga9ltnoraxZ9dhAaYvmA==
-----END CERTIFICATE-----
tls_key: |
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC2jud0ozO5qacH
...
ufjZCQaXMLwfVgmhgYr/62jV7YFXFF==
-----END PRIVATE KEY-----
Resolving TLS at the load balancer
It is also common to let cloud providers manage certificates at the edge, for example at the Load Balancer.
In this case, no tls-cert
resource is needed in the cluster. Instead, the ingress
resource must be configured not to do TLS termination.
If you are using the humanitec/ingress
driver, you can simply set the no_tls
field to true
.
Dynamic TLS certificates with Cert-Manager
Cert-Manager allows for dynamic TLS certification management. After the installation of Cert-Manager to a Kubernetes cluster, it can be configured using custom resource definitions like clusterIssuer and certificate to request, renew and manage TLS certificates.
Example scenario
Let’s assume we want to use a wildcard certificate like *.my-test-domain.com
for dynamic preview environments. Each environment will be exposed under a different subdomain like preview-myapp-dev.my-test-domain.com
or preview-myapp-test.my-test-domain.com
.
Prerequisites
- A DNS record for
*.my-test-domain.com
pointing to the load balancer IP of the ingress controller in the cluster. - Cert-manager is installed in the cluster.
- Setup of a clusterIssuer or issuer custom resource definition enabling cert-manager to issue certificates for
*.my-test-domain.com
and its sub domains.
Create a DNS based on a sub domain template
Creating a DNS resource definition with the wildcard-dns driver allows us to use a template for the DNS subdomain.
dns-template.yaml
(view on GitHub)
:
apiVersion: entity.humanitec.io/v1b1
kind: Definition
metadata:
id: dns-template
entity:
name: dns-template
type: dns
driver_type: humanitec/dns-wildcard
driver_inputs:
values:
domain: "my-domain.com"
template: '{{ index (splitList "." "${context.res.id}") 1 }}-${context.env.id}-${context.app.id}'
provision:
ingress:
is_dependent: false
criteria:
- {}
Based on the placeholder variables for app id and environment id, the template for the host name preview-${context.app.id}-${context.env.id}.my-test-domain.com
will for example render into preview-myapp-dev.my-test-domain.com
.
Create a certificate CRD
Using the Template driver and the tls-cert Resource Type we can configure cert-manager dynamically for each Environment to create individually managed TLS certificates.
certificate-crd.yaml
(view on GitHub)
:
# This Resource Definition creates a certificate custom resource definition,
# which will instruct cert-manager to create a TLS certificate
apiVersion: entity.humanitec.io/v1b1
kind: Definition
metadata:
id: certificate-crd
entity:
driver_type: humanitec/template
name: certificate-crd
type: tls-cert
criteria:
- class: default
driver_inputs:
values:
templates:
init: |
tlsSecretName: {{ .id }}-tls
hostName: ${resources.dns.outputs.host}
certificateName: {{ .id }}-cert
manifests: |
certificate-crd.yml:
data:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: {{ .init.certificateName }}
spec:
secretName: {{ .init.tlsSecretName }}
duration: 2160h # 90d
renewBefore: 720h # 30d
isCA: false
privateKey:
algorithm: RSA
encoding: PKCS1
size: 2048
usages:
- server auth
- client auth
dnsNames:
- {{ .init.hostName | toString | toRawJson }}
# The name of the issuerRef must point to the issuer / clusterIssuer in your cluster
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
location: namespace
outputs: |
tls_secret_name: {{ .init.tlsSecretName }}
This tls-cert resource definition will create a certificate custom resource definition in the cluster instructing cert-manager to create a tls-secret. For this it will take the host name from the dns resource ${resources.dns.outputs.host}
as an input for the certificate request. As an output it will provide the name of the tls-secrets which will be used in the ingress resource definition as an input. For custom use cases it can be referred to via ${resources.tls-cert.outputs.tls_secret_name}
.
Conclusion
With both in place,
- the resource definition for the DNS template and
- the resource definition for the tls-cert creating the certificate CRD,
we will have a valid TLS certificate with each environment exposed under a different subdomain.
These TLS certificates will be valid for 3 months and cert-manager will renew them once they are valid for less than 30 days, depending on the configuration in the certificate CRD. The creation of the resources will happen with the deployment of the environment.