mirror of
https://github.com/caddyserver/caddy.git
synced 2024-11-29 04:10:16 +08:00
Scope TLS max_certs to site config instead of global
This commit is contained in:
parent
1e1e69b90f
commit
af48bbd234
|
@ -75,7 +75,7 @@ type Config struct {
|
|||
CAUrl string
|
||||
|
||||
// The host (ONLY the host, not port) to listen
|
||||
//on if necessary to start a a listener to solve
|
||||
// on if necessary to start a listener to solve
|
||||
// an ACME challenge
|
||||
ListenHost string
|
||||
|
||||
|
@ -105,6 +105,22 @@ type Config struct {
|
|||
// implementors are encouraged to cache any heavy
|
||||
// instantiations.
|
||||
StorageCreator StorageCreator
|
||||
|
||||
// The state needed to operate on-demand TLS
|
||||
OnDemandState OnDemandState
|
||||
}
|
||||
|
||||
// OnDemandState contains some state relevant for providing
|
||||
// on-demand TLS.
|
||||
type OnDemandState struct {
|
||||
// The number of certificates that have been issued on-demand
|
||||
// by this config. It is only safe to modify this count atomically.
|
||||
// If it reaches MaxObtain, on-demand issuances must fail.
|
||||
ObtainedCount int32
|
||||
|
||||
// Based on max_certs in tls config, it specifies the
|
||||
// maximum number of certificates that can be issued.
|
||||
MaxObtain int32
|
||||
}
|
||||
|
||||
// ObtainCert obtains a certificate for c.Hostname, as long as a certificate
|
||||
|
|
|
@ -100,7 +100,7 @@ func (cg configGroup) getCertDuringHandshake(name string, loadIfNecessary, obtai
|
|||
name = strings.ToLower(name)
|
||||
|
||||
// Make sure aren't over any applicable limits
|
||||
err := cg.checkLimitsForObtainingNewCerts(name)
|
||||
err := cg.checkLimitsForObtainingNewCerts(name, cfg)
|
||||
if err != nil {
|
||||
return Certificate{}, err
|
||||
}
|
||||
|
@ -127,10 +127,11 @@ func (cg configGroup) getCertDuringHandshake(name string, loadIfNecessary, obtai
|
|||
// now according to mitigating factors we keep track of and preferences the
|
||||
// user has set. If a non-nil error is returned, do not issue a new certificate
|
||||
// for name.
|
||||
func (cg configGroup) checkLimitsForObtainingNewCerts(name string) error {
|
||||
func (cg configGroup) checkLimitsForObtainingNewCerts(name string, cfg *Config) error {
|
||||
// User can set hard limit for number of certs for the process to issue
|
||||
if onDemandMaxIssue > 0 && atomic.LoadInt32(OnDemandIssuedCount) >= onDemandMaxIssue {
|
||||
return fmt.Errorf("%s: maximum certificates issued (%d)", name, onDemandMaxIssue)
|
||||
if cfg.OnDemandState.MaxObtain > 0 &&
|
||||
atomic.LoadInt32(&cfg.OnDemandState.ObtainedCount) >= cfg.OnDemandState.MaxObtain {
|
||||
return fmt.Errorf("%s: maximum certificates issued (%d)", name, cfg.OnDemandState.MaxObtain)
|
||||
}
|
||||
|
||||
// Make sure name hasn't failed a challenge recently
|
||||
|
@ -146,7 +147,7 @@ func (cg configGroup) checkLimitsForObtainingNewCerts(name string) error {
|
|||
lastIssueTimeMu.Lock()
|
||||
since := time.Since(lastIssueTime)
|
||||
lastIssueTimeMu.Unlock()
|
||||
if atomic.LoadInt32(OnDemandIssuedCount) >= 10 && since < 10*time.Minute {
|
||||
if atomic.LoadInt32(&cfg.OnDemandState.ObtainedCount) >= 10 && since < 10*time.Minute {
|
||||
return fmt.Errorf("%s: throttled; last certificate was obtained %v ago", name, since)
|
||||
}
|
||||
|
||||
|
@ -202,7 +203,7 @@ func (cg configGroup) obtainOnDemandCertificate(name string, cfg *Config) (Certi
|
|||
}
|
||||
|
||||
// Success - update counters and stuff
|
||||
atomic.AddInt32(OnDemandIssuedCount, 1)
|
||||
atomic.AddInt32(&cfg.OnDemandState.ObtainedCount, 1)
|
||||
lastIssueTimeMu.Lock()
|
||||
lastIssueTime = time.Now()
|
||||
lastIssueTimeMu.Unlock()
|
||||
|
@ -286,18 +287,6 @@ func (cg configGroup) renewDynamicCertificate(name string, cfg *Config) (Certifi
|
|||
var obtainCertWaitChans = make(map[string]chan struct{})
|
||||
var obtainCertWaitChansMu sync.Mutex
|
||||
|
||||
// OnDemandIssuedCount is the number of certificates that have been issued
|
||||
// on-demand by this process. It is only safe to modify this count atomically.
|
||||
// If it reaches onDemandMaxIssue, on-demand issuances will fail.
|
||||
var OnDemandIssuedCount = new(int32)
|
||||
|
||||
// onDemandMaxIssue is set based on max_certs in tls config. It specifies the
|
||||
// maximum number of certificates that can be issued.
|
||||
// TODO: This applies globally, but we should probably make a server-specific
|
||||
// way to keep track of these limits and counts, since it's specified in the
|
||||
// Caddyfile...
|
||||
var onDemandMaxIssue int32
|
||||
|
||||
// failedIssuance is a set of names that we recently failed to get a
|
||||
// certificate for from the ACME CA. They are removed after some time.
|
||||
// When a name is in this map, do not issue a certificate for it on-demand.
|
||||
|
|
|
@ -156,9 +156,7 @@ func setupTLS(c *caddy.Controller) error {
|
|||
if err != nil || maxCertsNum < 1 {
|
||||
return c.Err("max_certs must be a positive integer")
|
||||
}
|
||||
if onDemandMaxIssue == 0 || int32(maxCertsNum) < onDemandMaxIssue { // keep the minimum; TODO: We have to do this because it is global; should be per-server or per-vhost...
|
||||
onDemandMaxIssue = int32(maxCertsNum)
|
||||
}
|
||||
config.OnDemandState.MaxObtain = int32(maxCertsNum)
|
||||
}
|
||||
|
||||
// don't try to load certificates unless we're supposed to
|
||||
|
|
Loading…
Reference in New Issue
Block a user