aboutsummaryrefslogtreecommitdiffhomepage
path: root/caddyconfig
diff options
context:
space:
mode:
authorMatt Holt <[email protected]>2024-04-13 21:31:43 -0400
committerGitHub <[email protected]>2024-04-13 21:31:43 -0400
commit81413caea251a3ef9e3641d7b1b6e867572a2b1b (patch)
tree1a379dcf516e8d7daeae1fb00e54c1fbf1e74696 /caddyconfig
parentdc9dd2e4b3e266cb1267f672e3bcfd50c67cc3d4 (diff)
downloadcaddy-81413caea251a3ef9e3641d7b1b6e867572a2b1b.tar.gz
caddy-81413caea251a3ef9e3641d7b1b6e867572a2b1b.zip
caddytls: Upgrade ACMEz to v2; support ZeroSSL API; various fixes (#6229)
* WIP: acmez v2, CertMagic, and ZeroSSL issuer upgrades * caddytls: ZeroSSLIssuer now uses ZeroSSL API instead of ACME * Fix go.mod * caddytls: Fix automation related to managers (fix #6060) * Fix typo (appease linter) * Fix HTTP validation with ZeroSSL API
Diffstat (limited to 'caddyconfig')
-rw-r--r--caddyconfig/httpcaddyfile/builtins.go28
-rw-r--r--caddyconfig/httpcaddyfile/options.go6
-rw-r--r--caddyconfig/httpcaddyfile/tlsapp.go31
3 files changed, 41 insertions, 24 deletions
diff --git a/caddyconfig/httpcaddyfile/builtins.go b/caddyconfig/httpcaddyfile/builtins.go
index 505885d2d..a7f4247f5 100644
--- a/caddyconfig/httpcaddyfile/builtins.go
+++ b/caddyconfig/httpcaddyfile/builtins.go
@@ -24,7 +24,7 @@ import (
"time"
"github.com/caddyserver/certmagic"
- "github.com/mholt/acmez/acme"
+ "github.com/mholt/acmez/v2/acme"
"go.uber.org/zap/zapcore"
"github.com/caddyserver/caddy/v2"
@@ -107,7 +107,6 @@ func parseTLS(h Helper) ([]ConfigValue, error) {
var onDemand bool
var reusePrivateKeys bool
- // file certificate loader
firstLine := h.RemainingArgs()
switch len(firstLine) {
case 0:
@@ -117,13 +116,13 @@ func parseTLS(h Helper) ([]ConfigValue, error) {
} else if !strings.Contains(firstLine[0], "@") {
return nil, h.Err("single argument must either be 'internal' or an email address")
} else {
- if acmeIssuer == nil {
- acmeIssuer = new(caddytls.ACMEIssuer)
+ acmeIssuer = &caddytls.ACMEIssuer{
+ Email: firstLine[0],
}
- acmeIssuer.Email = firstLine[0]
}
case 2:
+ // file certificate loader
certFilename := firstLine[0]
keyFilename := firstLine[1]
@@ -488,19 +487,24 @@ func parseTLS(h Helper) ([]ConfigValue, error) {
case acmeIssuer != nil:
// implicit ACME issuers (from various subdirectives) - use defaults; there might be more than one
- defaultIssuers := caddytls.DefaultIssuers()
+ defaultIssuers := caddytls.DefaultIssuers(acmeIssuer.Email)
- // if a CA endpoint was set, override multiple implicit issuers since it's a specific one
+ // if an ACME CA endpoint was set, the user expects to use that specific one,
+ // not any others that may be defaults, so replace all defaults with that ACME CA
if acmeIssuer.CA != "" {
defaultIssuers = []certmagic.Issuer{acmeIssuer}
}
for _, issuer := range defaultIssuers {
- switch iss := issuer.(type) {
- case *caddytls.ACMEIssuer:
- issuer = acmeIssuer
- case *caddytls.ZeroSSLIssuer:
- iss.ACMEIssuer = acmeIssuer
+ // apply settings from the implicitly-configured ACMEIssuer to any
+ // default ACMEIssuers, but preserve each default issuer's CA endpoint,
+ // because, for example, if you configure the DNS challenge, it should
+ // apply to any of the default ACMEIssuers, but you don't want to trample
+ // out their unique CA endpoints
+ if iss, ok := issuer.(*caddytls.ACMEIssuer); ok && iss != nil {
+ acmeCopy := *acmeIssuer
+ acmeCopy.CA = iss.CA
+ issuer = &acmeCopy
}
configVals = append(configVals, ConfigValue{
Class: "tls.cert_issuer",
diff --git a/caddyconfig/httpcaddyfile/options.go b/caddyconfig/httpcaddyfile/options.go
index 70d475d6b..bbc63ced8 100644
--- a/caddyconfig/httpcaddyfile/options.go
+++ b/caddyconfig/httpcaddyfile/options.go
@@ -18,7 +18,7 @@ import (
"strconv"
"github.com/caddyserver/certmagic"
- "github.com/mholt/acmez/acme"
+ "github.com/mholt/acmez/v2/acme"
"github.com/caddyserver/caddy/v2"
"github.com/caddyserver/caddy/v2/caddyconfig"
@@ -212,9 +212,9 @@ func parseOptACMEDNS(d *caddyfile.Dispenser, _ any) (any, error) {
if err != nil {
return nil, err
}
- prov, ok := unm.(certmagic.ACMEDNSProvider)
+ prov, ok := unm.(certmagic.DNSProvider)
if !ok {
- return nil, d.Errf("module %s (%T) is not a certmagic.ACMEDNSProvider", modID, unm)
+ return nil, d.Errf("module %s (%T) is not a certmagic.DNSProvider", modID, unm)
}
return prov, nil
}
diff --git a/caddyconfig/httpcaddyfile/tlsapp.go b/caddyconfig/httpcaddyfile/tlsapp.go
index 1adb2b6e0..08da3a5c7 100644
--- a/caddyconfig/httpcaddyfile/tlsapp.go
+++ b/caddyconfig/httpcaddyfile/tlsapp.go
@@ -24,7 +24,7 @@ import (
"strings"
"github.com/caddyserver/certmagic"
- "github.com/mholt/acmez/acme"
+ "github.com/mholt/acmez/v2/acme"
"github.com/caddyserver/caddy/v2"
"github.com/caddyserver/caddy/v2/caddyconfig"
@@ -224,7 +224,7 @@ func (st ServerType) buildTLSApp(
var internal, external []string
for _, s := range ap.SubjectsRaw {
// do not create Issuers for Tailscale domains; they will be given a Manager instead
- if strings.HasSuffix(strings.ToLower(s), ".ts.net") {
+ if isTailscaleDomain(s) {
continue
}
if !certmagic.SubjectQualifiesForCert(s) {
@@ -378,15 +378,12 @@ func (st ServerType) buildTLSApp(
if len(ap.Issuers) == 0 && automationPolicyHasAllPublicNames(ap) {
// for public names, create default issuers which will later be filled in with configured global defaults
// (internal names will implicitly use the internal issuer at auto-https time)
- ap.Issuers = caddytls.DefaultIssuers()
+ emailStr, _ := globalEmail.(string)
+ ap.Issuers = caddytls.DefaultIssuers(emailStr)
// if a specific endpoint is configured, can't use multiple default issuers
if globalACMECA != nil {
- if strings.Contains(globalACMECA.(string), "zerossl") {
- ap.Issuers = []certmagic.Issuer{&caddytls.ZeroSSLIssuer{ACMEIssuer: new(caddytls.ACMEIssuer)}}
- } else {
- ap.Issuers = []certmagic.Issuer{new(caddytls.ACMEIssuer)}
- }
+ ap.Issuers = []certmagic.Issuer{new(caddytls.ACMEIssuer)}
}
}
}
@@ -666,17 +663,33 @@ func automationPolicyShadows(i int, aps []*caddytls.AutomationPolicy) int {
// subjectQualifiesForPublicCert is like certmagic.SubjectQualifiesForPublicCert() except
// that this allows domains with multiple wildcard levels like '*.*.example.com' to qualify
// if the automation policy has OnDemand enabled (i.e. this function is more lenient).
+//
+// IP subjects are considered as non-qualifying for public certs. Technically, there are
+// now public ACME CAs as well as non-ACME CAs that issue IP certificates. But this function
+// is used solely for implicit automation (defaults), where it gets really complicated to
+// keep track of which issuers support IP certificates in which circumstances. Currently,
+// issuers that support IP certificates are very few, and all require some sort of config
+// from the user anyway (such as an account credential). Since we cannot implicitly and
+// automatically get public IP certs without configuration from the user, we treat IPs as
+// not qualifying for public certificates. Users should expressly configure an issuer
+// that supports IP certs for that purpose.
func subjectQualifiesForPublicCert(ap *caddytls.AutomationPolicy, subj string) bool {
return !certmagic.SubjectIsIP(subj) &&
!certmagic.SubjectIsInternal(subj) &&
(strings.Count(subj, "*.") < 2 || ap.OnDemand)
}
+// automationPolicyHasAllPublicNames returns true if all the names on the policy
+// do NOT qualify for public certs OR are tailscale domains.
func automationPolicyHasAllPublicNames(ap *caddytls.AutomationPolicy) bool {
for _, subj := range ap.SubjectsRaw {
- if !subjectQualifiesForPublicCert(ap, subj) {
+ if !subjectQualifiesForPublicCert(ap, subj) || isTailscaleDomain(subj) {
return false
}
}
return true
}
+
+func isTailscaleDomain(name string) bool {
+ return strings.HasSuffix(strings.ToLower(name), ".ts.net")
+}