Improve handshake logic
- Only load cert from storage (or manager) if allowed to do so (fix #174) - Sync cert loading so storage isn't stampeded (fix #185) - Update dependencies
This commit is contained in:
parent
0dc2834a03
commit
6670b5e1cc
@ -433,7 +433,7 @@ type CertificateResource struct {
|
|||||||
|
|
||||||
// The unique string identifying the issuer of the
|
// The unique string identifying the issuer of the
|
||||||
// certificate; internally useful for storage access.
|
// certificate; internally useful for storage access.
|
||||||
issuerKey string `json:"-"`
|
issuerKey string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NamesKey returns the list of SANs as a single string,
|
// NamesKey returns the list of SANs as a single string,
|
||||||
|
14
config.go
14
config.go
@ -210,13 +210,16 @@ func newWithCache(certCache *Cache, cfg Config) *Config {
|
|||||||
if !cfg.MustStaple {
|
if !cfg.MustStaple {
|
||||||
cfg.MustStaple = Default.MustStaple
|
cfg.MustStaple = Default.MustStaple
|
||||||
}
|
}
|
||||||
if len(cfg.Issuers) == 0 {
|
if cfg.Issuers == nil {
|
||||||
cfg.Issuers = Default.Issuers
|
cfg.Issuers = Default.Issuers
|
||||||
if len(cfg.Issuers) == 0 {
|
if cfg.Issuers == nil {
|
||||||
// at least one issuer is absolutely required
|
// at least one issuer is absolutely required if not nil
|
||||||
cfg.Issuers = []Issuer{NewACMEIssuer(&cfg, DefaultACME)}
|
cfg.Issuers = []Issuer{NewACMEIssuer(&cfg, DefaultACME)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if cfg.Managers == nil {
|
||||||
|
cfg.Managers = Default.Managers
|
||||||
|
}
|
||||||
if cfg.RenewalWindowRatio == 0 {
|
if cfg.RenewalWindowRatio == 0 {
|
||||||
cfg.RenewalWindowRatio = Default.RenewalWindowRatio
|
cfg.RenewalWindowRatio = Default.RenewalWindowRatio
|
||||||
}
|
}
|
||||||
@ -335,6 +338,9 @@ func (cfg *Config) manageAll(ctx context.Context, domainNames []string, async bo
|
|||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if len(cfg.Managers) > 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: consider doing this in a goroutine if async, to utilize multiple cores while loading certs
|
// TODO: consider doing this in a goroutine if async, to utilize multiple cores while loading certs
|
||||||
// otherwise, begin management immediately
|
// otherwise, begin management immediately
|
||||||
@ -589,6 +595,7 @@ func (cfg *Config) obtainCert(ctx context.Context, name string, interactive bool
|
|||||||
CertificatePEM: issuedCert.Certificate,
|
CertificatePEM: issuedCert.Certificate,
|
||||||
PrivateKeyPEM: privKeyPEM,
|
PrivateKeyPEM: privKeyPEM,
|
||||||
IssuerData: issuedCert.Metadata,
|
IssuerData: issuedCert.Metadata,
|
||||||
|
issuerKey: issuerUsed.IssuerKey(),
|
||||||
}
|
}
|
||||||
err = cfg.saveCertResource(ctx, issuerUsed, certRes)
|
err = cfg.saveCertResource(ctx, issuerUsed, certRes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -814,6 +821,7 @@ func (cfg *Config) renewCert(ctx context.Context, name string, force, interactiv
|
|||||||
CertificatePEM: issuedCert.Certificate,
|
CertificatePEM: issuedCert.Certificate,
|
||||||
PrivateKeyPEM: certRes.PrivateKeyPEM,
|
PrivateKeyPEM: certRes.PrivateKeyPEM,
|
||||||
IssuerData: issuedCert.Metadata,
|
IssuerData: issuedCert.Metadata,
|
||||||
|
issuerKey: issuerUsed.IssuerKey(),
|
||||||
}
|
}
|
||||||
err = cfg.saveCertResource(ctx, issuerUsed, newCertRes)
|
err = cfg.saveCertResource(ctx, issuerUsed, newCertRes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
26
go.mod
26
go.mod
@ -1,22 +1,22 @@
|
|||||||
module github.com/caddyserver/certmagic
|
module github.com/caddyserver/certmagic
|
||||||
|
|
||||||
go 1.18
|
go 1.19
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/klauspost/cpuid/v2 v2.1.1
|
github.com/klauspost/cpuid/v2 v2.2.4
|
||||||
github.com/libdns/libdns v0.2.1
|
github.com/libdns/libdns v0.2.1
|
||||||
github.com/mholt/acmez v1.0.4
|
github.com/mholt/acmez v1.1.1
|
||||||
github.com/miekg/dns v1.1.50
|
github.com/miekg/dns v1.1.54
|
||||||
go.uber.org/zap v1.23.0
|
go.uber.org/zap v1.24.0
|
||||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa
|
golang.org/x/crypto v0.8.0
|
||||||
golang.org/x/net v0.7.0
|
golang.org/x/net v0.9.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
go.uber.org/atomic v1.7.0 // indirect
|
go.uber.org/atomic v1.11.0 // indirect
|
||||||
go.uber.org/multierr v1.6.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
golang.org/x/mod v0.10.0 // indirect
|
||||||
golang.org/x/sys v0.5.0 // indirect
|
golang.org/x/sys v0.8.0 // indirect
|
||||||
golang.org/x/text v0.7.0 // indirect
|
golang.org/x/text v0.9.0 // indirect
|
||||||
golang.org/x/tools v0.1.12 // indirect
|
golang.org/x/tools v0.8.0 // indirect
|
||||||
)
|
)
|
||||||
|
104
go.sum
104
go.sum
@ -1,89 +1,35 @@
|
|||||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
||||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
|
||||||
github.com/klauspost/cpuid/v2 v2.1.1 h1:t0wUqjowdm8ezddV5k0tLWVklVuvLJpoHeb4WBdydm0=
|
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||||
github.com/klauspost/cpuid/v2 v2.1.1/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
|
||||||
github.com/libdns/libdns v0.2.1 h1:Wu59T7wSHRgtA0cfxC+n1c/e+O3upJGWytknkmFEDis=
|
github.com/libdns/libdns v0.2.1 h1:Wu59T7wSHRgtA0cfxC+n1c/e+O3upJGWytknkmFEDis=
|
||||||
github.com/libdns/libdns v0.2.1/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
|
github.com/libdns/libdns v0.2.1/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
|
||||||
github.com/mholt/acmez v1.0.4 h1:N3cE4Pek+dSolbsofIkAYz6H1d3pE+2G0os7QHslf80=
|
github.com/mholt/acmez v1.1.1 h1:sYeeYd/EHVm9cSmLdWey5oW/fXFVAq5pNLjSczN2ZUg=
|
||||||
github.com/mholt/acmez v1.0.4/go.mod h1:qFGLZ4u+ehWINeJZjzPlsnjJBCPAADWTcIqE/7DAYQY=
|
github.com/mholt/acmez v1.1.1/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE=
|
||||||
github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
|
github.com/miekg/dns v1.1.54 h1:5jon9mWcb0sFJGpnI99tOMhCPyJ+RPVz5b63MQG0VWI=
|
||||||
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
|
github.com/miekg/dns v1.1.54/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
|
||||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
|
||||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
|
||||||
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
|
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
|
||||||
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
|
||||||
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
|
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
|
||||||
go.uber.org/zap v1.23.0 h1:OjGQ5KQDEUawVHxNwQgPpiypGHOxo2mNZsOqTak4fFY=
|
golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
|
||||||
go.uber.org/zap v1.23.0/go.mod h1:D+nX8jyLsMHMYrln8A0rJjFt/T/9/bGgIhAqxv5URuY=
|
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c=
|
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
|
||||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
|
||||||
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
|
||||||
golang.org/x/net v0.0.0-20220630215102-69896b714898/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
|
||||||
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
|
|
||||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
|
||||||
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
|
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
|
||||||
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
|
||||||
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
|
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
114
handshake.go
114
handshake.go
@ -243,37 +243,6 @@ func (cfg *Config) getCertDuringHandshake(ctx context.Context, hello *tls.Client
|
|||||||
log := logWithRemote(cfg.Logger.Named("handshake"), hello)
|
log := logWithRemote(cfg.Logger.Named("handshake"), hello)
|
||||||
name := cfg.getNameFromClientHello(hello)
|
name := cfg.getNameFromClientHello(hello)
|
||||||
|
|
||||||
// if a swarm of requests comes in for the same domain, avoid pounding storage thousands of times simultaneously
|
|
||||||
// (we do a similar sync strategy for obtaining certificate during handshake)
|
|
||||||
certLoadWaitChansMu.Lock()
|
|
||||||
wait, ok := certLoadWaitChans[name]
|
|
||||||
if ok {
|
|
||||||
// another goroutine is already loading the cert; just wait and we'll get it from the in-memory cache
|
|
||||||
certLoadWaitChansMu.Unlock()
|
|
||||||
|
|
||||||
// TODO: see if we can get a proper context in here, for true cancellation
|
|
||||||
timeout := time.NewTimer(2 * time.Minute)
|
|
||||||
select {
|
|
||||||
case <-timeout.C:
|
|
||||||
return Certificate{}, fmt.Errorf("timed out waiting to load certificate for %s", name)
|
|
||||||
case <-wait:
|
|
||||||
timeout.Stop()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// no other goroutine is currently trying to load this cert
|
|
||||||
wait = make(chan struct{})
|
|
||||||
certLoadWaitChans[name] = wait
|
|
||||||
certLoadWaitChansMu.Unlock()
|
|
||||||
|
|
||||||
// unblock others and clean up when we're done
|
|
||||||
defer func() {
|
|
||||||
certLoadWaitChansMu.Lock()
|
|
||||||
close(wait)
|
|
||||||
delete(certLoadWaitChans, name)
|
|
||||||
certLoadWaitChansMu.Unlock()
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
// First check our in-memory cache to see if we've already loaded it
|
// First check our in-memory cache to see if we've already loaded it
|
||||||
cert, matched, defaulted := cfg.getCertificateFromCache(hello)
|
cert, matched, defaulted := cfg.getCertificateFromCache(hello)
|
||||||
if matched {
|
if matched {
|
||||||
@ -291,6 +260,49 @@ func (cfg *Config) getCertDuringHandshake(ctx context.Context, hello *tls.Client
|
|||||||
return cert, nil
|
return cert, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// By this point, we need to load or obtain a certificate. If a swarm of requests comes in for the same
|
||||||
|
// domain, avoid pounding manager or storage thousands of times simultaneously. We do a similar sync
|
||||||
|
// strategy for obtaining certificate during handshake.
|
||||||
|
certLoadWaitChansMu.Lock()
|
||||||
|
wait, ok := certLoadWaitChans[name]
|
||||||
|
if ok {
|
||||||
|
// another goroutine is already loading the cert; just wait and we'll get it from the in-memory cache
|
||||||
|
certLoadWaitChansMu.Unlock()
|
||||||
|
|
||||||
|
timeout := time.NewTimer(2 * time.Minute) // TODO: have Caddy use the context param to establish a timeout
|
||||||
|
select {
|
||||||
|
case <-timeout.C:
|
||||||
|
return Certificate{}, fmt.Errorf("timed out waiting to load certificate for %s", name)
|
||||||
|
case <-ctx.Done():
|
||||||
|
timeout.Stop()
|
||||||
|
return Certificate{}, ctx.Err()
|
||||||
|
case <-wait:
|
||||||
|
timeout.Stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg.getCertDuringHandshake(ctx, hello, false, false)
|
||||||
|
} else {
|
||||||
|
// no other goroutine is currently trying to load this cert
|
||||||
|
wait = make(chan struct{})
|
||||||
|
certLoadWaitChans[name] = wait
|
||||||
|
certLoadWaitChansMu.Unlock()
|
||||||
|
|
||||||
|
// unblock others and clean up when we're done
|
||||||
|
defer func() {
|
||||||
|
certLoadWaitChansMu.Lock()
|
||||||
|
close(wait)
|
||||||
|
delete(certLoadWaitChans, name)
|
||||||
|
certLoadWaitChansMu.Unlock()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure a certificate is allowed for the given name. If not, it doesn't
|
||||||
|
// make sense to try loading one from storage (issue #185), getting it from a
|
||||||
|
// certificate manager, or obtaining one from an issuer.
|
||||||
|
if err := cfg.checkIfCertShouldBeObtained(name, false); err != nil {
|
||||||
|
return Certificate{}, fmt.Errorf("certificate is not allowed for server name %s: %v", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
// If an external Manager is configured, try to get it from them.
|
// If an external Manager is configured, try to get it from them.
|
||||||
// Only continue to use our own logic if it returns empty+nil.
|
// Only continue to use our own logic if it returns empty+nil.
|
||||||
externalCert, err := cfg.getCertFromAnyCertManager(ctx, hello, log)
|
externalCert, err := cfg.getCertFromAnyCertManager(ctx, hello, log)
|
||||||
@ -320,11 +332,7 @@ func (cfg *Config) getCertDuringHandshake(ctx context.Context, hello *tls.Client
|
|||||||
loadDynamically := cfg.OnDemand != nil || cacheAlmostFull
|
loadDynamically := cfg.OnDemand != nil || cacheAlmostFull
|
||||||
|
|
||||||
if loadDynamically && loadIfNecessary {
|
if loadDynamically && loadIfNecessary {
|
||||||
// Then check to see if we have one on disk
|
// Check to see if we have one on disk
|
||||||
// TODO: As suggested here, https://caddy.community/t/error-tls-alert-internal-error-592-again/13272/30?u=matt,
|
|
||||||
// it might be a good idea to check with the DecisionFunc or allowlist first before even loading the certificate
|
|
||||||
// from storage, since if we can't renew it, why should we even try serving it (it will just get evicted after
|
|
||||||
// we get a return value of false anyway)? See issue #174
|
|
||||||
loadedCert, err := cfg.CacheManagedCertificate(ctx, name)
|
loadedCert, err := cfg.CacheManagedCertificate(ctx, name)
|
||||||
if errors.Is(err, fs.ErrNotExist) {
|
if errors.Is(err, fs.ErrNotExist) {
|
||||||
// If no exact match, try a wildcard variant, which is something we can still use
|
// If no exact match, try a wildcard variant, which is something we can still use
|
||||||
@ -400,19 +408,20 @@ func (cfg *Config) optionalMaintenance(ctx context.Context, log *zap.Logger, cer
|
|||||||
// checkIfCertShouldBeObtained checks to see if an on-demand TLS certificate
|
// checkIfCertShouldBeObtained checks to see if an on-demand TLS certificate
|
||||||
// should be obtained for a given domain based upon the config settings. If
|
// should be obtained for a given domain based upon the config settings. If
|
||||||
// a non-nil error is returned, do not issue a new certificate for name.
|
// a non-nil error is returned, do not issue a new certificate for name.
|
||||||
func (cfg *Config) checkIfCertShouldBeObtained(name string) error {
|
func (cfg *Config) checkIfCertShouldBeObtained(name string, requireOnDemand bool) error {
|
||||||
if cfg.OnDemand == nil {
|
if requireOnDemand && cfg.OnDemand == nil {
|
||||||
return fmt.Errorf("not configured for on-demand certificate issuance")
|
return fmt.Errorf("not configured for on-demand certificate issuance")
|
||||||
}
|
}
|
||||||
if !SubjectQualifiesForCert(name) {
|
if !SubjectQualifiesForCert(name) {
|
||||||
return fmt.Errorf("subject name does not qualify for certificate: %s", name)
|
return fmt.Errorf("subject name does not qualify for certificate: %s", name)
|
||||||
}
|
}
|
||||||
if cfg.OnDemand.DecisionFunc != nil {
|
if cfg.OnDemand != nil {
|
||||||
return cfg.OnDemand.DecisionFunc(name)
|
if cfg.OnDemand.DecisionFunc != nil {
|
||||||
}
|
return fmt.Errorf("decision func: %w", cfg.OnDemand.DecisionFunc(name))
|
||||||
if len(cfg.OnDemand.hostWhitelist) > 0 &&
|
}
|
||||||
!cfg.OnDemand.whitelistContains(name) {
|
if len(cfg.OnDemand.hostWhitelist) > 0 && !cfg.OnDemand.whitelistContains(name) {
|
||||||
return fmt.Errorf("certificate for '%s' is not managed", name)
|
return fmt.Errorf("certificate for '%s' is not managed", name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -465,13 +474,6 @@ func (cfg *Config) obtainOnDemandCertificate(ctx context.Context, hello *tls.Cli
|
|||||||
obtainCertWaitChansMu.Unlock()
|
obtainCertWaitChansMu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the certificate should be obtained based on config
|
|
||||||
err := cfg.checkIfCertShouldBeObtained(name)
|
|
||||||
if err != nil {
|
|
||||||
unblockWaiters()
|
|
||||||
return Certificate{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Info("obtaining new certificate", zap.String("server_name", name))
|
log.Info("obtaining new certificate", zap.String("server_name", name))
|
||||||
|
|
||||||
// TODO: we are only adding a timeout because we don't know if the context passed in is actually cancelable...
|
// TODO: we are only adding a timeout because we don't know if the context passed in is actually cancelable...
|
||||||
@ -481,7 +483,7 @@ func (cfg *Config) obtainOnDemandCertificate(ctx context.Context, hello *tls.Cli
|
|||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// Obtain the certificate
|
// Obtain the certificate
|
||||||
err = cfg.ObtainCertAsync(ctx, name)
|
err := cfg.ObtainCertAsync(ctx, name)
|
||||||
|
|
||||||
// immediately unblock anyone waiting for it; doing this in
|
// immediately unblock anyone waiting for it; doing this in
|
||||||
// a defer would risk deadlock because of the recursive call
|
// a defer would risk deadlock because of the recursive call
|
||||||
@ -649,10 +651,8 @@ func (cfg *Config) renewDynamicCertificate(ctx context.Context, hello *tls.Clien
|
|||||||
renewAndReload := func(ctx context.Context, cancel context.CancelFunc) (Certificate, error) {
|
renewAndReload := func(ctx context.Context, cancel context.CancelFunc) (Certificate, error) {
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
log.Info("attempting certificate renewal")
|
// Make sure a certificate for this name should be renewed on-demand
|
||||||
|
err := cfg.checkIfCertShouldBeObtained(name, true)
|
||||||
// Make sure a certificate for this name should be obtained on-demand
|
|
||||||
err := cfg.checkIfCertShouldBeObtained(name)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// if not, remove from cache (it will be deleted from storage later)
|
// if not, remove from cache (it will be deleted from storage later)
|
||||||
cfg.certCache.mu.Lock()
|
cfg.certCache.mu.Lock()
|
||||||
@ -667,6 +667,8 @@ func (cfg *Config) renewDynamicCertificate(ctx context.Context, hello *tls.Clien
|
|||||||
return Certificate{}, err
|
return Certificate{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Info("attempting certificate renewal")
|
||||||
|
|
||||||
// otherwise, renew with issuer, etc.
|
// otherwise, renew with issuer, etc.
|
||||||
var newCert Certificate
|
var newCert Certificate
|
||||||
if revoked {
|
if revoked {
|
||||||
|
@ -33,7 +33,7 @@ func NewRateLimiter(maxEvents int, window time.Duration) *RingBufferRateLimiter
|
|||||||
panic("maxEvents cannot be less than zero")
|
panic("maxEvents cannot be less than zero")
|
||||||
}
|
}
|
||||||
if maxEvents == 0 && window != 0 {
|
if maxEvents == 0 && window != 0 {
|
||||||
panic("invalid configuration: maxEvents = 0 and window != 0 would not allow any events")
|
panic("NewRateLimiter: invalid configuration: maxEvents = 0 and window != 0 would not allow any events")
|
||||||
}
|
}
|
||||||
rbrl := &RingBufferRateLimiter{
|
rbrl := &RingBufferRateLimiter{
|
||||||
window: window,
|
window: window,
|
||||||
@ -144,14 +144,15 @@ func (r *RingBufferRateLimiter) MaxEvents() int {
|
|||||||
// the oldest events will be forgotten. If the new limit is
|
// the oldest events will be forgotten. If the new limit is
|
||||||
// higher, the window will suddenly have capacity for new
|
// higher, the window will suddenly have capacity for new
|
||||||
// reservations. It panics if maxEvents is 0 and window size
|
// reservations. It panics if maxEvents is 0 and window size
|
||||||
// is not zero.
|
// is not zero; if setting both the events limit and the
|
||||||
|
// window size to 0, call SetWindow() first.
|
||||||
func (r *RingBufferRateLimiter) SetMaxEvents(maxEvents int) {
|
func (r *RingBufferRateLimiter) SetMaxEvents(maxEvents int) {
|
||||||
newRing := make([]time.Time, maxEvents)
|
newRing := make([]time.Time, maxEvents)
|
||||||
r.mu.Lock()
|
r.mu.Lock()
|
||||||
defer r.mu.Unlock()
|
defer r.mu.Unlock()
|
||||||
|
|
||||||
if r.window != 0 && maxEvents == 0 {
|
if r.window != 0 && maxEvents == 0 {
|
||||||
panic("invalid configuration: maxEvents = 0 and window != 0 would not allow any events")
|
panic("SetMaxEvents: invalid configuration: maxEvents = 0 and window != 0 would not allow any events")
|
||||||
}
|
}
|
||||||
|
|
||||||
// only make the change if the new limit is different
|
// only make the change if the new limit is different
|
||||||
@ -203,7 +204,7 @@ func (r *RingBufferRateLimiter) SetWindow(window time.Duration) {
|
|||||||
r.mu.Lock()
|
r.mu.Lock()
|
||||||
defer r.mu.Unlock()
|
defer r.mu.Unlock()
|
||||||
if window != 0 && len(r.ring) == 0 {
|
if window != 0 && len(r.ring) == 0 {
|
||||||
panic("invalid configuration: maxEvents = 0 and window != 0 would not allow any events")
|
panic("SetWindow: invalid configuration: maxEvents = 0 and window != 0 would not allow any events")
|
||||||
}
|
}
|
||||||
r.window = window
|
r.window = window
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user