forked from TrueCloudLab/lego
Add DNS challenge provider 'exec' (#508)
As discussed in #505, this commits adds a very simple DNS provider which calls out to an external program which must then add or remove the DNS record.
This commit is contained in:
parent
2e0e9cd68f
commit
2b18d40bab
3 changed files with 76 additions and 0 deletions
1
cli.go
1
cli.go
|
@ -226,6 +226,7 @@ Here is an example bash command using the CloudFlare DNS provider:
|
||||||
fmt.Fprintln(w, "\tpdns:\tPDNS_API_KEY, PDNS_API_URL")
|
fmt.Fprintln(w, "\tpdns:\tPDNS_API_KEY, PDNS_API_URL")
|
||||||
fmt.Fprintln(w, "\tdnspod:\tDNSPOD_API_KEY")
|
fmt.Fprintln(w, "\tdnspod:\tDNSPOD_API_KEY")
|
||||||
fmt.Fprintln(w, "\totc:\tOTC_USER_NAME, OTC_PASSWORD, OTC_PROJECT_NAME, OTC_DOMAIN_NAME, OTC_IDENTITY_ENDPOINT")
|
fmt.Fprintln(w, "\totc:\tOTC_USER_NAME, OTC_PASSWORD, OTC_PROJECT_NAME, OTC_DOMAIN_NAME, OTC_IDENTITY_ENDPOINT")
|
||||||
|
fmt.Fprintln(w, "\texec:\tEXEC_PATH")
|
||||||
w.Flush()
|
w.Flush()
|
||||||
|
|
||||||
fmt.Println(`
|
fmt.Println(`
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"github.com/xenolf/lego/providers/dns/dnsmadeeasy"
|
"github.com/xenolf/lego/providers/dns/dnsmadeeasy"
|
||||||
"github.com/xenolf/lego/providers/dns/dnspod"
|
"github.com/xenolf/lego/providers/dns/dnspod"
|
||||||
"github.com/xenolf/lego/providers/dns/dyn"
|
"github.com/xenolf/lego/providers/dns/dyn"
|
||||||
|
"github.com/xenolf/lego/providers/dns/exec"
|
||||||
"github.com/xenolf/lego/providers/dns/exoscale"
|
"github.com/xenolf/lego/providers/dns/exoscale"
|
||||||
"github.com/xenolf/lego/providers/dns/gandi"
|
"github.com/xenolf/lego/providers/dns/gandi"
|
||||||
"github.com/xenolf/lego/providers/dns/gandiv5"
|
"github.com/xenolf/lego/providers/dns/gandiv5"
|
||||||
|
@ -91,6 +92,8 @@ func NewDNSChallengeProviderByName(name string) (acme.ChallengeProvider, error)
|
||||||
provider, err = ns1.NewDNSProvider()
|
provider, err = ns1.NewDNSProvider()
|
||||||
case "otc":
|
case "otc":
|
||||||
provider, err = otc.NewDNSProvider()
|
provider, err = otc.NewDNSProvider()
|
||||||
|
case "exec":
|
||||||
|
provider, err = exec.NewDNSProvider()
|
||||||
default:
|
default:
|
||||||
err = fmt.Errorf("Unrecognised DNS provider: %s", name)
|
err = fmt.Errorf("Unrecognised DNS provider: %s", name)
|
||||||
}
|
}
|
||||||
|
|
72
providers/dns/exec/exec.go
Normal file
72
providers/dns/exec/exec.go
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
// Package exec implements a manual DNS provider which runs a program for
|
||||||
|
// adding/removing the DNS record.
|
||||||
|
//
|
||||||
|
// The file name of the external program is specified in the environment
|
||||||
|
// variable EXEC_PATH. When it is run by lego, three command-line parameters
|
||||||
|
// are passed to it: The action ("present" or "cleanup"), the fully-qualified domain
|
||||||
|
// name, the value for the record and the TTL.
|
||||||
|
//
|
||||||
|
// For example, requesting a certificate for the domain 'foo.example.com' can
|
||||||
|
// be achieved by calling lego as follows:
|
||||||
|
//
|
||||||
|
// EXEC_PATH=./update-dns.sh \
|
||||||
|
// lego --dns exec \
|
||||||
|
// --domains foo.example.com \
|
||||||
|
// --email invalid@example.com run
|
||||||
|
//
|
||||||
|
// It will then call the program './update-dns.sh' with like this:
|
||||||
|
//
|
||||||
|
// ./update-dns.sh "present" "_acme-challenge.foo.example.com." "MsijOYZxqyjGnFGwhjrhfg-Xgbl5r68WPda0J9EgqqI" "120"
|
||||||
|
//
|
||||||
|
// The program then needs to make sure the record is inserted. When it returns
|
||||||
|
// an error via a non-zero exit code, lego aborts.
|
||||||
|
//
|
||||||
|
// When the record is to be removed again, the program is called with the first
|
||||||
|
// command-line parameter set to "cleanup" instead of "present".
|
||||||
|
package exec
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/xenolf/lego/acme"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DNSProvider adds and removes the record for the DNS challenge by calling a
|
||||||
|
// program with command-line parameters.
|
||||||
|
type DNSProvider struct {
|
||||||
|
program string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDNSProvider returns a new DNS provider which runs the program in the
|
||||||
|
// environment variable EXEC_PATH for adding and removing the DNS record.
|
||||||
|
func NewDNSProvider() (*DNSProvider, error) {
|
||||||
|
s := os.Getenv("EXEC_PATH")
|
||||||
|
if s == "" {
|
||||||
|
return nil, errors.New("environment variable EXEC_PATH not set")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &DNSProvider{program: s}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Present creates a TXT record to fulfil the dns-01 challenge.
|
||||||
|
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
|
fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
|
||||||
|
cmd := exec.Command(d.program, "present", fqdn, value, strconv.Itoa(ttl))
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
|
||||||
|
return cmd.Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
// CleanUp removes the TXT record matching the specified parameters
|
||||||
|
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||||
|
fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
|
||||||
|
cmd := exec.Command(d.program, "cleanup", fqdn, value, strconv.Itoa(ttl))
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
|
||||||
|
return cmd.Run()
|
||||||
|
}
|
Loading…
Reference in a new issue