cool-dns/lego.go

119 lines
2.3 KiB
Go
Raw Normal View History

2021-01-08 15:08:57 +00:00
package main
import (
"encoding/json"
"log"
"net/http"
"github.com/miekg/dns"
)
// See https://go-acme.github.io/lego/dns/httpreq/
type configLego struct {
Enable bool `yaml:"enable"`
Address string `yaml:"address"`
Username string `yaml:"username"`
Secret string `yaml:"secret"`
}
type legoPresent struct {
Fqdn string `json:"fqdn"`
Value string `json:"value"`
}
type legoMap map[string]string
func startLEGOWebSever(config configLego) *legoMap {
mux := http.NewServeMux()
acmeMap := make(legoMap)
mux.HandleFunc("/present", func(rw http.ResponseWriter, r *http.Request) {
if !checkBasicAuth(r, config) {
rw.WriteHeader(http.StatusUnauthorized)
return
}
var presentData legoPresent
err := json.NewDecoder(r.Body).Decode(&presentData)
defer r.Body.Close()
if err != nil {
log.Printf("Failed to parse request for ACME: %s", err.Error())
}
acmeMap[presentData.Fqdn] = presentData.Value
rw.WriteHeader(http.StatusOK)
})
mux.HandleFunc("/cleanup", func(rw http.ResponseWriter, r *http.Request) {
if !checkBasicAuth(r, config) {
rw.WriteHeader(http.StatusUnauthorized)
return
}
for k := range acmeMap {
delete(acmeMap, k)
}
rw.WriteHeader(http.StatusOK)
})
go func() {
if err := http.ListenAndServe(config.Address, mux); err != nil {
log.Fatalf("Failed to start Webserver for LEGO: %s\n", err.Error())
}
}()
log.Printf("Startet webserver on %s", config.Address)
return &acmeMap
}
func checkBasicAuth(r *http.Request, config configLego) bool {
if config.Username != "" && config.Secret != "" {
u, p, ok := r.BasicAuth()
if !ok {
return false
}
if u == config.Username && p == config.Secret {
return true
}
log.Printf("Failed lego authentication")
return false
}
return true
}
func handleACMERequest(w dns.ResponseWriter, r *dns.Msg, acmeMap *legoMap) bool {
if len(r.Question) == 1 {
if r.Question[0].Qtype == dns.TypeTXT && r.Question[0].Qclass == dns.ClassINET {
if value, ok := (*acmeMap)[r.Question[0].Name]; ok {
m := new(dns.Msg)
m.SetReply(r)
m.Answer = append(m.Answer, &dns.TXT{
Hdr: dns.RR_Header{
Name: r.Question[0].Name,
Rrtype: dns.TypeTXT,
Class: dns.ClassINET,
Ttl: 0,
},
Txt: []string{value},
})
w.WriteMsg(m)
return true
}
}
}
return false
}