From 5a19db5dc2db7c02d0f99630a07a64cacb7f7b44 Mon Sep 17 00:00:00 2001 From: Matt Holt Date: Fri, 13 Mar 2020 11:06:08 -0600 Subject: v2: Implement 'pki' app powered by Smallstep for localhost certificates (#3125) * pki: Initial commit of PKI app (WIP) (see #2502 and #3021) * pki: Ability to use root/intermediates, and sign with root * pki: Fix benign misnamings left over from copy+paste * pki: Only install root if not already trusted * Make HTTPS port the default; all names use auto-HTTPS; bug fixes * Fix build - what happened to our CI tests?? * Fix go.mod --- caddyconfig/httpcaddyfile/builtins.go | 81 +++++++++++++++++++++++------------ 1 file changed, 54 insertions(+), 27 deletions(-) (limited to 'caddyconfig/httpcaddyfile/builtins.go') diff --git a/caddyconfig/httpcaddyfile/builtins.go b/caddyconfig/httpcaddyfile/builtins.go index 3b5a4f5..91c1c0a 100644 --- a/caddyconfig/httpcaddyfile/builtins.go +++ b/caddyconfig/httpcaddyfile/builtins.go @@ -95,7 +95,7 @@ func parseRoot(h Helper) ([]ConfigValue, error) { // parseTLS parses the tls directive. Syntax: // -// tls []|[ ] { +// tls [|internal]|[ ] { // protocols [] // ciphers // curves @@ -106,23 +106,11 @@ func parseRoot(h Helper) ([]ConfigValue, error) { // } // func parseTLS(h Helper) ([]ConfigValue, error) { - var configVals []ConfigValue - var cp *caddytls.ConnectionPolicy var fileLoader caddytls.FileLoader var folderLoader caddytls.FolderLoader - var mgr caddytls.ACMEIssuer - - // fill in global defaults, if configured - if email := h.Option("email"); email != nil { - mgr.Email = email.(string) - } - if acmeCA := h.Option("acme_ca"); acmeCA != nil { - mgr.CA = acmeCA.(string) - } - if caPemFile := h.Option("acme_ca_root"); caPemFile != nil { - mgr.TrustedRootsPEMFiles = append(mgr.TrustedRootsPEMFiles, caPemFile.(string)) - } + var acmeIssuer *caddytls.ACMEIssuer + var internalIssuer *caddytls.InternalIssuer for h.Next() { // file certificate loader @@ -130,10 +118,17 @@ func parseTLS(h Helper) ([]ConfigValue, error) { switch len(firstLine) { case 0: case 1: - if !strings.Contains(firstLine[0], "@") { - return nil, h.Err("single argument must be an email address") + if firstLine[0] == "internal" { + internalIssuer = new(caddytls.InternalIssuer) + } 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.Email = firstLine[0] } - mgr.Email = firstLine[0] + case 2: certFilename := firstLine[0] keyFilename := firstLine[1] @@ -143,7 +138,7 @@ func parseTLS(h Helper) ([]ConfigValue, error) { // https://github.com/caddyserver/caddy/issues/2588 ... but we // must be careful about how we do this; being careless will // lead to failed handshakes - + // // we need to remember which cert files we've seen, since we // must load each cert only once; otherwise, they each get a // different tag... since a cert loaded twice has the same @@ -152,7 +147,7 @@ func parseTLS(h Helper) ([]ConfigValue, error) { // policy that is looking for any tag but the last one to be // loaded won't find it, and TLS handshakes will fail (see end) // of issue #3004) - + // // tlsCertTags maps certificate filenames to their tag. // This is used to remember which tag is used for each // certificate files, since we need to avoid loading @@ -256,29 +251,38 @@ func parseTLS(h Helper) ([]ConfigValue, error) { if len(arg) != 1 { return nil, h.ArgErr() } - mgr.CA = arg[0] + if acmeIssuer == nil { + acmeIssuer = new(caddytls.ACMEIssuer) + } + acmeIssuer.CA = arg[0] // DNS provider for ACME DNS challenge case "dns": if !h.Next() { return nil, h.ArgErr() } + if acmeIssuer == nil { + acmeIssuer = new(caddytls.ACMEIssuer) + } provName := h.Val() - if mgr.Challenges == nil { - mgr.Challenges = new(caddytls.ChallengesConfig) + if acmeIssuer.Challenges == nil { + acmeIssuer.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) + acmeIssuer.Challenges.DNSRaw = caddyconfig.JSONModuleObject(dnsProvModule.New(), "provider", provName, h.warnings) case "ca_root": arg := h.RemainingArgs() if len(arg) != 1 { return nil, h.ArgErr() } - mgr.TrustedRootsPEMFiles = append(mgr.TrustedRootsPEMFiles, arg[0]) + if acmeIssuer == nil { + acmeIssuer = new(caddytls.ACMEIssuer) + } + acmeIssuer.TrustedRootsPEMFiles = append(acmeIssuer.TrustedRootsPEMFiles, arg[0]) default: return nil, h.Errf("unknown subdirective: %s", h.Val()) @@ -291,6 +295,9 @@ func parseTLS(h Helper) ([]ConfigValue, error) { } } + // begin building the final config values + var configVals []ConfigValue + // certificate loaders if len(fileLoader) > 0 { configVals = append(configVals, ConfigValue{ @@ -322,10 +329,30 @@ func parseTLS(h Helper) ([]ConfigValue, error) { } // automation policy - if !reflect.DeepEqual(mgr, caddytls.ACMEIssuer{}) { + if acmeIssuer != nil && internalIssuer != nil { + // the logic to support this would be complex + return nil, h.Err("cannot use both ACME and internal issuers in same server block") + } + if acmeIssuer != nil { + // fill in global defaults, if configured + if email := h.Option("email"); email != nil && acmeIssuer.Email == "" { + acmeIssuer.Email = email.(string) + } + if acmeCA := h.Option("acme_ca"); acmeCA != nil && acmeIssuer.CA == "" { + acmeIssuer.CA = acmeCA.(string) + } + if caPemFile := h.Option("acme_ca_root"); caPemFile != nil { + acmeIssuer.TrustedRootsPEMFiles = append(acmeIssuer.TrustedRootsPEMFiles, caPemFile.(string)) + } + + configVals = append(configVals, ConfigValue{ + Class: "tls.cert_issuer", + Value: acmeIssuer, + }) + } else if internalIssuer != nil { configVals = append(configVals, ConfigValue{ Class: "tls.cert_issuer", - Value: mgr, + Value: internalIssuer, }) } -- cgit v1.2.3