stackit-cert-manager-webhook

STACKIT Webhook Integration for Cert Manager

GoTemplate Go Helm Kubernetes Cert Manager Releases CI Go Report Card

Facilitate a webhook integration for leveraging the STACKIT DNS alongside its API to act as a DNS01 ACME Issuer with cert-manager.

Installation

helm repo add stackit-cert-manager-webhook https://stackitcloud.github.io/stackit-cert-manager-webhook
helm install stackit-cert-manager-webhook --namespace cert-manager stackit-cert-manager-webhook/stackit-cert-manager-webhook

Usage

  1. Initiation of STACKIT Authentication Token Secret:
     kubectl create secret generic stackit-cert-manager-webhook \
       --namespace=cert-manager \
       --from-literal=auth-token=<STACKIT AUTH TOKEN>
    

    Or alternatively we can utilize the STACKIT service account path authentication:

     kubectl create secret generic stackit-sa-authentication -n cert-manager \
         --from-literal=sa.json='{
       "id": "4e1fe486-b463-4bcd-9210-288854268e34",
       "publicKey": "-----BEGIN PUBLIC KEY-----\nPUBLIC_KEY\n-----END PUBLIC KEY-----",
       "createdAt": "2024-04-02T13:12:17.678+00:00",
       "validUntil": "2024-04-15T22:00:00.000+00:00",
       "keyType": "USER_MANAGED",
       "keyOrigin": "GENERATED",
       "keyAlgorithm": "RSA_2048",
       "active": true,
       "credentials": {
         "kid": "kid",
         "iss": "iss",
         "sub": "sub",
         "aud": "aud",
         "privateKey": "-----BEGIN PRIVATE KEY-----\nPRIVATE-KEY==\n-----END PRIVATE KEY-----"
       }
     }'
    

    You now need to adjust the deployment via helm to use the secret:

     helm upgrade stackit-cert-manager-webhook \
       --namespace cert-manager \
       stackit-cert-manager-webhook/stackit-cert-manager-webhook \
      --set stackitSaAuthentication.enabled=true
    
  2. Configuration of ClusterIssuer/Issuer:
    For scenarios wherein zones and record sets are encapsulated within a singular project, utilize a ClusterIssuer:
     apiVersion: cert-manager.io/v1
     kind: ClusterIssuer
     metadata:
       name: letsencrypt-prod
     spec:
       acme:
         server: https://acme-v02.api.letsencrypt.org/directory
         email: example@example.com # Replace this with your email address
         privateKeySecretRef:
           name: letsencrypt-prod
         solvers:
         - dns01:
             webhook:
               solverName: stackit
               groupName: acme.stackit.de
               config:
                 projectId: <STACKIT PROJECT ID>
    

    For diverse project architectures where zones are spread across varying projects, necessitating distinct authentication tokens per project, the Issuer configuration becomes pertinent. This approach inherently tethers namespaces to individual projects.

     kubectl create secret generic stackit-cert-manager-webhook \
       --namespace=default \
       --from-literal=auth-token=<STACKIT AUTH TOKEN>
    
     apiVersion: cert-manager.io/v1
     kind: Issuer
     metadata:
       name: letsencrypt-prod
       namespace: default
     spec:
       acme:
         server: https://acme-v02.api.letsencrypt.org/directory
         email: example@example.com # Replace this with your email address
         privateKeySecretRef:
           name: letsencrypt-prod
         solvers:
         - dns01:
             webhook:
               solverName: stackit
               groupName: acme.stackit.de
               config:
                 projectId: <STACKIT PROJECT ID>
                 authTokenSecretNamespace: default
    

    Note: Ensure the creation of an authentication token secret within the namespace linked to the issuer. The secret must be vested with permissions to access zones in the stipulated project configuration.

  3. Demonstration of Ingress Integration with Wildcard SSL/TLS Certificate Generation
    Given the preceding configuration, it is possible to exploit the capabilities of the Issuer or ClusterIssuer to dynamically produce wildcard SSL/TLS certificates in the following manner:
     apiVersion: cert-manager.io/v1
     kind: Certificate
     metadata:
       name: wildcard-example
       namespace: default
     spec:
       secretName: wildcard-example-tls
       issuerRef:
         name: letsencrypt-prod
         kind: Issuer
       commonName: '*.example.runs.onstackit.cloud' # project must be the owner of this zone
       duration: 8760h0m0s
       dnsNames:
         - example.runs.onstackit.cloud
         - '*.example.runs.onstackit.cloud'
     ---
     apiVersion: networking.k8s.io/v1
     kind: Ingress
     metadata:
       name: app-ingress
       namespace: default
       annotations:
         ingress.kubernetes.io/rewrite-target: /
         kubernetes.io/ingress.class: "nginx"
     spec:
       rules:
         - host: "app.example.runs.onstackit.cloud"
           http:
             paths:
               - path: /
                 pathType: Prefix
                 backend:
                   service:
                     name: webapp
                     port:
                       number: 80
       tls:
         - hosts:
             - "app.example.runs.onstackit.cloud"
           secretName: wildcard-example-tls
    

Config Options

The following table delineates the configuration options available for the STACKIT Cert Manager Webhook:

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: letsencrypt-prod
  namespace: default
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: example@example.com # Replace this with your email address
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
      - dns01:
        webhook:
          solverName: stackit
          groupName: acme.stackit.de
          config:
            projectId: string
            apiBasePath: string
            authTokenSecretRef: string
            authTokenSecretKey: string
            authTokenSecretNamespace: string
            serviceAccountKeyPath: string
            acmeTxtRecordTTL: int64

Test Procedures

Release Process Overview

Our release pipeline leverages goreleaser for the generation and publishing of release assets. This sophisticated approach ensures the streamlined delivery of:

However, one should be cognizant of the fact that goreleaser doesn’t inherently support Helm chart distributions as part of its conventional workflow. Historically, the incorporation of Helm charts into our releases demanded manual intervention. Post the foundational release generation via goreleaser, the Helm chart was affixed as an asset through manual processes.
For those interested in the Helm chart creation mechanics, the process was facilitated via the command:

helm package deploy/stackit

To release a new version of the Helm chart, one must meticulously update the version delineation in the Chart.yaml. Post this modification, initiate a new release to encompass these changes.