httpcaddyfile: Add support for DNS challenge solvers

Configuration via the Caddyfile requires use of env variables, but
an upstream issue is currently blocking that:
https://github.com/go-acme/lego/issues/1054

Providers will need to be retrofitted upstream in order to support env
var configuration.
This commit is contained in:
Matthew Holt 2020-02-08 16:52:54 -07:00
parent 98bbc54fdc
commit 17d938fc54
No known key found for this signature in database
GPG key ID: 2A349DD577D586A5
3 changed files with 37 additions and 9 deletions

View file

@ -98,6 +98,7 @@ func parseRoot(h Helper) ([]ConfigValue, error) {
// alpn <values...> // alpn <values...>
// load <paths...> // load <paths...>
// ca <acme_ca_endpoint> // ca <acme_ca_endpoint>
// dns <provider_name>
// } // }
// //
func parseTLS(h Helper) ([]ConfigValue, error) { func parseTLS(h Helper) ([]ConfigValue, error) {
@ -217,6 +218,21 @@ func parseTLS(h Helper) ([]ConfigValue, error) {
} }
mgr.CA = arg[0] mgr.CA = arg[0]
// DNS provider for ACME DNS challenge
case "dns":
if !h.Next() {
return nil, h.ArgErr()
}
provName := h.Val()
if mgr.Challenges == nil {
mgr.Challenges = new(caddytls.ChallengesConfig)
}
dnsProvModule, err := caddy.GetModule("tls.dns." + provName)
if err != nil {
return nil, h.Errf("getting DNS provider module named '%s': %v", provName, err)
}
mgr.Challenges.DNSRaw = caddyconfig.JSONModuleObject(dnsProvModule.New(), "provider", provName, h.warnings)
default: default:
return nil, h.Errf("unknown subdirective: %s", h.Val()) return nil, h.Errf("unknown subdirective: %s", h.Val())
} }

View file

@ -71,8 +71,8 @@ func (st ServerType) Setup(originalServerBlocks []caddyfile.ServerBlock,
val, err = parseOptExperimentalHTTP3(disp) val, err = parseOptExperimentalHTTP3(disp)
case "storage": case "storage":
val, err = parseOptStorage(disp) val, err = parseOptStorage(disp)
case "acme_ca": case "acme_ca", "acme_dns":
val, err = parseOptACMECA(disp) val, err = parseOptACME(disp)
case "email": case "email":
val, err = parseOptEmail(disp) val, err = parseOptEmail(disp)
case "admin": case "admin":
@ -222,11 +222,12 @@ func (st ServerType) Setup(originalServerBlocks []caddyfile.ServerBlock,
} }
} }
} }
// if global ACME CA or email were set, append a catch-all automation // if global ACME CA, DNS, or email were set, append a catch-all automation
// policy that ensures they will be used if no tls directive was used // policy that ensures they will be used if no tls directive was used
acmeCA, hasACMECA := options["acme_ca"] acmeCA, hasACMECA := options["acme_ca"]
acmeDNS, hasACMEDNS := options["acme_dns"]
email, hasEmail := options["email"] email, hasEmail := options["email"]
if hasACMECA || hasEmail { if hasACMECA || hasACMEDNS || hasEmail {
if tlsApp.Automation == nil { if tlsApp.Automation == nil {
tlsApp.Automation = new(caddytls.AutomationConfig) tlsApp.Automation = new(caddytls.AutomationConfig)
} }
@ -236,11 +237,22 @@ func (st ServerType) Setup(originalServerBlocks []caddyfile.ServerBlock,
if !hasEmail { if !hasEmail {
email = "" email = ""
} }
mgr := caddytls.ACMEManagerMaker{
CA: acmeCA.(string),
Email: email.(string),
}
if hasACMEDNS {
provName := acmeDNS.(string)
dnsProvModule, err := caddy.GetModule("tls.dns." + provName)
if err != nil {
return nil, warnings, fmt.Errorf("getting DNS provider module named '%s': %v", provName, err)
}
mgr.Challenges = &caddytls.ChallengesConfig{
DNSRaw: caddyconfig.JSONModuleObject(dnsProvModule.New(), "provider", provName, &warnings),
}
}
tlsApp.Automation.Policies = append(tlsApp.Automation.Policies, caddytls.AutomationPolicy{ tlsApp.Automation.Policies = append(tlsApp.Automation.Policies, caddytls.AutomationPolicy{
ManagementRaw: caddyconfig.JSONModuleObject(caddytls.ACMEManagerMaker{ ManagementRaw: caddyconfig.JSONModuleObject(mgr, "module", "acme", &warnings),
CA: acmeCA.(string),
Email: email.(string),
}, "module", "acme", &warnings),
}) })
} }
if tlsApp.Automation != nil { if tlsApp.Automation != nil {

View file

@ -162,7 +162,7 @@ func parseOptStorage(d *caddyfile.Dispenser) (caddy.StorageConverter, error) {
return storage, nil return storage, nil
} }
func parseOptACMECA(d *caddyfile.Dispenser) (string, error) { func parseOptACME(d *caddyfile.Dispenser) (string, error) {
d.Next() // consume parameter name d.Next() // consume parameter name
if !d.Next() { if !d.Next() {
return "", d.ArgErr() return "", d.ArgErr()