diff options
Diffstat (limited to 'modules/caddytls')
-rw-r--r-- | modules/caddytls/acmeissuer.go | 21 | ||||
-rw-r--r-- | modules/caddytls/tls.go | 12 |
2 files changed, 32 insertions, 1 deletions
diff --git a/modules/caddytls/acmeissuer.go b/modules/caddytls/acmeissuer.go index 64725c9..bbcd5d7 100644 --- a/modules/caddytls/acmeissuer.go +++ b/modules/caddytls/acmeissuer.go @@ -59,6 +59,13 @@ type ACMEIssuer struct { // other than ACME transactions. Email string `json:"email,omitempty"` + // If you have an existing account with the ACME server, put + // the private key here in PEM format. The ACME client will + // look up your account information with this key first before + // trying to create a new one. You can use placeholders here, + // for example if you have it in an environment variable. + AccountKey string `json:"account_key,omitempty"` + // If using an ACME CA that requires an external account // binding, specify the CA-provided credentials here. ExternalAccount *acme.EAB `json:"external_account,omitempty"` @@ -98,15 +105,26 @@ func (ACMEIssuer) CaddyModule() caddy.ModuleInfo { func (iss *ACMEIssuer) Provision(ctx caddy.Context) error { iss.logger = ctx.Logger(iss) + repl := caddy.NewReplacer() + // expand email address, if non-empty if iss.Email != "" { - email, err := caddy.NewReplacer().ReplaceOrErr(iss.Email, true, true) + email, err := repl.ReplaceOrErr(iss.Email, true, true) if err != nil { return fmt.Errorf("expanding email address '%s': %v", iss.Email, err) } iss.Email = email } + // expand account key, if non-empty + if iss.AccountKey != "" { + accountKey, err := repl.ReplaceOrErr(iss.AccountKey, true, true) + if err != nil { + return fmt.Errorf("expanding account key PEM '%s': %v", iss.AccountKey, err) + } + iss.AccountKey = accountKey + } + // DNS providers if iss.Challenges != nil && iss.Challenges.DNS != nil && iss.Challenges.DNS.ProviderRaw != nil { val, err := ctx.LoadModule(iss.Challenges.DNS, "ProviderRaw") @@ -161,6 +179,7 @@ func (iss *ACMEIssuer) makeIssuerTemplate() (certmagic.ACMEManager, error) { CA: iss.CA, TestCA: iss.TestCA, Email: iss.Email, + AccountKeyPEM: iss.AccountKey, CertObtainTimeout: time.Duration(iss.ACMETimeout), TrustedRoots: iss.rootPool, ExternalAccount: iss.ExternalAccount, diff --git a/modules/caddytls/tls.go b/modules/caddytls/tls.go index fd3473e..489d87f 100644 --- a/modules/caddytls/tls.go +++ b/modules/caddytls/tls.go @@ -306,9 +306,11 @@ func (t *TLS) Manage(names []string) error { // requires that the automation policy for r.Host has an issuer of type // *certmagic.ACMEManager, or one that is ACME-enabled (GetACMEIssuer()). func (t *TLS) HandleHTTPChallenge(w http.ResponseWriter, r *http.Request) bool { + // no-op if it's not an ACME challenge request if !certmagic.LooksLikeHTTPChallenge(r) { return false } + // try all the issuers until we find the one that initiated the challenge ap := t.getAutomationPolicyForName(r.Host) type acmeCapable interface{ GetACMEIssuer() *ACMEIssuer } @@ -320,6 +322,16 @@ func (t *TLS) HandleHTTPChallenge(w http.ResponseWriter, r *http.Request) bool { } } } + + // it's possible another server in this process initiated the challenge; + // users have requested that Caddy only handle HTTP challenges it initiated, + // so that users can proxy the others through to their backends; but we + // might not have an automation policy for all identifiers that are trying + // to get certificates (e.g. the admin endpoint), so we do this manual check + if challenge, ok := certmagic.GetACMEChallenge(r.Host); ok { + return certmagic.SolveHTTPChallenge(t.logger, w, r, challenge.Challenge) + } + return false } |