Certificates

This page describes the two ways provided by the h8lio platform to manage the TLS certificates to secure your ingress routes (https scheme) using:

Traefik

Traefik integrates the TLS certificates management and we are providing a default certificate resolver using LetsEncrypt HTTP-01 Challenge which can be be used in your routes.

🟢 Pros:

  • Simplest solution to secure your routes as it is transparently managed by the Traefik Proxy and the provided default certificate resolver.

🔴 Cons:

  • No much control of your certificates as they are internally managed by Traefik using our default certificate resolver
  • Risk to reached the LetsEncrypt rates limits if you create lot of routes at once or if your route configuration is wrong and the LetsEncrypt challenge fails several times (see Best Practices)
  • the LetsEncrypt HTTP-01 challenge doesn’t allow wildcard certificates

Usage

Here is an example how to use the default certificate resolver within a Traefik IngressRoute. This example also shows you how to redirect the HTTP trafic to the HTTPS entry point using a Middleware:

# http: scheme route redirected to https: scheme.
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: example
spec:
  # http entry point
  entryPoints:
  - http
  # route rules definition
  routes:
  # list of rules
  - kind: Rule
    match: Host(`test.example.com`)
    # redirect middleware
    middlewares:
    - name: https-redirect
      namespace: traefik
    # backend Kubernetes service
    services:
    - name: my-service
      port: 8080
---
# secured route (https scheme) with "default" certificate resolver
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: example-tls
spec:
  # https entry point
  entryPoints:
  - https
  routes:
  - kind: Rule
    match: Host(`test.example.com`)
    # backend Kubernetes service
    services:
      - name: my-service
        port: 8080
  tls:
    # TLS certificate resolver
    certResolver: default

That’s it! Traefik is doing all the certificate generation and renewal processes internally.

the API Group will be changed in Traefik 3+ from traefik.containo.us/v1alpha1 to traefik.io/v1alpha1. You may start to use the new group but pay attention to the CustomResourceDefinition when you retrieve your resources (two IngressRoute definitions).

Best practices

To facilitate the TLS challenge and avoid the LetsEncrypt rate limits you should follow the following recommendations:

  • (required) The backend service has to be up and running and able to answer the LetsEncrypt challenge with a 200 http status response code before to deploy the secured route (you could check your service is running by using kubectl port-forward service...).
  • (mandatory) If you are using your own domain, make sure the routes are redirected to edge.h8l.io (CNAME record to edge.h8l.io or A record to the load balanced IP of edge.h8l.io) and the DNS propagation has been done (LetsEncrypt could perform the HTTP-01 challenge from the US)
  • If your route rules are complex, you can help Traefik to resolve the hosts to challenge by specifying the tls domains
  • You can group your routes in a single IngressRoute and/or in a single match: with Host(`a.b.com`,...,`c.b.com`) to help Traefik to resolve the hosts and limit the number of challenge and

Cert-Manager

The h8lio integrates cert-manager to manage your certificates. It allows to get more control of your certificates and share them with multiple Kubernetes resources.

The cert-manager h8lio integration is quite recent (alpha stage). Every feedback are welcome.

🟢 Pros:

🔴 Cons:

  • More complex to use compare to the integrated Traefik certificate resolver
  • You become the manager of your certificates
  • External management of the DNS-O1 Challenge Provider

For now, we deployed only the OVH Challenge Provider, if you need another supported provider or add your own provider let us know by opening a ticket or by emailed us at hello@h8l.io.

Usage

The following example shows how to create and use a wildcard certificate using cert-manager and LetsEncrypt DNS-O1 challenge on a OVH managed domain.

  1. Create a secret holding the OVH API credentials in the cluster where you want to use the certificate:
apiVersion: v1
kind: Secret
type: Opaque
metadata:
  name: ovh-<domain>-api
data:
  applicationKey: <base64 encoded application key>
  applicationSecret: <base64 encoded application secret>
  consumerKey: <base64 encoded consumer key>

replace the <...> by the value of your choice

you can use sealed-secret if you want to securely store the secret outside of the h8lio Kubernetes Cluster (example, in a Git repository)

  1. Create your cert-manager Issuer using LetsEncrypt and the OVH challenge provider:
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: ovh-<domain>
spec:
  acme:
    # LetsEncrypt production server
    server: "https://acme-v02.api.letsencrypt.org/directory"
    # email or mailing list used for the LetsEncrypt account
    email: <my@email.com>
    # reference to the secret holding your LetsEncrypt account key
    # it will be created by cert-manager if it doesn't exist
    privateKeySecretRef:
      name: "ovh-<domain>-account-key"
    solvers:
      # DNS-01 challenge configuration
      - dns01:
          cnameStrategy: "None"
          # OVH DNS-01 challenge webhook configuration
          webhook:
            solverName: ovh                    # do not change this value
            groupName: acme.h8l.io             # do not change this value
            config:
              # OVH zone
              endpoint: ovh-eu
              # OVH credentials from the secret
              # adapts the name: and key: based of your configuration
              applicationKeyRef:
                name: ovh-<domain>-api
                key: "applicationKey"
              applicationSecretRef:
                name: ovh-<domain>-api
                key: "applicationSecret"
              consumerKeyRef:
                name: ovh-<domain>-api
                key: "consumerKey"

Once the Issuer manifest has been applied to your cluster. You can check the events and status: of the cert-manager.io/v1 Issuer CustomResourceDefinition to validate its configuration and its readiness. It should look like:

status:
  acme:
    lastPrivateKeyHash: yTty...
    lastRegisteredEmail: my@email.com
    uri: https://acme-v02.api.letsencrypt.org/acme/acct/12345...
  conditions:
    - lastTransitionTime: '2023-08-05T13:58:40Z'
      message: The ACME account was registered with the ACME server
      observedGeneration: 2
      reason: ACMEAccountRegistered
      status: 'True'
      type: Ready
  1. Create the cert-manager Certificate’s secret using the previous Issuer which will be used in the IngressRoutes
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: ovh-<domain>
spec:
  # replace with your domain
  # it could be a second level subdomain (ie. "*.sub.domain.com")
  dnsNames:
    - "*.domain.com"
  issuerRef:
    group: cert-manager.io
    kind: Issuer
    name: ovh-<domain>                # the issuer name
  secretName: ovh-<domain>-cert       # the name of the secret which will hold the certificate

Once the Certificate manifest has been applied to your cluster. You can check the events and status: of the cert-manager.io/v1 Certificate CustomResourceDefinition to validate its configuration and its readiness.

This operation could take few seconds while cert-manager is internally managing the creation of all the resources involved in the DNS-01 challenge process to create the secret containing the new Certificate. It should look like:

status:
  conditions:
    - lastTransitionTime: '2023-08-07T07:44:14Z'
      message: Certificate is up to date and has not expired
      observedGeneration: 1
      reason: Ready
      status: 'True'
      type: Ready
  notAfter: '2023-11-05T06:44:12Z'
  notBefore: '2023-08-07T06:44:13Z'
  renewalTime: '2023-10-06T06:44:12Z'
  revision: 1

If the certificate generation process is successful, you should see your ovh-<domain>-cert secret with the two tls file entries:

kind: Secret
apiVersion: v1
metadata:
  name: ovh-<domain>-cert
  annotations:
    # cert-manager annotations
    cert-manager.io/alt-names: ...
    cert-manager.io/certificate-name: ...
    cert-manager.io/common-name: ...
    cert-manager.io/ip-sans: ...
    cert-manager.io/issuer-group: ...
    cert-manager.io/issuer-kind: ...
    cert-manager.io/issuer-name: ...
    cert-manager.io/uri-sans: ...
data:
  tls.crt: >-
    LS0t...    
  tls.key: >-
    LS0t...    
type: kubernetes.io/tls
  1. Use your certificate secret in your Traefik IngressRoutes (as many times you need):
# secured route (https scheme) with your certificate from a cert-manager secret
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: example-tls
spec:
  # https entry point
  entryPoints:
  - https
  routes:
  - kind: Rule
    # rule's match using subdomains of the generated wildcard certificate
    match: Host(`test.domain.com`,`demo.domain.com`)
    # backend Kubernetes service
    services:
      - name: my-service
        port: 8080
  tls:
    # TLS certificate secret reference
    secretName: ovh-<domain>-cert

No LetsEncrypt challenge is done by Traefik when you deploy this secured route as it has already been done and managed by the cert-manager (avoiding also the LetsEncrypt Rate Limits).

*.namespace.h8l.io certificates

If not already present, you may want to create an h8lio-tls secret holding the certificate for the routes *.[domain-cluster].h8l.io:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: h8lio
  namespace: <domain-cluster>
spec:
  dnsNames:
    - "*.<domain-cluster>.h8l.io"
  issuerRef:
    group: cert-manager.io
    kind: ClusterIssuer
    # cluster wide h8l.io issuer using LetsEncrypt
    # ⚠️ works only for the h8l.io subdomains
    name: h8lio-issuer
  # target secret name holding the
  secretName: h8lio-tls

Replace <domain-cluster> with your namespace and apply this manifest. After few seconds (checks the Certificate events/status), the h8lio-tls secret should be generated and can be used in you ingress routes tls: configuration:

apiVersion: traefik.io/v1alpha1
kind: IngressRoute
...
spec:
  entryPoints:
  - https
  routes:
  - ...
  tls:
    secretName: h8lio-tls

Remember to change your pipelines and/or helm chart to uses the new TLS configuration

If you are using the secret name, don’t mix your domain’s routes rules with the h8l.io ones. The generated certificate will only work for the specified h8l.io dnsNames