2018-06-11 15:32:50 +00:00
// Package duckdns Adds lego support for http://duckdns.org.
2018-05-30 17:53:04 +00:00
// See http://www.duckdns.org/spec.jsp for more info on updating TXT records.
package duckdns
import (
"errors"
"fmt"
"io/ioutil"
"github.com/xenolf/lego/acme"
2018-06-11 15:32:50 +00:00
"github.com/xenolf/lego/platform/config/env"
2018-05-30 17:53:04 +00:00
)
// DNSProvider adds and removes the record for the DNS challenge
type DNSProvider struct {
2018-06-11 15:32:50 +00:00
// The api token
2018-05-30 17:53:04 +00:00
token string
}
// NewDNSProvider returns a new DNS provider using
// environment variable DUCKDNS_TOKEN for adding and removing the DNS record.
func NewDNSProvider ( ) ( * DNSProvider , error ) {
2018-06-11 15:32:50 +00:00
values , err := env . Get ( "DUCKDNS_TOKEN" )
if err != nil {
return nil , fmt . Errorf ( "DuckDNS: %v" , err )
}
2018-05-30 17:53:04 +00:00
2018-06-11 15:32:50 +00:00
return NewDNSProviderCredentials ( values [ "DUCKDNS_TOKEN" ] )
2018-05-30 17:53:04 +00:00
}
// NewDNSProviderCredentials uses the supplied credentials to return a
// DNSProvider instance configured for http://duckdns.org .
2018-07-17 22:17:51 +00:00
func NewDNSProviderCredentials ( token string ) ( * DNSProvider , error ) {
if token == "" {
2018-06-11 15:32:50 +00:00
return nil , errors . New ( "DuckDNS: credentials missing" )
2018-05-30 17:53:04 +00:00
}
2018-07-17 22:17:51 +00:00
return & DNSProvider { token : token } , nil
2018-05-30 17:53:04 +00:00
}
2018-07-17 22:17:51 +00:00
// Present creates a TXT record to fulfil the dns-01 challenge.
func ( d * DNSProvider ) Present ( domain , token , keyAuth string ) error {
_ , txtRecord , _ := acme . DNS01Record ( domain , keyAuth )
return updateTxtRecord ( domain , d . token , txtRecord , false )
}
// CleanUp clears DuckDNS TXT record
func ( d * DNSProvider ) CleanUp ( domain , token , keyAuth string ) error {
return updateTxtRecord ( domain , d . token , "" , true )
2018-05-30 17:53:04 +00:00
}
2018-07-17 22:17:51 +00:00
// updateTxtRecord Update the domains TXT record
// To update the TXT record we just need to make one simple get request.
// In DuckDNS you only have one TXT record shared with the domain and all sub domains.
func updateTxtRecord ( domain , token , txt string , clear bool ) error {
u := fmt . Sprintf ( "https://www.duckdns.org/update?domains=%s&token=%s&clear=%t&txt=%s" , domain , token , clear , txt )
response , err := acme . HTTPClient . Get ( u )
2018-05-30 17:53:04 +00:00
if err != nil {
return err
}
defer response . Body . Close ( )
bodyBytes , err := ioutil . ReadAll ( response . Body )
if err != nil {
return err
}
2018-07-17 22:17:51 +00:00
2018-05-30 17:53:04 +00:00
body := string ( bodyBytes )
if body != "OK" {
2018-07-17 22:17:51 +00:00
return fmt . Errorf ( "request to change TXT record for DuckDNS returned the following result (%s) this does not match expectation (OK) used url [%s]" , body , u )
2018-05-30 17:53:04 +00:00
}
return nil
}