From 9fb0b1e838e216f90d20c9a32e948ad60dcca07d Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Tue, 31 Mar 2020 21:08:02 -0600 Subject: [PATCH] caddytls: Add support for externalAccountBinding ACME extension --- go.mod | 4 ++-- go.sum | 8 +++---- modules/caddytls/acmeissuer.go | 39 +++++++++++++++++++++++++++++++--- 3 files changed, 42 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 3cd325c0..76fa5149 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.14 require ( github.com/Masterminds/sprig/v3 v3.0.2 github.com/alecthomas/chroma v0.7.2-0.20200305040604-4f3623dce67a - github.com/caddyserver/certmagic v0.10.5 + github.com/caddyserver/certmagic v0.10.6 github.com/dustin/go-humanize v1.0.1-0.20200219035652-afde56e7acac github.com/go-acme/lego/v3 v3.5.0 github.com/google/cel-go v0.4.1 @@ -21,7 +21,7 @@ require ( github.com/smallstep/cli v0.14.0-rc.3 github.com/smallstep/truststore v0.9.4 github.com/vulcand/oxy v1.1.0 - github.com/yuin/goldmark v1.1.26 + github.com/yuin/goldmark v1.1.27 github.com/yuin/goldmark-highlighting v0.0.0-20200307114337-60d527fdb691 go.uber.org/zap v1.14.1 golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 diff --git a/go.sum b/go.sum index 30999085..aca4ed9c 100644 --- a/go.sum +++ b/go.sum @@ -120,8 +120,8 @@ github.com/bombsimon/wsl/v2 v2.0.0/go.mod h1:mf25kr/SqFEPhhcxW1+7pxzGlW+hIl/hYTK github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= -github.com/caddyserver/certmagic v0.10.5 h1:Dg4ipO1y23rWvFmiiRqhtUTh5Hy7PmfoFvPfDpnE8Z8= -github.com/caddyserver/certmagic v0.10.5/go.mod h1:Y8jcUBctgk/IhpAzlHKfimZNyXCkfGgRTC0orl8gROQ= +github.com/caddyserver/certmagic v0.10.6 h1:sCya6FmfaN74oZE46kqfaFOVoROD/mF36rTQfjN7TZc= +github.com/caddyserver/certmagic v0.10.6/go.mod h1:Y8jcUBctgk/IhpAzlHKfimZNyXCkfGgRTC0orl8gROQ= github.com/cenkalti/backoff/v4 v4.0.0 h1:6VeaLF9aI+MAUQ95106HwWzYZgJJpZ4stumjj6RFYAU= github.com/cenkalti/backoff/v4 v4.0.0/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg= github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -758,8 +758,8 @@ github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.22/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.26 h1:81MfIApzizD8JqKIjnWy2Vxj7GgmQUrJlh/jYWH8yGk= -github.com/yuin/goldmark v1.1.26/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27 h1:nqDD4MMMQA0lmWq03Z2/myGPYLQoXtmi0rGVs95ntbo= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark-highlighting v0.0.0-20200307114337-60d527fdb691 h1:VWSxtAiQNh3zgHJpdpkpVYjTPqRE3P6UZCOPa1nRDio= github.com/yuin/goldmark-highlighting v0.0.0-20200307114337-60d527fdb691/go.mod h1:YLF3kDffRfUH/bTxOxHhV6lxwIB3Vfj91rEwNMS9MXo= go.etcd.io/bbolt v1.3.2 h1:Z/90sZLPOeCy2PwprqkFa25PdkusRzaj9P8zm/KNyvk= diff --git a/modules/caddytls/acmeissuer.go b/modules/caddytls/acmeissuer.go index 0e43046f..133d007c 100644 --- a/modules/caddytls/acmeissuer.go +++ b/modules/caddytls/acmeissuer.go @@ -17,6 +17,7 @@ package caddytls import ( "context" "crypto/x509" + "encoding/base64" "fmt" "io/ioutil" "net/url" @@ -54,6 +55,10 @@ type ACMEIssuer struct { // other than ACME transactions. Email string `json:"email,omitempty"` + // If using an ACME CA that requires an external account + // binding, specify the CA-provided credentials here. + ExternalAccount *ExternalAccountBinding `json:"external_account,omitempty"` + // Time to wait before timing out an ACME operation. ACMETimeout caddy.Duration `json:"acme_timeout,omitempty"` @@ -107,12 +112,16 @@ func (m *ACMEIssuer) Provision(ctx caddy.Context) error { } } - m.template = m.makeIssuerTemplate() + var err error + m.template, err = m.makeIssuerTemplate() + if err != nil { + return err + } return nil } -func (m *ACMEIssuer) makeIssuerTemplate() certmagic.ACMEManager { +func (m *ACMEIssuer) makeIssuerTemplate() (certmagic.ACMEManager, error) { template := certmagic.ACMEManager{ CA: m.CA, Email: m.Email, @@ -120,6 +129,20 @@ func (m *ACMEIssuer) makeIssuerTemplate() certmagic.ACMEManager { TrustedRoots: m.rootPool, } + if m.ExternalAccount != nil { + hmac, err := base64.StdEncoding.DecodeString(m.ExternalAccount.EncodedHMAC) + if err != nil { + return template, err + } + if m.ExternalAccount.KeyID == "" || len(hmac) == 0 { + return template, fmt.Errorf("when an external account binding is specified, both key ID and HMAC are required") + } + template.ExternalAccount = &certmagic.ExternalAccountBinding{ + KeyID: m.ExternalAccount.KeyID, + HMAC: hmac, + } + } + if m.Challenges != nil { if m.Challenges.HTTP != nil { template.DisableHTTPChallenge = m.Challenges.HTTP.Disabled @@ -132,7 +155,7 @@ func (m *ACMEIssuer) makeIssuerTemplate() certmagic.ACMEManager { template.DNSProvider = m.Challenges.DNS } - return template + return template, nil } // SetConfig sets the associated certmagic config for this issuer. @@ -201,6 +224,16 @@ type DNSProviderMaker interface { NewDNSProvider() (challenge.Provider, error) } +// ExternalAccountBinding contains information for +// binding an external account to an ACME account. +type ExternalAccountBinding struct { + // The key identifier. + KeyID string `json:"key_id,omitempty"` + + // The base64-encoded HMAC. + EncodedHMAC string `json:"hmac,omitempty"` +} + // Interface guards var ( _ certmagic.PreChecker = (*ACMEIssuer)(nil)