Compare commits

...

3 Commits

Author SHA1 Message Date
4fe54aabf0 Fixed some more rbac issues, v2022.03.15 2022-03-15 01:39:12 +09:00
c2272e3816 Fixed RBAC issues on 1.23.0 <= 2022-03-14 17:26:48 +09:00
3eea4a96a6 Proper log handling 2022-03-14 17:26:29 +09:00
9 changed files with 257 additions and 73 deletions

View File

@@ -1,4 +1,4 @@
FROM golang:1.16-alpine AS build_deps FROM golang:1.17-alpine AS build_deps
RUN apk add --no-cache git RUN apk add --no-cache git

View File

@@ -1,54 +1,59 @@
# ACME webhook example # Introduction
First, [RTFM](https://cert-manager.io/docs/configuration/acme/dns01/).
The ACME issuer type supports an optional 'webhook' solver, which can be used Have you read it? If you haven't go read it. Cuz I'll keep everything short.
to implement custom DNS01 challenge solving logic.
This is useful if you need to use cert-manager with a DNS provider that is not This is a dns01 solver for [FreeDNS](https://freedns.afraid.org/).
officially supported in cert-manager core.
## Why not in core? Pull requests welcome. I'm completely unfamiliar with golang. I did it by looking at
other webhook repos and this is the result.
As the project & adoption has grown, there has been an influx of DNS provider
pull requests to our core codebase. As this number has grown, the test matrix
has become un-maintainable and so, it's not possible for us to certify that
providers work to a sufficient level.
By creating this 'interface' between cert-manager and DNS providers, we allow
users to quickly iterate and test out new integrations, and then packaging
those up themselves as 'extensions' to cert-manager.
We can also then provide a standardised 'testing framework', or set of
conformance tests, which allow us to validate the a DNS provider works as
expected.
## Creating your own webhook
Webhook's themselves are deployed as Kubernetes API services, in order to allow
administrators to restrict access to webhooks with Kubernetes RBAC.
This is important, as otherwise it'd be possible for anyone with access to your
webhook to complete ACME challenge validations and obtain certificates.
To make the set up of these webhook's easier, we provide a template repository
that can be used to get started quickly.
### Creating your own repository
### Running the test suite
All DNS providers **must** run the DNS01 provider conformance testing suite,
else they will have undetermined behaviour when used with cert-manager.
**It is essential that you configure and run the test suite when creating a
DNS01 webhook.**
An example Go test file has been provided in [main_test.go](https://github.com/jetstack/cert-manager-webhook-example/blob/master/main_test.go).
You can run the test suite with:
## Install
```bash ```bash
$ TEST_ZONE_NAME=example.com. make test $ cd deploy
$ helm show values freedns-webhook > my-values.yaml
$ edit my-values.yaml
$ helm install -n cert-manager [INSTALLATION_NAME] freedns-webhook/ -f my-values.yaml
``` ```
The example file has a number of areas you must fill in and replace with your ## ClusterIssuer for Let's encrypt staging
own options in order for tests to pass. ```yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
email: myemail@example.com
server: https://acme-staging-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: le-staging
solvers:
- dns01:
webhook:
groupName: acme.freedns.afraid.org
solverName: freedns-solver
config:
secretName: freedns-auth
```
## FreeDNS webhook settings
Normally if you haven't changed anything, the default namespace should be
`cert-manager`. It should be within the same namespace for the webhook when
you do `helm install webhook -n cert-manager`.
```yaml
apiVersion: v1
kind: Secret
metadata:
name: freedns-auth
namespace: cert-manager
data:
username: [YOUR_USERNAME_IN_BASE64]
password: [YOUR_PASSWORD_IN_BASE64]
type: Opaque
```
Additionally, the following names can be customized
* acme.freedns.afraid.org
* freedns-auth

View File

@@ -8,6 +8,45 @@ metadata:
release: {{ .Release.Name }} release: {{ .Release.Name }}
heritage: {{ .Release.Service }} heritage: {{ .Release.Service }}
--- ---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ include "freedns-webhook.fullname" . }}:secret-read
namespace: {{ .Release.Namespace }}
labels:
app: {{ include "freedns-webhook.name" . }}
chart: {{ include "freedns-webhook.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
rules:
- apiGroups:
- ''
resources:
- 'secrets'
verbs:
- 'get'
---
# Grant the webhook permission to read the secret
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ include "freedns-webhook.fullname" . }}:secret-read
namespace: {{ .Release.Namespace }}
labels:
app: {{ include "freedns-webhook.name" . }}
chart: {{ include "freedns-webhook.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ include "freedns-webhook.fullname" . }}:secret-read
subjects:
- apiGroup: ""
kind: ServiceAccount
name: {{ include "freedns-webhook.fullname" . }}
namespace: {{ .Release.Namespace }}
---
# Grant the webhook permission to read the ConfigMap containing the Kubernetes # Grant the webhook permission to read the ConfigMap containing the Kubernetes
# apiserver's requestheader-ca-certificate. # apiserver's requestheader-ca-certificate.
# This ConfigMap is automatically created by the Kubernetes apiserver. # This ConfigMap is automatically created by the Kubernetes apiserver.
@@ -88,3 +127,42 @@ subjects:
kind: ServiceAccount kind: ServiceAccount
name: {{ .Values.certManager.serviceAccountName }} name: {{ .Values.certManager.serviceAccountName }}
namespace: {{ .Values.certManager.namespace }} namespace: {{ .Values.certManager.namespace }}
---
# Grant pod account permission to validate using our apiserver
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "freedns-webhook.fullname" . }}:flowcontrol
labels:
app: {{ include "freedns-webhook.name" . }}
chart: {{ include "freedns-webhook.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
rules:
- apiGroups:
- "flowcontrol.apiserver.k8s.io"
resources:
- 'prioritylevelconfigurations'
- 'flowschemas'
verbs:
- 'list'
- 'watch'
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ include "freedns-webhook.fullname" . }}:flowcontrol
labels:
app: {{ include "freedns-webhook.name" . }}
chart: {{ include "freedns-webhook.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ include "freedns-webhook.fullname" . }}:flowcontrol
subjects:
- apiGroup: ""
kind: ServiceAccount
name: {{ include "freedns-webhook.fullname" . }}
namespace: {{ .Release.Namespace }}

View File

@@ -1,20 +1,20 @@
# 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 freedns, this may be "acme.mycompany.com". # For freedns, this may be "acme.freedns.afraid.org".
# 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.
# This group name should be **unique**, hence using your own company's domain # This group name should be **unique**, hence using your own company's domain
# here is recommended. # here is recommended.
groupName: acme.mycompany.com groupName: acme.freedns.afraid.org
certManager: certManager:
namespace: cert-manager namespace: cert-manager
serviceAccountName: cert-manager serviceAccountName: cert-manager
image: image:
repository: mycompany/webhook-image repository: penguinade/cert-manager-webhook-freedns
tag: latest tag: 2022.03.15
pullPolicy: IfNotPresent pullPolicy: IfNotPresent
nameOverride: "" nameOverride: ""

View File

@@ -6,8 +6,10 @@ import (
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"net/url" "net/url"
"strconv"
"strings" "strings"
logf "github.com/jetstack/cert-manager/pkg/logs"
"golang.org/x/net/html" "golang.org/x/net/html"
) )
@@ -22,6 +24,7 @@ type FreeDNSOperations interface {
type FreeDNS struct { type FreeDNS struct {
AuthCookie *http.Cookie AuthCookie *http.Cookie
DomainId string DomainId string
LoggedOut bool
} }
const URI_LOGIN = "https://freedns.afraid.org/zc.php?step=2" const URI_LOGIN = "https://freedns.afraid.org/zc.php?step=2"
@@ -32,7 +35,15 @@ const URI_SUBDOMAIN_EDIT = "https://freedns.afraid.org/subdomain/edit.php?data_i
const URI_LOGOUT = "https://freedns.afraid.org/logout/" const URI_LOGOUT = "https://freedns.afraid.org/logout/"
const URI_DELETE_RECORD = "https://freedns.afraid.org/subdomain/delete2.php?data_id[]=%s&submit=delete%%20selected" const URI_DELETE_RECORD = "https://freedns.afraid.org/subdomain/delete2.php?data_id[]=%s&submit=delete%%20selected"
// const URI_LOGIN string = "http://127.0.0.1:1234/" func LogInfo(Mesg string) {
// fmt.Println(Mesg)
logf.V(logf.InfoLevel).Info(Mesg)
}
func LogDebug(Mesg string) {
// fmt.Println(Mesg)
logf.V(logf.DebugLevel).Info(Mesg)
}
func GetDomainFromZone(Zone string) string { func GetDomainFromZone(Zone string) string {
_segs := strings.Split(strings.TrimSuffix(Zone, "."), ".") _segs := strings.Split(strings.TrimSuffix(Zone, "."), ".")
@@ -63,6 +74,8 @@ func _HttpRequest(method string, url string, PostData url.Values, ExCookie *http
return nil, "", err return nil, "", err
} }
req.Header.Set("User-Agent", "github.com/tgckpg/cert-manager-webhook-freedns (2022.03.15)")
if ExCookie != nil { if ExCookie != nil {
req.AddCookie(ExCookie) req.AddCookie(ExCookie)
} }
@@ -102,6 +115,7 @@ func (dnsObj *FreeDNS) Login(Username string, Password string) error {
for _, cookie := range resp.Cookies() { for _, cookie := range resp.Cookies() {
if cookie.Name == "dns_cookie" { if cookie.Name == "dns_cookie" {
dnsObj.AuthCookie = cookie dnsObj.AuthCookie = cookie
dnsObj.LoggedOut = false
} }
} }
@@ -109,14 +123,16 @@ func (dnsObj *FreeDNS) Login(Username string, Password string) error {
} }
func (dnsObj *FreeDNS) Logout() error { func (dnsObj *FreeDNS) Logout() error {
if dnsObj.AuthCookie == nil { if dnsObj.LoggedOut {
return nil return nil
} }
_, _, err := _HttpRequest("GET", URI_DOMAIN, nil, dnsObj.AuthCookie) _, _, err := _HttpRequest("GET", URI_LOGOUT, nil, dnsObj.AuthCookie)
if err != nil { if err != nil {
return err return err
} }
dnsObj.LoggedOut = true
return nil return nil
} }
@@ -149,7 +165,7 @@ loop:
break loop break loop
case html.TextToken: case html.TextToken:
if inBold && strings.TrimSpace(htmlTokens.Token().Data) == DomainName { if inBold && strings.TrimSpace(htmlTokens.Token().Data) == DomainName {
fmt.Println("Found " + DomainName + ", looking for domain id") LogInfo("Found " + DomainName + ", looking for domain id")
lookForA = true lookForA = true
} }
// The [Manage] anchor is next to the bold tag // The [Manage] anchor is next to the bold tag
@@ -162,9 +178,9 @@ loop:
for { for {
attrKey, attrValue, moreAttr := htmlTokens.TagAttr() attrKey, attrValue, moreAttr := htmlTokens.TagAttr()
_href := string(attrValue) _href := string(attrValue)
if string(attrKey) == "href" && strings.Contains(_href, "/subdomain/?limit=") { if string(attrKey) == "href" && strings.HasPrefix(_href, "/subdomain/?limit=") {
dnsObj.DomainId = strings.TrimPrefix(_href, "/subdomain/?limit=") dnsObj.DomainId = strings.TrimPrefix(_href, "/subdomain/?limit=")
fmt.Printf("Domain id for \"%s\" is %s\n", DomainName, dnsObj.DomainId) LogDebug(fmt.Sprintf("Domain id for \"%s\" is %s\n", DomainName, dnsObj.DomainId))
break loop break loop
} }
if !moreAttr { if !moreAttr {
@@ -205,10 +221,15 @@ func (dnsObj *FreeDNS) AddRecord(RecordType string, Subdomain string, Address st
// Record already exists, treat this as success // Record already exists, treat this as success
if strings.Contains(respStr, "already have another already existent") { if strings.Contains(respStr, "already have another already existent") {
fmt.Println("Record already exists") LogInfo("Record already exists")
return nil return nil
} }
// Try get a sense of the problem
var errorMesgs []string
lookForNextEl := 0
lookForText := false
_strBuffer := ""
htmlTokens := html.NewTokenizer(strings.NewReader(respStr)) htmlTokens := html.NewTokenizer(strings.NewReader(respStr))
loop: loop:
for { for {
@@ -217,10 +238,40 @@ func (dnsObj *FreeDNS) AddRecord(RecordType string, Subdomain string, Address st
case html.ErrorToken: case html.ErrorToken:
break loop break loop
case html.TextToken: case html.TextToken:
_text := strings.TrimSpace(string(htmlTokens.Text()))
// Search for the "1 error" / "N errors" message
if strings.HasSuffix(_text, "error") || strings.HasSuffix(_text, "errors") {
_text = strings.TrimSpace(strings.TrimSuffix(strings.TrimSuffix(_text, "s"), "error"))
_n, _ := strconv.ParseInt(_text, 10, 8)
// + 1 because we are already inside a font tag
// The next closing </font> is ourself
lookForNextEl = int(_n) + 1
} else if lookForText {
_strBuffer = _strBuffer + _text
}
case html.StartTagToken: case html.StartTagToken:
_t, _ := htmlTokens.TagName()
tagName := string(_t)
if tagName == "font" && 0 < lookForNextEl {
lookForText = true
_strBuffer = ""
}
case html.EndTagToken:
_t, _ := htmlTokens.TagName()
tagName := string(_t)
if tagName == "font" && 0 < lookForNextEl {
lookForText = false
errorMesgs = append(errorMesgs, strings.TrimSpace(_strBuffer))
lookForNextEl--
}
} }
} }
if 0 < len(errorMesgs) {
return errors.New(strings.Join(errorMesgs, ", "))
}
return errors.New("Unknown error while submitting record") return errors.New("Unknown error while submitting record")
} }
@@ -229,8 +280,8 @@ func (dnsObj *FreeDNS) AddRecord(RecordType string, Subdomain string, Address st
return err return err
} }
if strings.Contains(_Location.Path, "/zc.php") { if strings.HasPrefix(_Location.Path, "/zc.php") {
fmt.Println("Error on AddRecord: Cookie expired") LogDebug("Error on AddRecord: Cookie expired")
return errors.New("dns_cookie maybe expired") return errors.New("dns_cookie maybe expired")
} }
@@ -278,7 +329,7 @@ func (dnsObj *FreeDNS) FindRecord(Subdomain string, RecordType string, Address s
CurrRecordType := "" CurrRecordType := ""
CurrRecordAddr := "" CurrRecordAddr := ""
CurrTagName := "" CurrTagName := ""
lookForNextTD := 0 lookForNextEl := 0
htmlTokens := html.NewTokenizer(strings.NewReader(respStr)) htmlTokens := html.NewTokenizer(strings.NewReader(respStr))
loop: loop:
@@ -288,13 +339,13 @@ loop:
case html.ErrorToken: case html.ErrorToken:
break loop break loop
case html.TextToken: case html.TextToken:
if CurrTagName == "a" && lookForNextTD == 1 && CurrRecordAddr == "" { if CurrTagName == "a" && lookForNextEl == 1 && CurrRecordAddr == "" {
CurrRecordAddr = strings.TrimSpace(string(htmlTokens.Text())) CurrRecordAddr = strings.TrimSpace(string(htmlTokens.Text()))
} else if CurrTagName == "td" { } else if CurrTagName == "td" {
if lookForNextTD == 1 { if lookForNextEl == 1 {
CurrRecordType = string(htmlTokens.Text()) CurrRecordType = string(htmlTokens.Text())
lookForNextTD = 2 lookForNextEl = 2
} else if lookForNextTD == 2 { } else if lookForNextEl == 2 {
_Addr := string(htmlTokens.Text()) _Addr := string(htmlTokens.Text())
if CurrRecordType == RecordType && CurrRecordAddr == Subdomain { if CurrRecordType == RecordType && CurrRecordAddr == Subdomain {
if _Addr == Address { if _Addr == Address {
@@ -303,7 +354,7 @@ loop:
DeepSearchCandidates = append(DeepSearchCandidates, CurrRecordId) DeepSearchCandidates = append(DeepSearchCandidates, CurrRecordId)
} }
} }
lookForNextTD = 0 lookForNextEl = 0
} }
} }
/** Each record is displayed with the following structure /** Each record is displayed with the following structure
@@ -323,7 +374,7 @@ loop:
attrKey, attrValue, moreAttr := htmlTokens.TagAttr() attrKey, attrValue, moreAttr := htmlTokens.TagAttr()
_href := string(attrValue) _href := string(attrValue)
if string(attrKey) == "href" && strings.Contains(_href, "edit.php?data_id=") { if string(attrKey) == "href" && strings.Contains(_href, "edit.php?data_id=") {
lookForNextTD = 1 lookForNextEl = 1
CurrRecordAddr = "" CurrRecordAddr = ""
CurrRecordId = strings.TrimPrefix(_href, "edit.php?data_id=") CurrRecordId = strings.TrimPrefix(_href, "edit.php?data_id=")
break break
@@ -340,7 +391,7 @@ loop:
// Begin deep search for truncated records // Begin deep search for truncated records
htmlAddr := strings.ReplaceAll(html.EscapeString(Address), "&#34;", "&quot;") htmlAddr := strings.ReplaceAll(html.EscapeString(Address), "&#34;", "&quot;")
for _, RecordId := range DeepSearchCandidates { for _, RecordId := range DeepSearchCandidates {
fmt.Println("Searching in " + RecordId) LogDebug("Searching in " + RecordId)
_, respStr, err := _HttpRequest("GET", URI_SUBDOMAIN_EDIT+RecordId, nil, dnsObj.AuthCookie) _, respStr, err := _HttpRequest("GET", URI_SUBDOMAIN_EDIT+RecordId, nil, dnsObj.AuthCookie)
if err != nil { if err != nil {
continue continue

42
freedns/freedns_test.go Executable file
View File

@@ -0,0 +1,42 @@
package freedns
import (
"os"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
/*
func TestHttpRequest(t *testing.T) {
_HttpRequest("GET", "http://127.0.0.1:12345", nil, nil)
}
*/
func TestGetDomainFromZone(t *testing.T) {
assert.Equal(t, GetDomainFromZone("a.b.example.com"), "example.com")
assert.Equal(t, GetDomainFromZone("example.com"), "example.com")
}
func TestOperations(t *testing.T) {
freeDNS := FreeDNS{}
var UserName = os.Getenv("FREEDNS_USERNAME")
var Password = os.Getenv("FREEDNS_PASSWORD")
var SelectedDomain = os.Getenv("FREEDNS_DOMAIN")
require.NotEmpty(t, UserName, "Please set the env vars for FREEDNS_USERNAME")
require.NotEmpty(t, Password, "Please set the env vars for FREEDNS_PASSWORD")
require.NotEmpty(t, SelectedDomain, "Please set the env vars for FREEDNS_DOMAIN")
require.Nil(t, freeDNS.Login(UserName, Password))
require.Nil(t, freeDNS.SelectDomain(SelectedDomain))
require.Nil(t, freeDNS.AddRecord("TXT", "", "\"TEST\"", false, ""))
id, _ := freeDNS.FindRecord(SelectedDomain, "TXT", "\"TEST\"")
require.NotEmpty(t, id)
require.Nil(t, freeDNS.DeleteRecord(id))
require.Nil(t, freeDNS.Logout())
require.Equal(t, freeDNS.LoggedOut, true)
}

2
go.mod
View File

@@ -3,7 +3,7 @@ module github.com/cert-manager/webhook-freedns
go 1.17 go 1.17
require ( require (
github.com/jetstack/cert-manager v1.7.0 github.com/jetstack/cert-manager v1.7.1
github.com/miekg/dns v1.1.34 github.com/miekg/dns v1.1.34
github.com/stretchr/testify v1.7.0 github.com/stretchr/testify v1.7.0
k8s.io/apiextensions-apiserver v0.23.1 k8s.io/apiextensions-apiserver v0.23.1

2
go.sum
View File

@@ -305,6 +305,8 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jetstack/cert-manager v1.7.0 h1:XLLDmREJ8MlBg/Z1bySjHdyzT4yYTzGlbBsxqddJzxU= github.com/jetstack/cert-manager v1.7.0 h1:XLLDmREJ8MlBg/Z1bySjHdyzT4yYTzGlbBsxqddJzxU=
github.com/jetstack/cert-manager v1.7.0/go.mod h1:xj0TPp31HE0Jub5mNOnF3Fp3XvhIsiP+tsPZVOmU/Qs= github.com/jetstack/cert-manager v1.7.0/go.mod h1:xj0TPp31HE0Jub5mNOnF3Fp3XvhIsiP+tsPZVOmU/Qs=
github.com/jetstack/cert-manager v1.7.1 h1:qIIP0RN5FzBChJLJ3uGCGJmdAAonwDMdcsJExATa64I=
github.com/jetstack/cert-manager v1.7.1/go.mod h1:xj0TPp31HE0Jub5mNOnF3Fp3XvhIsiP+tsPZVOmU/Qs=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ=
github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=

12
main.go
View File

@@ -121,7 +121,7 @@ func (c *customDNSProviderSolver) Present(ch *v1alpha1.ChallengeRequest) error {
_zone = strings.TrimRight(_zone, ".") _zone = strings.TrimRight(_zone, ".")
_key := "\"" + ch.Key + "\"" _key := "\"" + ch.Key + "\""
fmt.Println("ADD", _zone, _key) freedns.LogInfo(fmt.Sprintf("ADD %s %s", _zone, _key))
err = dnsObj.AddRecord("TXT", _zone, _key, false, "") err = dnsObj.AddRecord("TXT", _zone, _key, false, "")
if err != nil { if err != nil {
@@ -140,11 +140,17 @@ func (c *customDNSProviderSolver) Present(ch *v1alpha1.ChallengeRequest) error {
// concurrently. // concurrently.
func (c *customDNSProviderSolver) CleanUp(ch *v1alpha1.ChallengeRequest) error { func (c *customDNSProviderSolver) CleanUp(ch *v1alpha1.ChallengeRequest) error {
if c.freedns.AuthCookie == nil {
return nil
}
dnsObj := c.freedns
_addr := strings.TrimRight(ch.ResolvedFQDN, ".") _addr := strings.TrimRight(ch.ResolvedFQDN, ".")
_key := "\"" + ch.Key + "\"" _key := "\"" + ch.Key + "\""
_id, err := c.freedns.FindRecord(_addr, "TXT", _key) _id, err := c.freedns.FindRecord(_addr, "TXT", _key)
fmt.Println("DEL", _addr) freedns.LogInfo(fmt.Sprintf("DEL %s %s", _addr, _key))
if _id != "" { if _id != "" {
err = c.freedns.DeleteRecord(_id) err = c.freedns.DeleteRecord(_id)
@@ -153,7 +159,7 @@ func (c *customDNSProviderSolver) CleanUp(ch *v1alpha1.ChallengeRequest) error {
} }
} }
return c.freedns.Logout() return dnsObj.Logout()
} }
// Initialize will be called when the webhook first starts. // Initialize will be called when the webhook first starts.