{"id":36202952,"url":"https://github.com/stackitcloud/stackit-cert-manager-webhook","last_synced_at":"2026-04-29T09:01:13.920Z","repository":{"id":342052791,"uuid":"681499534","full_name":"stackitcloud/stackit-cert-manager-webhook","owner":"stackitcloud","description":"A webhook integration for Cert Manager that enables STACKIT DNS usage via its API as a DNS01 ACME Issuer. This repository provides Helm-based deployment, operational guidance for multiple Issuer configurations, and a comprehensive testing suite.","archived":false,"fork":false,"pushed_at":"2026-04-27T13:49:54.000Z","size":531,"stargazers_count":13,"open_issues_count":7,"forks_count":10,"subscribers_count":4,"default_branch":"main","last_synced_at":"2026-04-27T15:31:20.645Z","etag":null,"topics":["cert-manager","cert-manager-webhook","clouddns","dns","dns-provider","kubernetes","stackit","stackit-cloud","webhook"],"latest_commit_sha":null,"homepage":"https://www.stackit.de","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stackitcloud.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-08-22T06:39:21.000Z","updated_at":"2026-04-27T13:50:23.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/stackitcloud/stackit-cert-manager-webhook","commit_stats":null,"previous_names":["stackitcloud/stackit-cert-manager-webhook"],"tags_count":33,"template":false,"template_full_name":null,"purl":"pkg:github/stackitcloud/stackit-cert-manager-webhook","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stackitcloud%2Fstackit-cert-manager-webhook","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stackitcloud%2Fstackit-cert-manager-webhook/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stackitcloud%2Fstackit-cert-manager-webhook/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stackitcloud%2Fstackit-cert-manager-webhook/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stackitcloud","download_url":"https://codeload.github.com/stackitcloud/stackit-cert-manager-webhook/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stackitcloud%2Fstackit-cert-manager-webhook/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32418173,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-29T06:29:02.080Z","status":"ssl_error","status_checked_at":"2026-04-29T06:29:00.631Z","response_time":110,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cert-manager","cert-manager-webhook","clouddns","dns","dns-provider","kubernetes","stackit","stackit-cloud","webhook"],"created_at":"2026-01-11T03:39:04.978Z","updated_at":"2026-04-29T09:01:13.913Z","avatar_url":"https://github.com/stackitcloud.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# STACKIT Webhook Integration for Cert Manager\n\n[![GoTemplate](https://img.shields.io/badge/go/template-black?logo=go)](https://github.com/golang-standards/project-layout)\n[![Go](https://img.shields.io/badge/go-1.22.0-blue?logo=go)](https://golang.org/)\n[![Helm](https://img.shields.io/badge/helm-3.12.3-blue?logo=helm)](https://helm.sh/)\n[![Kubernetes](https://img.shields.io/badge/kubernetes-1.30.2-blue?logo=kubernetes)](https://kubernetes.io/)\n[![Cert Manager](https://img.shields.io/badge/cert--manager-1.15.2-blue?logo=cert-manager)](https://cert-manager.io/)\n[![Releases](https://img.shields.io/github/v/release/stackitcloud/stackit-cert-manager-webhook?include_prereleases)](https://github.com/stackitcloud/stackit-cert-manager-webhook/releases)\n[![CI](https://github.com/stackitcloud/stackit-cert-manager-webhook/actions/workflows/main.yml/badge.svg)](https://github.com/stackitcloud/stackit-cert-manager-webhook/actions/workflows/main.yml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/stackitcloud/stackit-cert-manager-webhook)](https://goreportcard.com/report/github.com/stackitcloud/stackit-cert-manager-webhook)\n\nFacilitate a webhook integration for leveraging the STACKIT DNS alongside\nits [API](https://docs.api.stackit.cloud/documentation/dns/version/v1) to act as a DNS01\nACME Issuer with [cert-manager](https://cert-manager.io/docs/).\n\n## Installation\n\n```bash\nhelm repo add stackit-cert-manager-webhook https://stackitcloud.github.io/stackit-cert-manager-webhook\nhelm install stackit-cert-manager-webhook --namespace cert-manager stackit-cert-manager-webhook/stackit-cert-manager-webhook\n```\n\n## Usage\n\n1. ***Initiation of STACKIT Service Account Secret:***\n    ```bash\n    kubectl create secret generic stackit-sa-authentication \\\n      -n cert-manager \\\n      --from-literal=sa.json='{\n      \"id\": \"4e1fe486-b463-4bcd-9210-288854268e34\",\n      \"publicKey\": \"-----BEGIN PUBLIC KEY-----\\nPUBLIC_KEY\\n-----END PUBLIC KEY-----\",\n      \"createdAt\": \"2024-04-02T13:12:17.678+00:00\",\n      \"validUntil\": \"2024-04-15T22:00:00.000+00:00\",\n      \"keyType\": \"USER_MANAGED\",\n      \"keyOrigin\": \"GENERATED\",\n      \"keyAlgorithm\": \"RSA_2048\",\n      \"active\": true,\n      \"credentials\": {\n        \"kid\": \"kid\",\n        \"iss\": \"iss\",\n        \"sub\": \"sub\",\n        \"aud\": \"aud\",\n        \"privateKey\": \"-----BEGIN PRIVATE KEY-----\\nPRIVATE-KEY==\\n-----END PRIVATE KEY-----\"\n      }\n    }'\n    ```\n   You now need to adjust the deployment via helm to use the secret:\n    ```bash\n    helm upgrade stackit-cert-manager-webhook \\\n      --namespace cert-manager \\\n      stackit-cert-manager-webhook/stackit-cert-manager-webhook \\\n     --set stackitSaAuthentication.enabled=true\n    ```\n\n2. ***Configuration of ClusterIssuer/Issuer:***   \n   For scenarios wherein zones and record sets are encapsulated within a singular project, utilize a ClusterIssuer:\n    ```yaml\n    apiVersion: cert-manager.io/v1\n    kind: ClusterIssuer\n    metadata:\n      name: letsencrypt-prod\n    spec:\n      acme:\n        server: https://acme-v02.api.letsencrypt.org/directory\n        email: example@example.com # Replace this with your email address\n        privateKeySecretRef:\n          name: letsencrypt-prod\n        solvers:\n        - dns01:\n            webhook:\n              solverName: stackit\n              groupName: acme.stackit.de\n              config:\n                projectId: \u003cSTACKIT PROJECT ID\u003e\n    ```\n\n   For diverse project architectures where zones are spread across varying projects, use an Issuer (namespaces are separate):\n    ```yaml\n    apiVersion: cert-manager.io/v1\n    kind: Issuer\n    metadata:\n      name: letsencrypt-prod\n      namespace: default\n    spec:\n      acme:\n        server: https://acme-v02.api.letsencrypt.org/directory\n        email: example@example.com # Replace this with your email address\n        privateKeySecretRef:\n          name: letsencrypt-prod\n        solvers:\n        - dns01:\n            webhook:\n              solverName: stackit\n              groupName: acme.stackit.de\n              config:\n                projectId: \u003cSTACKIT PROJECT ID\u003e\n    ```\n   *Note on service accounts and namespaces:*\n   - Issuer-per-namespace (recommended for isolation): create a STACKIT service-account key (sa.json) for each STACKIT project you need to manage and place that key in a Kubernetes Secret in the same namespace as the Issuer. This means one sa.json (one SA key) per Issuer/namespace when the Issuers target different STACKIT projects.\n     Example (create a secret in the Issuer namespace):\n     ```bash\n     kubectl create secret generic stackit-sa-authentication \\\n       -n \u003cissuer-namespace\u003e \\\n       --from-literal=sa.json='{\"id\":\"...\",\"credentials\":{...}}'\n     ```\n     Ensure the webhook can read the secret in that namespace (create the secret where the Issuer lives).\n   - Alternative (single SA key for multiple projects): you can grant the service account broader permissions at folder or organization level so one sa.json can manage zones across multiple projects. This is more convenient but grants wider access — evaluate security and follow least-privilege principles.\n   - Tradeoffs:\n     - Per-namespace/per-project SA keys: better isolation and least privilege, easier to rotate keys per project.\n     - Folder/org-level SA key: lower operational overhead (single key), but larger blast radius if compromised.\n\n3. ***Demonstration of Ingress Integration with Wildcard SSL/TLS Certificate Generation***   \n   Given the preceding configuration, it is possible to exploit the capabilities of the Issuer or ClusterIssuer to\n   dynamically produce wildcard SSL/TLS certificates in the following manner:\n    ```yaml\n    apiVersion: cert-manager.io/v1\n    kind: Certificate\n    metadata:\n      name: wildcard-example\n      namespace: default\n    spec:\n      secretName: wildcard-example-tls\n      issuerRef:\n        name: letsencrypt-prod\n        kind: Issuer\n      commonName: '*.example.runs.onstackit.cloud' # project must be the owner of this zone\n      duration: 8760h0m0s\n      dnsNames:\n        - example.runs.onstackit.cloud\n        - '*.example.runs.onstackit.cloud'\n    ---\n    apiVersion: networking.k8s.io/v1\n    kind: Ingress\n    metadata:\n      name: app-ingress\n      namespace: default\n      annotations:\n        ingress.kubernetes.io/rewrite-target: /\n        kubernetes.io/ingress.class: \"nginx\"\n    spec:\n      rules:\n        - host: \"app.example.runs.onstackit.cloud\"\n          http:\n            paths:\n              - path: /\n                pathType: Prefix\n                backend:\n                  service:\n                    name: webapp\n                    port:\n                      number: 80\n      tls:\n        - hosts:\n            - \"app.example.runs.onstackit.cloud\"\n          secretName: wildcard-example-tls\n    ```\n\n## Config Options\n\nThe following table delineates the configuration options available for the STACKIT Cert Manager Webhook:\n\n```yaml\napiVersion: cert-manager.io/v1\nkind: Issuer\nmetadata:\n  name: letsencrypt-prod\n  namespace: default\nspec:\n  acme:\n    server: https://acme-v02.api.letsencrypt.org/directory\n    email: example@example.com # Replace this with your email address\n    privateKeySecretRef:\n      name: letsencrypt-prod\n    solvers:\n      - dns01:\n        webhook:\n          solverName: stackit\n          groupName: acme.stackit.de\n          config:\n            projectId: string\n            apiBasePath: string\n            serviceAccountKeyPath: string\n            serviceAccountBaseUrl: string\n            acmeTxtRecordTTL: int64\n```\n\n- projectId: The unique identifier for the STACKIT project.\n- apiBasePath: The base path for the STACKIT DNS API. (Default: https://dns.api.stackit.cloud)\n- serviceAccountKeyPath: The path to the service account key file. The file must be mounted into the container.\n- serviceAccountBaseUrl: The base URL for the STACKIT service account API. (Default: https://service-account.api.stackit.cloud/token)\n- acmeTxtRecordTTL: The TTL for the ACME TXT record. (Default: 600)\n\n## Test Procedures\n\n- Unit Testing:\n    ```bash\n    make test\n    ```\n\n- Unit Testing with Coverage Analysis:\n    ```bash\n    make coverage\n    ```\n\n- Linting:\n    ```bash\n    make lint\n    ```\n\n- End-to-End Testing Workflow:  \n  Follow the comprehensive guide available [here](e2e_test/README.md).\n\n## Release Process Overview\n\nOur release pipeline leverages goreleaser for the generation and publishing of release assets.\nThis sophisticated approach ensures the streamlined delivery of:\n\n- Pre-compiled binaries tailored for various platforms.\n- Docker images optimized for production readiness.\n\nHowever, one should be cognizant of the fact that goreleaser doesn't inherently support Helm chart distributions\nas part of its conventional workflow. Historically, the incorporation of Helm charts into our releases demanded manual\nintervention. Post the foundational release generation via goreleaser, the Helm chart was affixed as an asset through\nmanual processes.    \nFor those interested in the Helm chart creation mechanics, the process was facilitated via the command:\n\n```bash\nhelm package deploy/stackit\n```\n\nTo release a new version of the Helm chart, one must meticulously update the appVersion and (chart)version delineation in the\n[Chart.yaml](./deploy/stackit/Chart.yaml). Post this modification, initiate a new release to encompass these changes.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstackitcloud%2Fstackit-cert-manager-webhook","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstackitcloud%2Fstackit-cert-manager-webhook","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstackitcloud%2Fstackit-cert-manager-webhook/lists"}