feat: complete implementation and add build workflow

This commit is contained in:
Marc Singer 2026-02-15 20:23:29 +01:00
parent 398194366b
commit 23523d8ab2
4 changed files with 89 additions and 1 deletions

43
.github/workflows/docker.yml vendored Normal file
View file

@ -0,0 +1,43 @@
name: 'Build docker image'
on:
push:
branches:
- main
jobs:
build:
name: "Build"
runs-on: ubuntu-latest
steps:
- name: "Checkout sources"
uses: actions/checkout@v6
- name: "Login to docker registry"
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: "Set version container labels"
id: meta
uses: docker/metadata-action@v5
with:
images: |
ghcr.io/pr0ton11/cert-manager-desec-webhook
tags: |
type=raw,value=latest,enable={{is_default_branch}}
type=sha
labels: |
maintainer=proton11@github.com
org.opencontainers.image.title=cert-manager-deSEC-webhook
org.opencontainers.image.description=An independently maintained deSEC DNS validation webhook for cert-manager
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: "Build docker image"
uses: docker/build-push-action@v6
with:
context: .
push: true
platforms: linux/amd64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

3
go.mod
View file

@ -57,6 +57,7 @@ require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect
github.com/miekg/dns v1.1.68 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
@ -88,6 +89,7 @@ require (
go.yaml.in/yaml/v3 v3.0.4 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/crypto v0.48.0 // indirect golang.org/x/crypto v0.48.0 // indirect
golang.org/x/exp v0.0.0-20260212183809-81e46e3db34a // indirect golang.org/x/exp v0.0.0-20260212183809-81e46e3db34a // indirect
golang.org/x/mod v0.33.0 // indirect
golang.org/x/net v0.50.0 // indirect golang.org/x/net v0.50.0 // indirect
golang.org/x/oauth2 v0.35.0 // indirect golang.org/x/oauth2 v0.35.0 // indirect
golang.org/x/sync v0.19.0 // indirect golang.org/x/sync v0.19.0 // indirect
@ -95,6 +97,7 @@ require (
golang.org/x/term v0.40.0 // indirect golang.org/x/term v0.40.0 // indirect
golang.org/x/text v0.34.0 // indirect golang.org/x/text v0.34.0 // indirect
golang.org/x/time v0.14.0 // indirect golang.org/x/time v0.14.0 // indirect
golang.org/x/tools v0.42.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 // indirect

2
go.sum
View file

@ -142,6 +142,8 @@ github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxec
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/miekg/dns v1.1.68 h1:jsSRkNozw7G/mnmXULynzMNIsgY2dHC8LO6U6Ij2JEA=
github.com/miekg/dns v1.1.68/go.mod h1:fujopn7TB3Pu3JM69XaawiU0wqjpL9/8xGop5UrTPps=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=

View file

@ -4,9 +4,11 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"strings"
acme "github.com/cert-manager/cert-manager/pkg/acme/webhook/apis/acme/v1alpha1" acme "github.com/cert-manager/cert-manager/pkg/acme/webhook/apis/acme/v1alpha1"
v1 "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" v1 "github.com/cert-manager/cert-manager/pkg/apis/meta/v1"
"github.com/cert-manager/cert-manager/pkg/issuer/acme/dns/util"
"github.com/nrdcg/desec" "github.com/nrdcg/desec"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -71,6 +73,29 @@ func (s *DeSECDNSProviderSolver) Present(req *acme.ChallengeRequest) error {
if err != nil { if err != nil {
return err return err
} }
zone := util.UnFqdn(req.ResolvedZone)
fqdn := util.UnFqdn(req.ResolvedFQDN)
// Cut the zone from the fqdn to retrieve the subdomain
subdomain := util.UnFqdn(strings.Replace(fqdn, zone, "", 0))
// Check if zone is managed in deSEC
domain, err := apiClient.Domains.Get(context.Background(), zone)
if err != nil {
return fmt.Errorf("domain %s could not be retrieved from deSEC API: %w", zone, err)
}
// Create the TXT record to be created
recordSet := desec.RRSet{
Domain: domain.Name,
SubName: subdomain,
Records: []string{fmt.Sprintf("\"%s\"", req.Key)},
Type: "TXT",
TTL: 3600,
}
// Create the TXT record
_, err = apiClient.Records.Create(context.Background(), recordSet)
if err != nil {
return fmt.Errorf("DNS record %s creation failed: %w", fqdn, err)
}
// Return no error
return nil return nil
} }
@ -81,6 +106,21 @@ func (s *DeSECDNSProviderSolver) CleanUp(req *acme.ChallengeRequest) error {
if err != nil { if err != nil {
return err return err
} }
zone := util.UnFqdn(req.ResolvedZone)
fqdn := util.UnFqdn(req.ResolvedFQDN)
// Cut the zone from the fqdn to retrieve the subdomain
subdomain := util.UnFqdn(strings.Replace(fqdn, zone, "", 0))
// Check if zone is managed in deSEC
domain, err := apiClient.Domains.Get(context.Background(), zone)
if err != nil {
return fmt.Errorf("domain %s could not be retrieved from deSEC API: %w", zone, err)
}
// Delete the TXT record
err = apiClient.Records.Delete(context.Background(), domain.Name, subdomain, "TXT")
if err != nil {
return fmt.Errorf("DNS record %s deletion failed: %w", fqdn, err)
}
// Return no error
return nil return nil
} }
@ -93,6 +133,6 @@ func (s *DeSECDNSProviderSolver) Initialize(kubeClientConfig *rest.Config, stopC
} }
// Assign the k8s client to the solver // Assign the k8s client to the solver
s.k8s = k8s s.k8s = k8s
// Return no error
return nil return nil
} }