@@ -2,6 +2,7 @@ package example
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/miekg/dns"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -11,45 +12,7 @@ func (e *exampleSolver) handleDNSRequest(w dns.ResponseWriter, req *dns.Msg) {
 | 
			
		||||
	switch req.Opcode {
 | 
			
		||||
	case dns.OpcodeQuery:
 | 
			
		||||
		for _, q := range msg.Question {
 | 
			
		||||
			switch q.Qtype {
 | 
			
		||||
			case dns.TypeA:
 | 
			
		||||
				rr, err := dns.NewRR(fmt.Sprintf("%s 5 IN A 127.0.0.1", q.Name))
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					msg.SetRcode(req, dns.RcodeNameError)
 | 
			
		||||
				} else {
 | 
			
		||||
					msg.Answer = append(msg.Answer, rr)
 | 
			
		||||
				}
 | 
			
		||||
			case dns.TypeTXT:
 | 
			
		||||
				// get record
 | 
			
		||||
				e.RLock()
 | 
			
		||||
				record, found := e.txtRecords[q.Name]
 | 
			
		||||
				e.RUnlock()
 | 
			
		||||
				if !found {
 | 
			
		||||
					msg.SetRcode(req, dns.RcodeNameError)
 | 
			
		||||
				} else {
 | 
			
		||||
					rr, err := dns.NewRR(fmt.Sprintf("%s 5 IN TXT %s", q.Name, record))
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						msg.SetRcode(req, dns.RcodeServerFailure)
 | 
			
		||||
						break
 | 
			
		||||
					}
 | 
			
		||||
					msg.Answer = append(msg.Answer, rr)
 | 
			
		||||
				}
 | 
			
		||||
			case dns.TypeNS:
 | 
			
		||||
				rr, err := dns.NewRR(fmt.Sprintf("%s 5 IN NS ns.example-acme-webook.invalid.", q.Name))
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					msg.SetRcode(req, dns.RcodeServerFailure)
 | 
			
		||||
					break
 | 
			
		||||
				} else {
 | 
			
		||||
					msg.Answer = append(msg.Answer, rr)
 | 
			
		||||
				}
 | 
			
		||||
			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 {
 | 
			
		||||
					msg.SetRcode(req, dns.RcodeServerFailure)
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
				msg.Answer = append(msg.Answer, rr)
 | 
			
		||||
			default:
 | 
			
		||||
			if err := e.addDNSAnswer(q, msg, req); err != nil {
 | 
			
		||||
				msg.SetRcode(req, dns.RcodeServerFailure)
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
@@ -57,3 +20,50 @@ func (e *exampleSolver) handleDNSRequest(w dns.ResponseWriter, req *dns.Msg) {
 | 
			
		||||
	}
 | 
			
		||||
	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)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,8 @@
 | 
			
		||||
package example
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"github.com/jetstack/cert-manager/pkg/acme/webhook"
 | 
			
		||||
@@ -18,31 +20,36 @@ type exampleSolver struct {
 | 
			
		||||
	sync.RWMutex
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e exampleSolver) Name() string {
 | 
			
		||||
func (e *exampleSolver) Name() string {
 | 
			
		||||
	return e.name
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e exampleSolver) Present(ch *acme.ChallengeRequest) error {
 | 
			
		||||
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 {
 | 
			
		||||
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 {
 | 
			
		||||
func (e *exampleSolver) Initialize(kubeClientConfig *rest.Config, stopCh <-chan struct{}) error {
 | 
			
		||||
	go func(done <-chan struct{}) {
 | 
			
		||||
		<-done
 | 
			
		||||
		e.server.Shutdown()
 | 
			
		||||
		if err := e.server.Shutdown(); err != nil {
 | 
			
		||||
			fmt.Fprintf(os.Stderr, "%s\n", err.Error())
 | 
			
		||||
		}
 | 
			
		||||
	}(stopCh)
 | 
			
		||||
	go func() {
 | 
			
		||||
		e.server.ListenAndServe()
 | 
			
		||||
		if err := e.server.ListenAndServe(); err != nil {
 | 
			
		||||
			fmt.Fprintf(os.Stderr, "%s\n", err.Error())
 | 
			
		||||
			os.Exit(1)
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user