summaryrefslogtreecommitdiff
path: root/modules/caddytls
diff options
context:
space:
mode:
Diffstat (limited to 'modules/caddytls')
-rw-r--r--modules/caddytls/acmeissuer.go21
-rw-r--r--modules/caddytls/tls.go12
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
}