penguin/webhook-freedns

freedns webhook for cert-manager

commit b99ca72213c6cd20c745d06764467197a4624b96

author斟酌 鵬兄 <tgckpg@gmail.com>
date2022-03-13T21:39:42Z
subjectPassed Conformance Tests
commit b99ca72213c6cd20c745d06764467197a4624b96
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date:   2022-03-13T21:39:42Z

    Passed Conformance Tests
---
 freedns/freedns.go                  | 12 ++++++---
 main.go                             | 49 ++++++++++++++++++++++++++++++++-----
 testdata/freedns-solver/config.json |  1 -
 3 files changed, 52 insertions(+), 10 deletions(-)

diff --git a/freedns/freedns.go b/freedns/freedns.go
index 59248f2..093021f 100755
--- a/freedns/freedns.go
+++ b/freedns/freedns.go
@@ -34,6 +34,12 @@ const URI_DELETE_RECORD = "https://freedns.afraid.org/subdomain/delete2.php?data
 
 // const URI_LOGIN string = "http://127.0.0.1:1234/"
 
+func GetDomainFromZone(Zone string) string {
+	_segs := strings.Split(strings.TrimSuffix(Zone, "."), ".")
+	_segs = _segs[len(_segs)-2:]
+	return strings.Join(_segs, ".")
+}
+
 func _HttpRequest(method string, url string, PostData url.Values, ExCookie *http.Cookie) (*http.Response, string, error) {
 	client := http.Client{
 		CheckRedirect: func(req *http.Request, via []*http.Request) error {
@@ -157,7 +163,7 @@ loop:
 					attrKey, attrValue, moreAttr := htmlTokens.TagAttr()
 					_href := string(attrValue)
 					if string(attrKey) == "href" && strings.Contains(_href, "/subdomain/?limit=") {
-						dnsObj.DomainId = strings.TrimLeft(_href, "/subdomain/?limit=")
+						dnsObj.DomainId = strings.TrimPrefix(_href, "/subdomain/?limit=")
 						fmt.Printf("Domain id for \"%s\" is %s\n", DomainName, dnsObj.DomainId)
 						break loop
 					}
@@ -293,7 +299,7 @@ loop:
 					if CurrRecordType == RecordType && CurrRecordAddr == Subdomain {
 						if _Addr == Address {
 							return CurrRecordId, nil
-						} else if strings.HasSuffix(_Addr, "...") && strings.HasPrefix(Address, strings.TrimRight(_Addr, "...")) {
+						} else if strings.HasSuffix(_Addr, "...") && strings.HasPrefix(Address, strings.TrimSuffix(_Addr, "...")) {
 							DeepSearchCandidates = append(DeepSearchCandidates, CurrRecordId)
 						}
 					}
@@ -319,7 +325,7 @@ loop:
 					if string(attrKey) == "href" && strings.Contains(_href, "edit.php?data_id=") {
 						lookForNextTD = 1
 						CurrRecordAddr = ""
-						CurrRecordId = strings.TrimLeft(_href, "edit.php?data_id=")
+						CurrRecordId = strings.TrimPrefix(_href, "edit.php?data_id=")
 						break
 					}
 					if !moreAttr {
diff --git a/main.go b/main.go
index 305aee3..0737116 100644
--- a/main.go
+++ b/main.go
@@ -5,12 +5,14 @@ import (
 	"encoding/json"
 	"fmt"
 	"os"
+	"strings"
 
 	extapi "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/client-go/kubernetes"
 	"k8s.io/client-go/rest"
 
+	"github.com/cert-manager/webhook-freedns/freedns"
 	"github.com/jetstack/cert-manager/pkg/acme/webhook/apis/acme/v1alpha1"
 	"github.com/jetstack/cert-manager/pkg/acme/webhook/cmd"
 )
@@ -43,7 +45,8 @@ type customDNSProviderSolver struct {
 	// 3. uncomment the relevant code in the Initialize method below
 	// 4. ensure your webhook's service account has the required RBAC role
 	//    assigned to it for interacting with the Kubernetes APIs you need.
-	client *kubernetes.Clientset
+	client  *kubernetes.Clientset
+	freedns *freedns.FreeDNS
 }
 
 // customDNSProviderConfig is a structure that is used to decode into when
@@ -68,7 +71,6 @@ type customDNSProviderConfig struct {
 
 	//Email           string `json:"email"`
 	SecretRef string `json:"secretName"`
-	Domain    string `json:"domain"`
 	//APIKeySecretRef v1.SecretKeySelector `json:"apiKeySecretRef"`
 }
 
@@ -102,9 +104,31 @@ func (c *customDNSProviderSolver) Present(ch *v1alpha1.ChallengeRequest) error {
 	username := string(secretObj.Data["username"])
 	password := string(secretObj.Data["password"])
 
-	fmt.Printf("Domain: %s, Auth: %s %s\n", cfg.Domain, username, password)
+	dnsObj := freedns.FreeDNS{}
+	err = dnsObj.Login(username, password)
+	if err != nil {
+		return err
+	}
+
+	domainName := freedns.GetDomainFromZone(ch.ResolvedZone)
+	err = dnsObj.SelectDomain(domainName)
+	if err != nil {
+		return err
+	}
+
+	_zone := strings.TrimRight(ch.ResolvedFQDN, ".")
+	_zone = strings.TrimSuffix(_zone, domainName)
+	_zone = strings.TrimRight(_zone, ".")
+	_key := "\"" + ch.Key + "\""
 
-	// TODO: add code that sets a record in the DNS provider's console
+	fmt.Println("ADD", _zone, _key)
+
+	err = dnsObj.AddRecord("TXT", _zone, _key, false, "")
+	if err != nil {
+		return err
+	}
+
+	c.freedns = &dnsObj
 	return nil
 }
 
@@ -115,8 +139,21 @@ func (c *customDNSProviderSolver) Present(ch *v1alpha1.ChallengeRequest) error {
 // This is in order to facilitate multiple DNS validations for the same domain
 // concurrently.
 func (c *customDNSProviderSolver) CleanUp(ch *v1alpha1.ChallengeRequest) error {
-	// TODO: add code that deletes a record from the DNS provider's console
-	return nil
+
+	_addr := strings.TrimRight(ch.ResolvedFQDN, ".")
+	_key := "\"" + ch.Key + "\""
+	_id, err := c.freedns.FindRecord(_addr, "TXT", _key)
+
+	fmt.Println("DEL", _addr)
+
+	if _id != "" {
+		err = c.freedns.DeleteRecord(_id)
+		if err != nil {
+			return err
+		}
+	}
+
+	return c.freedns.Logout()
 }
 
 // Initialize will be called when the webhook first starts.
diff --git a/testdata/freedns-solver/config.json b/testdata/freedns-solver/config.json
index f1723e9..b82e05a 100644
--- a/testdata/freedns-solver/config.json
+++ b/testdata/freedns-solver/config.json
@@ -1,4 +1,3 @@
 {
 	"secretName": "freedns-auth"
-	, "domain": "example.com"
 }