From 269b1e9aa34b2b02911f8746e7b6a162cd8222cf Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Thu, 20 Jun 2019 20:36:29 -0600 Subject: tls: Improve (and fix) on-demand configuration --- modules/caddytls/tls.go | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) (limited to 'modules/caddytls/tls.go') diff --git a/modules/caddytls/tls.go b/modules/caddytls/tls.go index 0614d24..c84118a 100644 --- a/modules/caddytls/tls.go +++ b/modules/caddytls/tls.go @@ -5,10 +5,12 @@ import ( "encoding/json" "fmt" "net/http" + "time" "github.com/caddyserver/caddy" "github.com/go-acme/lego/challenge" "github.com/mholt/certmagic" + "golang.org/x/time/rate" ) func init() { @@ -71,6 +73,16 @@ func (t *TLS) Provision(ctx caddy.Context) error { return fmt.Errorf("provisioning session tickets configuration: %v", err) } + // on-demand rate limiting + if t.Automation.OnDemand != nil && t.Automation.OnDemand.RateLimit != nil { + limit := rate.Every(time.Duration(t.Automation.OnDemand.RateLimit.Interval)) + // TODO: Burst size is not updated, see https://github.com/golang/go/issues/23575 + onDemandRateLimiter.SetLimit(limit) + } else { + // if no rate limit is specified, be sure to remove any existing limit + onDemandRateLimiter.SetLimit(0) + } + return nil } @@ -178,6 +190,7 @@ type CertificateLoader interface { // construction and use of ACME clients. type AutomationConfig struct { Policies []AutomationPolicy `json:"policies,omitempty"` + OnDemand *OnDemandConfig `json:"on_demand,omitempty"` } // AutomationPolicy designates the policy for automating the @@ -189,6 +202,9 @@ type AutomationPolicy struct { Management managerMaker `json:"-"` } +// makeCertMagicConfig converts ap into a CertMagic config. Passing onDemand +// is necessary because the automation policy does not have convenient access +// to the TLS app's global on-demand policies; func (ap AutomationPolicy) makeCertMagicConfig(ctx caddy.Context) certmagic.Config { // default manager (ACME) is a special case because of how CertMagic is designed // TODO: refactor certmagic so that ACME manager is not a special case by extracting @@ -226,10 +242,14 @@ type TLSALPNChallengeConfig struct { // OnDemandConfig configures on-demand TLS, for obtaining // needed certificates at handshake-time. type OnDemandConfig struct { - // TODO: MaxCertificates state might not endure reloads... - // MaxCertificates int `json:"max_certificates,omitempty"` - AskURL string `json:"ask_url,omitempty"` - AskStarlark string `json:"ask_starlark,omitempty"` + RateLimit *RateLimit `json:"rate_limit,omitempty"` + Ask string `json:"ask,omitempty"` +} + +// RateLimit specifies an interval with optional burst size. +type RateLimit struct { + Interval caddy.Duration `json:"interval,omitempty"` + Burst int `json:"burst,omitempty"` } // managerMaker makes a certificate manager. @@ -237,4 +257,15 @@ type managerMaker interface { newManager(interactive bool) (certmagic.Manager, error) } +// These perpetual values are used for on-demand TLS. +var ( + onDemandRateLimiter = rate.NewLimiter(0, 1) + onDemandAskClient = &http.Client{ + Timeout: 10 * time.Second, + CheckRedirect: func(req *http.Request, via []*http.Request) error { + return fmt.Errorf("following http redirects is not allowed") + }, + } +) + const automateKey = "automate" -- cgit v1.2.3