I don't know what I'm doing

This commit is contained in:
斟酌 鵬兄 2022-03-12 23:35:44 +00:00
parent be0eb944c4
commit c7e83ca6cc
22 changed files with 98 additions and 336 deletions

2
.gitignore vendored
View File

@ -12,7 +12,7 @@
*.out *.out
# Ignore the built binary # Ignore the built binary
cert-manager-webhook-example cert-manager-webhook-freedns
# Make artifacts # Make artifacts
_out _out

View File

@ -35,7 +35,7 @@ build:
.PHONY: rendered-manifest.yaml .PHONY: rendered-manifest.yaml
rendered-manifest.yaml: rendered-manifest.yaml:
helm template \ helm template \
--name example-webhook \ --name freedns-webhook \
--set image.repository=$(IMAGE_NAME) \ --set image.repository=$(IMAGE_NAME) \
--set image.tag=$(IMAGE_TAG) \ --set image.tag=$(IMAGE_TAG) \
deploy/example-webhook > "$(OUT)/rendered-manifest.yaml" deploy/freedns-webhook > "$(OUT)/rendered-manifest.yaml"

View File

@ -1,5 +1,5 @@
apiVersion: v1 apiVersion: v1
appVersion: "1.0" appVersion: "1.0"
description: A Helm chart for Kubernetes description: A Helm chart for Kubernetes
name: example-webhook name: freedns-webhook
version: 0.1.0 version: 0.1.0

View File

@ -2,7 +2,7 @@
{{/* {{/*
Expand the name of the chart. Expand the name of the chart.
*/}} */}}
{{- define "example-webhook.name" -}} {{- define "freedns-webhook.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}} {{- end -}}
@ -11,7 +11,7 @@ Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name. If release name contains chart name it will be used as a full name.
*/}} */}}
{{- define "example-webhook.fullname" -}} {{- define "freedns-webhook.fullname" -}}
{{- if .Values.fullnameOverride -}} {{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}} {{- else -}}
@ -27,22 +27,22 @@ If release name contains chart name it will be used as a full name.
{{/* {{/*
Create chart name and version as used by the chart label. Create chart name and version as used by the chart label.
*/}} */}}
{{- define "example-webhook.chart" -}} {{- define "freedns-webhook.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}} {{- end -}}
{{- define "example-webhook.selfSignedIssuer" -}} {{- define "freedns-webhook.selfSignedIssuer" -}}
{{ printf "%s-selfsign" (include "example-webhook.fullname" .) }} {{ printf "%s-selfsign" (include "freedns-webhook.fullname" .) }}
{{- end -}} {{- end -}}
{{- define "example-webhook.rootCAIssuer" -}} {{- define "freedns-webhook.rootCAIssuer" -}}
{{ printf "%s-ca" (include "example-webhook.fullname" .) }} {{ printf "%s-ca" (include "freedns-webhook.fullname" .) }}
{{- end -}} {{- end -}}
{{- define "example-webhook.rootCACertificate" -}} {{- define "freedns-webhook.rootCACertificate" -}}
{{ printf "%s-ca" (include "example-webhook.fullname" .) }} {{ printf "%s-ca" (include "freedns-webhook.fullname" .) }}
{{- end -}} {{- end -}}
{{- define "example-webhook.servingCertificate" -}} {{- define "freedns-webhook.servingCertificate" -}}
{{ printf "%s-webhook-tls" (include "example-webhook.fullname" .) }} {{ printf "%s-webhook-tls" (include "freedns-webhook.fullname" .) }}
{{- end -}} {{- end -}}

View File

@ -3,17 +3,17 @@ kind: APIService
metadata: metadata:
name: v1alpha1.{{ .Values.groupName }} name: v1alpha1.{{ .Values.groupName }}
labels: labels:
app: {{ include "example-webhook.name" . }} app: {{ include "freedns-webhook.name" . }}
chart: {{ include "example-webhook.chart" . }} chart: {{ include "freedns-webhook.chart" . }}
release: {{ .Release.Name }} release: {{ .Release.Name }}
heritage: {{ .Release.Service }} heritage: {{ .Release.Service }}
annotations: annotations:
cert-manager.io/inject-ca-from: "{{ .Release.Namespace }}/{{ include "example-webhook.servingCertificate" . }}" cert-manager.io/inject-ca-from: "{{ .Release.Namespace }}/{{ include "freedns-webhook.servingCertificate" . }}"
spec: spec:
group: {{ .Values.groupName }} group: {{ .Values.groupName }}
groupPriorityMinimum: 1000 groupPriorityMinimum: 1000
versionPriority: 15 versionPriority: 15
service: service:
name: {{ include "example-webhook.fullname" . }} name: {{ include "freedns-webhook.fullname" . }}
namespace: {{ .Release.Namespace }} namespace: {{ .Release.Namespace }}
version: v1alpha1 version: v1alpha1

View File

@ -1,25 +1,25 @@
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: {{ include "example-webhook.fullname" . }} name: {{ include "freedns-webhook.fullname" . }}
labels: labels:
app: {{ include "example-webhook.name" . }} app: {{ include "freedns-webhook.name" . }}
chart: {{ include "example-webhook.chart" . }} chart: {{ include "freedns-webhook.chart" . }}
release: {{ .Release.Name }} release: {{ .Release.Name }}
heritage: {{ .Release.Service }} heritage: {{ .Release.Service }}
spec: spec:
replicas: {{ .Values.replicaCount }} replicas: {{ .Values.replicaCount }}
selector: selector:
matchLabels: matchLabels:
app: {{ include "example-webhook.name" . }} app: {{ include "freedns-webhook.name" . }}
release: {{ .Release.Name }} release: {{ .Release.Name }}
template: template:
metadata: metadata:
labels: labels:
app: {{ include "example-webhook.name" . }} app: {{ include "freedns-webhook.name" . }}
release: {{ .Release.Name }} release: {{ .Release.Name }}
spec: spec:
serviceAccountName: {{ include "example-webhook.fullname" . }} serviceAccountName: {{ include "freedns-webhook.fullname" . }}
containers: containers:
- name: {{ .Chart.Name }} - name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
@ -53,7 +53,7 @@ spec:
volumes: volumes:
- name: certs - name: certs
secret: secret:
secretName: {{ include "example-webhook.servingCertificate" . }} secretName: {{ include "freedns-webhook.servingCertificate" . }}
{{- with .Values.nodeSelector }} {{- with .Values.nodeSelector }}
nodeSelector: nodeSelector:
{{ toYaml . | indent 8 }} {{ toYaml . | indent 8 }}

View File

@ -4,11 +4,11 @@
apiVersion: cert-manager.io/v1 apiVersion: cert-manager.io/v1
kind: Issuer kind: Issuer
metadata: metadata:
name: {{ include "example-webhook.selfSignedIssuer" . }} name: {{ include "freedns-webhook.selfSignedIssuer" . }}
namespace: {{ .Release.Namespace | quote }} namespace: {{ .Release.Namespace | quote }}
labels: labels:
app: {{ include "example-webhook.name" . }} app: {{ include "freedns-webhook.name" . }}
chart: {{ include "example-webhook.chart" . }} chart: {{ include "freedns-webhook.chart" . }}
release: {{ .Release.Name }} release: {{ .Release.Name }}
heritage: {{ .Release.Service }} heritage: {{ .Release.Service }}
spec: spec:
@ -20,19 +20,19 @@ spec:
apiVersion: cert-manager.io/v1 apiVersion: cert-manager.io/v1
kind: Certificate kind: Certificate
metadata: metadata:
name: {{ include "example-webhook.rootCACertificate" . }} name: {{ include "freedns-webhook.rootCACertificate" . }}
namespace: {{ .Release.Namespace | quote }} namespace: {{ .Release.Namespace | quote }}
labels: labels:
app: {{ include "example-webhook.name" . }} app: {{ include "freedns-webhook.name" . }}
chart: {{ include "example-webhook.chart" . }} chart: {{ include "freedns-webhook.chart" . }}
release: {{ .Release.Name }} release: {{ .Release.Name }}
heritage: {{ .Release.Service }} heritage: {{ .Release.Service }}
spec: spec:
secretName: {{ include "example-webhook.rootCACertificate" . }} secretName: {{ include "freedns-webhook.rootCACertificate" . }}
duration: 43800h # 5y duration: 43800h # 5y
issuerRef: issuerRef:
name: {{ include "example-webhook.selfSignedIssuer" . }} name: {{ include "freedns-webhook.selfSignedIssuer" . }}
commonName: "ca.example-webhook.cert-manager" commonName: "ca.freedns-webhook.cert-manager"
isCA: true isCA: true
--- ---
@ -41,16 +41,16 @@ spec:
apiVersion: cert-manager.io/v1 apiVersion: cert-manager.io/v1
kind: Issuer kind: Issuer
metadata: metadata:
name: {{ include "example-webhook.rootCAIssuer" . }} name: {{ include "freedns-webhook.rootCAIssuer" . }}
namespace: {{ .Release.Namespace | quote }} namespace: {{ .Release.Namespace | quote }}
labels: labels:
app: {{ include "example-webhook.name" . }} app: {{ include "freedns-webhook.name" . }}
chart: {{ include "example-webhook.chart" . }} chart: {{ include "freedns-webhook.chart" . }}
release: {{ .Release.Name }} release: {{ .Release.Name }}
heritage: {{ .Release.Service }} heritage: {{ .Release.Service }}
spec: spec:
ca: ca:
secretName: {{ include "example-webhook.rootCACertificate" . }} secretName: {{ include "freedns-webhook.rootCACertificate" . }}
--- ---
@ -58,19 +58,19 @@ spec:
apiVersion: cert-manager.io/v1 apiVersion: cert-manager.io/v1
kind: Certificate kind: Certificate
metadata: metadata:
name: {{ include "example-webhook.servingCertificate" . }} name: {{ include "freedns-webhook.servingCertificate" . }}
namespace: {{ .Release.Namespace | quote }} namespace: {{ .Release.Namespace | quote }}
labels: labels:
app: {{ include "example-webhook.name" . }} app: {{ include "freedns-webhook.name" . }}
chart: {{ include "example-webhook.chart" . }} chart: {{ include "freedns-webhook.chart" . }}
release: {{ .Release.Name }} release: {{ .Release.Name }}
heritage: {{ .Release.Service }} heritage: {{ .Release.Service }}
spec: spec:
secretName: {{ include "example-webhook.servingCertificate" . }} secretName: {{ include "freedns-webhook.servingCertificate" . }}
duration: 8760h # 1y duration: 8760h # 1y
issuerRef: issuerRef:
name: {{ include "example-webhook.rootCAIssuer" . }} name: {{ include "freedns-webhook.rootCAIssuer" . }}
dnsNames: dnsNames:
- {{ include "example-webhook.fullname" . }} - {{ include "freedns-webhook.fullname" . }}
- {{ include "example-webhook.fullname" . }}.{{ .Release.Namespace }} - {{ include "freedns-webhook.fullname" . }}.{{ .Release.Namespace }}
- {{ include "example-webhook.fullname" . }}.{{ .Release.Namespace }}.svc - {{ include "freedns-webhook.fullname" . }}.{{ .Release.Namespace }}.svc

View File

@ -1,10 +1,10 @@
apiVersion: v1 apiVersion: v1
kind: ServiceAccount kind: ServiceAccount
metadata: metadata:
name: {{ include "example-webhook.fullname" . }} name: {{ include "freedns-webhook.fullname" . }}
labels: labels:
app: {{ include "example-webhook.name" . }} app: {{ include "freedns-webhook.name" . }}
chart: {{ include "example-webhook.chart" . }} chart: {{ include "freedns-webhook.chart" . }}
release: {{ .Release.Name }} release: {{ .Release.Name }}
heritage: {{ .Release.Service }} heritage: {{ .Release.Service }}
--- ---
@ -14,11 +14,11 @@ metadata:
apiVersion: rbac.authorization.k8s.io/v1 apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding kind: RoleBinding
metadata: metadata:
name: {{ include "example-webhook.fullname" . }}:webhook-authentication-reader name: {{ include "freedns-webhook.fullname" . }}:webhook-authentication-reader
namespace: kube-system namespace: kube-system
labels: labels:
app: {{ include "example-webhook.name" . }} app: {{ include "freedns-webhook.name" . }}
chart: {{ include "example-webhook.chart" . }} chart: {{ include "freedns-webhook.chart" . }}
release: {{ .Release.Name }} release: {{ .Release.Name }}
heritage: {{ .Release.Service }} heritage: {{ .Release.Service }}
roleRef: roleRef:
@ -28,7 +28,7 @@ roleRef:
subjects: subjects:
- apiGroup: "" - apiGroup: ""
kind: ServiceAccount kind: ServiceAccount
name: {{ include "example-webhook.fullname" . }} name: {{ include "freedns-webhook.fullname" . }}
namespace: {{ .Release.Namespace }} namespace: {{ .Release.Namespace }}
--- ---
# apiserver gets the auth-delegator role to delegate auth decisions to # apiserver gets the auth-delegator role to delegate auth decisions to
@ -36,10 +36,10 @@ subjects:
apiVersion: rbac.authorization.k8s.io/v1 apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
name: {{ include "example-webhook.fullname" . }}:auth-delegator name: {{ include "freedns-webhook.fullname" . }}:auth-delegator
labels: labels:
app: {{ include "example-webhook.name" . }} app: {{ include "freedns-webhook.name" . }}
chart: {{ include "example-webhook.chart" . }} chart: {{ include "freedns-webhook.chart" . }}
release: {{ .Release.Name }} release: {{ .Release.Name }}
heritage: {{ .Release.Service }} heritage: {{ .Release.Service }}
roleRef: roleRef:
@ -49,17 +49,17 @@ roleRef:
subjects: subjects:
- apiGroup: "" - apiGroup: ""
kind: ServiceAccount kind: ServiceAccount
name: {{ include "example-webhook.fullname" . }} name: {{ include "freedns-webhook.fullname" . }}
namespace: {{ .Release.Namespace }} namespace: {{ .Release.Namespace }}
--- ---
# Grant cert-manager permission to validate using our apiserver # Grant cert-manager permission to validate using our apiserver
apiVersion: rbac.authorization.k8s.io/v1 apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
name: {{ include "example-webhook.fullname" . }}:domain-solver name: {{ include "freedns-webhook.fullname" . }}:domain-solver
labels: labels:
app: {{ include "example-webhook.name" . }} app: {{ include "freedns-webhook.name" . }}
chart: {{ include "example-webhook.chart" . }} chart: {{ include "freedns-webhook.chart" . }}
release: {{ .Release.Name }} release: {{ .Release.Name }}
heritage: {{ .Release.Service }} heritage: {{ .Release.Service }}
rules: rules:
@ -73,16 +73,16 @@ rules:
apiVersion: rbac.authorization.k8s.io/v1 apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
name: {{ include "example-webhook.fullname" . }}:domain-solver name: {{ include "freedns-webhook.fullname" . }}:domain-solver
labels: labels:
app: {{ include "example-webhook.name" . }} app: {{ include "freedns-webhook.name" . }}
chart: {{ include "example-webhook.chart" . }} chart: {{ include "freedns-webhook.chart" . }}
release: {{ .Release.Name }} release: {{ .Release.Name }}
heritage: {{ .Release.Service }} heritage: {{ .Release.Service }}
roleRef: roleRef:
apiGroup: rbac.authorization.k8s.io apiGroup: rbac.authorization.k8s.io
kind: ClusterRole kind: ClusterRole
name: {{ include "example-webhook.fullname" . }}:domain-solver name: {{ include "freedns-webhook.fullname" . }}:domain-solver
subjects: subjects:
- apiGroup: "" - apiGroup: ""
kind: ServiceAccount kind: ServiceAccount

View File

@ -1,10 +1,10 @@
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: {{ include "example-webhook.fullname" . }} name: {{ include "freedns-webhook.fullname" . }}
labels: labels:
app: {{ include "example-webhook.name" . }} app: {{ include "freedns-webhook.name" . }}
chart: {{ include "example-webhook.chart" . }} chart: {{ include "freedns-webhook.chart" . }}
release: {{ .Release.Name }} release: {{ .Release.Name }}
heritage: {{ .Release.Service }} heritage: {{ .Release.Service }}
spec: spec:
@ -15,5 +15,5 @@ spec:
protocol: TCP protocol: TCP
name: https name: https
selector: selector:
app: {{ include "example-webhook.name" . }} app: {{ include "freedns-webhook.name" . }}
release: {{ .Release.Name }} release: {{ .Release.Name }}

View File

@ -1,6 +1,6 @@
# The GroupName here is used to identify your company or business unit that # The GroupName here is used to identify your company or business unit that
# created this webhook. # created this webhook.
# For example, this may be "acme.mycompany.com". # For freedns, this may be "acme.mycompany.com".
# This name will need to be referenced in each Issuer's `webhook` stanza to # This name will need to be referenced in each Issuer's `webhook` stanza to
# inform cert-manager of where to send ChallengePayload resources in order to # inform cert-manager of where to send ChallengePayload resources in order to
# solve the DNS01 challenge. # solve the DNS01 challenge.

View File

@ -1,69 +0,0 @@
package example
import (
"fmt"
"github.com/miekg/dns"
)
func (e *exampleSolver) handleDNSRequest(w dns.ResponseWriter, req *dns.Msg) {
msg := new(dns.Msg)
msg.SetReply(req)
switch req.Opcode {
case dns.OpcodeQuery:
for _, q := range msg.Question {
if err := e.addDNSAnswer(q, msg, req); err != nil {
msg.SetRcode(req, dns.RcodeServerFailure)
break
}
}
}
w.WriteMsg(msg)
}
func (e *exampleSolver) addDNSAnswer(q dns.Question, msg *dns.Msg, req *dns.Msg) error {
switch q.Qtype {
// Always return loopback for any A query
case dns.TypeA:
rr, err := dns.NewRR(fmt.Sprintf("%s 5 IN A 127.0.0.1", q.Name))
if err != nil {
return err
}
msg.Answer = append(msg.Answer, rr)
return nil
// TXT records are the only important record for ACME dns-01 challenges
case dns.TypeTXT:
e.RLock()
record, found := e.txtRecords[q.Name]
e.RUnlock()
if !found {
msg.SetRcode(req, dns.RcodeNameError)
return nil
}
rr, err := dns.NewRR(fmt.Sprintf("%s 5 IN TXT %s", q.Name, record))
if err != nil {
return err
}
msg.Answer = append(msg.Answer, rr)
return nil
// NS and SOA are for authoritative lookups, return obviously invalid data
case dns.TypeNS:
rr, err := dns.NewRR(fmt.Sprintf("%s 5 IN NS ns.example-acme-webook.invalid.", q.Name))
if err != nil {
return err
}
msg.Answer = append(msg.Answer, rr)
return nil
case dns.TypeSOA:
rr, err := dns.NewRR(fmt.Sprintf("%s 5 IN SOA %s 20 5 5 5 5", "ns.example-acme-webook.invalid.", "ns.example-acme-webook.invalid."))
if err != nil {
return err
}
msg.Answer = append(msg.Answer, rr)
return nil
default:
return fmt.Errorf("unimplemented record type %v", q.Qtype)
}
}

View File

@ -1,68 +0,0 @@
// package example contains a self-contained example of a webhook that passes the cert-manager
// DNS conformance tests
package example
import (
"fmt"
"os"
"sync"
"github.com/jetstack/cert-manager/pkg/acme/webhook"
acme "github.com/jetstack/cert-manager/pkg/acme/webhook/apis/acme/v1alpha1"
"github.com/miekg/dns"
"k8s.io/client-go/rest"
)
type exampleSolver struct {
name string
server *dns.Server
txtRecords map[string]string
sync.RWMutex
}
func (e *exampleSolver) Name() string {
return e.name
}
func (e *exampleSolver) Present(ch *acme.ChallengeRequest) error {
e.Lock()
e.txtRecords[ch.ResolvedFQDN] = ch.Key
e.Unlock()
return nil
}
func (e *exampleSolver) CleanUp(ch *acme.ChallengeRequest) error {
e.Lock()
delete(e.txtRecords, ch.ResolvedFQDN)
e.Unlock()
return nil
}
func (e *exampleSolver) Initialize(kubeClientConfig *rest.Config, stopCh <-chan struct{}) error {
go func(done <-chan struct{}) {
<-done
if err := e.server.Shutdown(); err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
}
}(stopCh)
go func() {
if err := e.server.ListenAndServe(); err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
os.Exit(1)
}
}()
return nil
}
func New(port string) webhook.Solver {
e := &exampleSolver{
name: "example",
txtRecords: make(map[string]string),
}
e.server = &dns.Server{
Addr: ":" + port,
Net: "udp",
Handler: dns.HandlerFunc(e.handleDNSRequest),
}
return e
}

View File

@ -1,96 +0,0 @@
package example
import (
"crypto/rand"
"math/big"
"testing"
acme "github.com/jetstack/cert-manager/pkg/acme/webhook/apis/acme/v1alpha1"
"github.com/miekg/dns"
"github.com/stretchr/testify/assert"
)
func TestExampleSolver_Name(t *testing.T) {
port, _ := rand.Int(rand.Reader, big.NewInt(50000))
port = port.Add(port, big.NewInt(15534))
solver := New(port.String())
assert.Equal(t, "example", solver.Name())
}
func TestExampleSolver_Initialize(t *testing.T) {
port, _ := rand.Int(rand.Reader, big.NewInt(50000))
port = port.Add(port, big.NewInt(15534))
solver := New(port.String())
done := make(chan struct{})
err := solver.Initialize(nil, done)
assert.NoError(t, err, "Expected Initialize not to error")
close(done)
}
func TestExampleSolver_Present_Cleanup(t *testing.T) {
port, _ := rand.Int(rand.Reader, big.NewInt(50000))
port = port.Add(port, big.NewInt(15534))
solver := New(port.String())
done := make(chan struct{})
err := solver.Initialize(nil, done)
assert.NoError(t, err, "Expected Initialize not to error")
validTestData := []struct {
hostname string
record string
}{
{"test1.example.com.", "testkey1"},
{"test2.example.com.", "testkey2"},
{"test3.example.com.", "testkey3"},
}
for _, test := range validTestData {
err := solver.Present(&acme.ChallengeRequest{
Action: acme.ChallengeActionPresent,
Type: "dns-01",
ResolvedFQDN: test.hostname,
Key: test.record,
})
assert.NoError(t, err, "Unexpected error while presenting %v", t)
}
// Resolve test data
for _, test := range validTestData {
msg := new(dns.Msg)
msg.Id = dns.Id()
msg.RecursionDesired = true
msg.Question = make([]dns.Question, 1)
msg.Question[0] = dns.Question{dns.Fqdn(test.hostname), dns.TypeTXT, dns.ClassINET}
in, err := dns.Exchange(msg, "127.0.0.1:"+port.String())
assert.NoError(t, err, "Presented record %s not resolvable", test.hostname)
assert.Len(t, in.Answer, 1, "RR response is of incorrect length")
assert.Equal(t, []string{test.record}, in.Answer[0].(*dns.TXT).Txt, "TXT record returned did not match presented record")
}
// Cleanup test data
for _, test := range validTestData {
err := solver.CleanUp(&acme.ChallengeRequest{
Action: acme.ChallengeActionCleanUp,
Type: "dns-01",
ResolvedFQDN: test.hostname,
Key: test.record,
})
assert.NoError(t, err, "Unexpected error while cleaning up %v", t)
}
// Resolve test data
for _, test := range validTestData {
msg := new(dns.Msg)
msg.Id = dns.Id()
msg.RecursionDesired = true
msg.Question = make([]dns.Question, 1)
msg.Question[0] = dns.Question{dns.Fqdn(test.hostname), dns.TypeTXT, dns.ClassINET}
in, err := dns.Exchange(msg, "127.0.0.1:"+port.String())
assert.NoError(t, err, "Presented record %s not resolvable", test.hostname)
assert.Len(t, in.Answer, 0, "RR response is of incorrect length")
assert.Equal(t, dns.RcodeNameError, in.Rcode, "Expexted NXDOMAIN")
}
close(done)
}

2
go.mod
View File

@ -1,4 +1,4 @@
module github.com/cert-manager/webhook-example module github.com/cert-manager/webhook-freedns
go 1.17 go 1.17

21
main.go
View File

@ -6,7 +6,7 @@ import (
"os" "os"
extapi "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" extapi "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
//"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest" "k8s.io/client-go/rest"
"github.com/jetstack/cert-manager/pkg/acme/webhook/apis/acme/v1alpha1" "github.com/jetstack/cert-manager/pkg/acme/webhook/apis/acme/v1alpha1"
@ -41,7 +41,7 @@ type customDNSProviderSolver struct {
// 3. uncomment the relevant code in the Initialize method below // 3. uncomment the relevant code in the Initialize method below
// 4. ensure your webhook's service account has the required RBAC role // 4. ensure your webhook's service account has the required RBAC role
// assigned to it for interacting with the Kubernetes APIs you need. // assigned to it for interacting with the Kubernetes APIs you need.
//client kubernetes.Clientset client *kubernetes.Clientset
} }
// customDNSProviderConfig is a structure that is used to decode into when // customDNSProviderConfig is a structure that is used to decode into when
@ -65,7 +65,9 @@ type customDNSProviderConfig struct {
// `issuer.spec.acme.dns01.providers.webhook.config` field. // `issuer.spec.acme.dns01.providers.webhook.config` field.
//Email string `json:"email"` //Email string `json:"email"`
//APIKeySecretRef v1alpha1.SecretKeySelector `json:"apiKeySecretRef"` SecretRef string `json:"secretName"`
Domain string `json:"domain"`
//APIKeySecretRef v1.SecretKeySelector `json:"apiKeySecretRef"`
} }
// Name is used as the name for this DNS solver when referencing it on the ACME // Name is used as the name for this DNS solver when referencing it on the ACME
@ -75,7 +77,7 @@ type customDNSProviderConfig struct {
// within a single webhook deployment**. // within a single webhook deployment**.
// For example, `cloudflare` may be used as the name of a solver. // For example, `cloudflare` may be used as the name of a solver.
func (c *customDNSProviderSolver) Name() string { func (c *customDNSProviderSolver) Name() string {
return "my-custom-solver" return "freedns-solver"
} }
// Present is responsible for actually presenting the DNS record with the // Present is responsible for actually presenting the DNS record with the
@ -120,12 +122,11 @@ func (c *customDNSProviderSolver) Initialize(kubeClientConfig *rest.Config, stop
///// UNCOMMENT THE BELOW CODE TO MAKE A KUBERNETES CLIENTSET AVAILABLE TO ///// UNCOMMENT THE BELOW CODE TO MAKE A KUBERNETES CLIENTSET AVAILABLE TO
///// YOUR CUSTOM DNS PROVIDER ///// YOUR CUSTOM DNS PROVIDER
//cl, err := kubernetes.NewForConfig(kubeClientConfig) cl, err := kubernetes.NewForConfig(kubeClientConfig)
//if err != nil { if err != nil {
// return err return err
//} }
// c.client = cl
//c.client = cl
///// END OF CODE TO MAKE KUBERNETES CLIENTSET AVAILABLE ///// END OF CODE TO MAKE KUBERNETES CLIENTSET AVAILABLE
return nil return nil

View File

@ -5,8 +5,6 @@ import (
"testing" "testing"
"github.com/jetstack/cert-manager/test/acme/dns" "github.com/jetstack/cert-manager/test/acme/dns"
"github.com/cert-manager/webhook-example/example"
) )
var ( var (
@ -20,22 +18,11 @@ func TestRunsSuite(t *testing.T) {
// //
// Uncomment the below fixture when implementing your custom DNS provider // Uncomment the below fixture when implementing your custom DNS provider
//fixture := dns.NewFixture(&customDNSProviderSolver{}, fixture := dns.NewFixture(&customDNSProviderSolver{},
// dns.SetResolvedZone(zone), dns.SetResolvedZone(zone),
// dns.SetAllowAmbientCredentials(false), dns.SetAllowAmbientCredentials(false),
// dns.SetManifestPath("testdata/my-custom-solver"), dns.SetManifestPath("testdata/freedns-solver"),
// dns.SetBinariesPath("_test/kubebuilder/bin"),
//)
solver := example.New("59351")
fixture := dns.NewFixture(solver,
dns.SetResolvedZone("example.com."),
dns.SetManifestPath("testdata/my-custom-solver"),
dns.SetDNSServer("127.0.0.1:59351"),
dns.SetUseAuthoritative(false),
) )
//need to uncomment and RunConformance delete runBasic and runExtended once https://github.com/cert-manager/cert-manager/pull/4835 is merged fixture.RunConformance(t)
//fixture.RunConformance(t)
fixture.RunBasic(t)
fixture.RunExtended(t)
} }

4
testdata/freedns-solver/config.json vendored Normal file
View File

@ -0,0 +1,4 @@
{
"secretName": "freedns-auth"
, "domain": "example.com"
}

View File

@ -0,0 +1,7 @@
apiVersion: v1
kind: Secret
metadata:
name: freedns-auth
data:
username: ZXhhbXBsZQ==
password: MTIzNA==

View File

@ -1,3 +0,0 @@
# Solver testdata directory
TODO

View File

@ -1 +0,0 @@
{}