diff --git a/README.md b/README.md index 16bd003..251e9d4 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ CertMagic - Automatic HTTPS using Let's Encrypt - Exponential backoff with carefully-tuned intervals - Retries with optional test/staging CA endpoint instead of production, to avoid rate limits - Written in Go, a language with memory-safety guarantees -- Powered by [ACMEz](https://github.com/mholt/acmez), _the_ premier ACME client library for Go +- Powered by [ACMEz](https://github.com/mholt/acmez/v2), _the_ premier ACME client library for Go - All [libdns](https://github.com/libdns) DNS providers work out-of-the-box - Pluggable storage backends (default: file system) - Pluggable key sources @@ -566,7 +566,7 @@ We welcome your contributions! Please see our **[contributing guidelines](https: ## Project History -CertMagic is the core of Caddy's advanced TLS automation code, extracted into a library. The underlying ACME client implementation is [ACMEz](https://github.com/mholt/acmez). CertMagic's code was originally a central part of Caddy even before Let's Encrypt entered public beta in 2015. +CertMagic is the core of Caddy's advanced TLS automation code, extracted into a library. The underlying ACME client implementation is [ACMEz](https://github.com/mholt/acmez/v2). CertMagic's code was originally a central part of Caddy even before Let's Encrypt entered public beta in 2015. In the years since then, Caddy's TLS automation techniques have been widely adopted, tried and tested in production, and served millions of sites and secured trillions of connections. diff --git a/account.go b/account.go index 97fdadf..2853691 100644 --- a/account.go +++ b/account.go @@ -32,7 +32,7 @@ import ( "strings" "sync" - "github.com/mholt/acmez/acme" + "github.com/mholt/acmez/v2/acme" ) // getAccount either loads or creates a new account, depending on if diff --git a/acmeclient.go b/acmeclient.go index 9a02aaf..ed904b9 100644 --- a/acmeclient.go +++ b/acmeclient.go @@ -26,8 +26,8 @@ import ( "sync" "time" - "github.com/mholt/acmez" - "github.com/mholt/acmez/acme" + "github.com/mholt/acmez/v2" + "github.com/mholt/acmez/v2/acme" "go.uber.org/zap" ) diff --git a/acmeissuer.go b/acmeissuer.go index 7a5113c..b5e837c 100644 --- a/acmeissuer.go +++ b/acmeissuer.go @@ -28,8 +28,8 @@ import ( "sync" "time" - "github.com/mholt/acmez" - "github.com/mholt/acmez/acme" + "github.com/mholt/acmez/v2" + "github.com/mholt/acmez/v2/acme" "go.uber.org/zap" ) @@ -69,6 +69,13 @@ type ACMEIssuer struct { // with this ACME account ExternalAccount *acme.EAB + // Optionally specify the validity period of + // the certificate(s) here as offsets from the + // approximate time of certificate issuance, + // but note that not all CAs support this + // (EXPERIMENTAL: Subject to change) + NotBefore, NotAfter time.Duration + // Disable all HTTP challenges DisableHTTPChallenge bool @@ -183,6 +190,12 @@ func NewACMEIssuer(cfg *Config, template ACMEIssuer) *ACMEIssuer { if template.ExternalAccount == nil { template.ExternalAccount = DefaultACME.ExternalAccount } + if template.NotBefore != 0 { + template.NotBefore = DefaultACME.NotBefore + } + if template.NotAfter != 0 { + template.NotAfter = DefaultACME.NotAfter + } if !template.DisableHTTPChallenge { template.DisableHTTPChallenge = DefaultACME.DisableHTTPChallenge } @@ -407,10 +420,21 @@ func (am *ACMEIssuer) doIssue(ctx context.Context, csr *x509.CertificateRequest, } } + params, err := acmez.OrderParametersFromCSR(client.account, csr) + if err != nil { + return nil, false, fmt.Errorf("generating order parameters from CSR: %v", err) + } + if am.NotBefore != 0 { + params.NotBefore = time.Now().Add(am.NotBefore) + } + if am.NotAfter != 0 { + params.NotAfter = time.Now().Add(am.NotAfter) + } + // do this in a loop because there's an error case that may necessitate a retry, but not more than once var certChains []acme.Certificate for i := 0; i < 2; i++ { - certChains, err = client.acmeClient.ObtainCertificateUsingCSR(ctx, client.account, csr) + certChains, err = client.acmeClient.ObtainCertificate(ctx, params) if err != nil { var prob acme.Problem if errors.As(err, &prob) && prob.Type == acme.ProblemTypeAccountDoesNotExist { diff --git a/config.go b/config.go index c2a3929..26cf3a4 100644 --- a/config.go +++ b/config.go @@ -34,8 +34,8 @@ import ( "strings" "time" - "github.com/mholt/acmez" - "github.com/mholt/acmez/acme" + "github.com/mholt/acmez/v2" + "github.com/mholt/acmez/v2/acme" "go.uber.org/zap" "golang.org/x/crypto/ocsp" "golang.org/x/net/idna" diff --git a/config_test.go b/config_test.go index 667e87f..0619159 100644 --- a/config_test.go +++ b/config_test.go @@ -20,7 +20,7 @@ import ( "reflect" "testing" - "github.com/mholt/acmez/acme" + "github.com/mholt/acmez/v2/acme" ) func TestSaveCertResource(t *testing.T) { diff --git a/go.mod b/go.mod index 978b204..44bf00d 100644 --- a/go.mod +++ b/go.mod @@ -6,18 +6,18 @@ require ( github.com/caddyserver/zerossl v0.1.1 github.com/klauspost/cpuid/v2 v2.2.7 github.com/libdns/libdns v0.2.2 - github.com/mholt/acmez v1.2.0 + github.com/mholt/acmez/v2 v2.0.0-beta.2 github.com/miekg/dns v1.1.58 github.com/zeebo/blake3 v0.2.3 go.uber.org/zap v1.27.0 - golang.org/x/crypto v0.21.0 - golang.org/x/net v0.22.0 + golang.org/x/crypto v0.22.0 + golang.org/x/net v0.24.0 ) require ( go.uber.org/multierr v1.11.0 // indirect golang.org/x/mod v0.14.0 // indirect - golang.org/x/sys v0.18.0 // indirect + golang.org/x/sys v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.17.0 // indirect ) diff --git a/go.sum b/go.sum index 1e14729..19290f4 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,8 @@ github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuV github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s= github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ= -github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30= -github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE= +github.com/mholt/acmez/v2 v2.0.0-beta.2 h1:GIgGILx8AWN0ePyTd+bjs2WDgNiIWm0nBwDLWp59aHc= +github.com/mholt/acmez/v2 v2.0.0-beta.2/go.mod h1:fX4c9r5jYwMyMsC+7tkYRxHibkOTgta5DIFGoe67e1U= github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4= github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -27,17 +27,17 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= -golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= diff --git a/handshake.go b/handshake.go index 9c923f6..aa970ad 100644 --- a/handshake.go +++ b/handshake.go @@ -25,7 +25,7 @@ import ( "sync" "time" - "github.com/mholt/acmez" + "github.com/mholt/acmez/v2" "go.uber.org/zap" "golang.org/x/crypto/ocsp" ) diff --git a/httphandler.go b/httphandler.go index fc2a880..aa65e67 100644 --- a/httphandler.go +++ b/httphandler.go @@ -18,7 +18,7 @@ import ( "net/http" "strings" - "github.com/mholt/acmez/acme" + "github.com/mholt/acmez/v2/acme" "go.uber.org/zap" ) diff --git a/maintain.go b/maintain.go index a609b63..5773280 100644 --- a/maintain.go +++ b/maintain.go @@ -27,7 +27,7 @@ import ( "strings" "time" - "github.com/mholt/acmez/acme" + "github.com/mholt/acmez/v2/acme" "go.uber.org/zap" "golang.org/x/crypto/ocsp" ) diff --git a/solvers.go b/solvers.go index 9da675f..557f17b 100644 --- a/solvers.go +++ b/solvers.go @@ -30,8 +30,8 @@ import ( "time" "github.com/libdns/libdns" - "github.com/mholt/acmez" - "github.com/mholt/acmez/acme" + "github.com/mholt/acmez/v2" + "github.com/mholt/acmez/v2/acme" "github.com/miekg/dns" "go.uber.org/zap" ) diff --git a/solvers_test.go b/solvers_test.go index 21deaea..15308fa 100644 --- a/solvers_test.go +++ b/solvers_test.go @@ -17,7 +17,7 @@ package certmagic import ( "testing" - "github.com/mholt/acmez/acme" + "github.com/mholt/acmez/v2/acme" ) func Test_challengeKey(t *testing.T) { diff --git a/zerosslissuer.go b/zerosslissuer.go index fab3152..419969d 100644 --- a/zerosslissuer.go +++ b/zerosslissuer.go @@ -26,7 +26,7 @@ import ( "time" "github.com/caddyserver/zerossl" - "github.com/mholt/acmez/acme" + "github.com/mholt/acmez/v2/acme" "go.uber.org/zap" )