caddytls: Allow on-demand w/o ask for internal-only

This commit is contained in:
Matthew Holt 2023-03-14 10:29:27 -06:00
parent b97c76fb47
commit a7af7c486e
No known key found for this signature in database
GPG key ID: 2A349DD577D586A5

View file

@ -165,40 +165,6 @@ func (ap *AutomationPolicy) Provision(tlsApp *TLS) error {
ap.storage = cmStorage ap.storage = cmStorage
} }
// on-demand TLS
var ond *certmagic.OnDemandConfig
if ap.OnDemand {
// ask endpoint is now required after a number of negligence cases causing abuse
if tlsApp.Automation == nil || tlsApp.Automation.OnDemand == nil || tlsApp.Automation.OnDemand.Ask == "" {
return fmt.Errorf("on-demand TLS cannot be enabled without an 'ask' endpoint to prevent abuse; please refer to documentation for details")
}
ond = &certmagic.OnDemandConfig{
DecisionFunc: func(name string) error {
if err := onDemandAskRequest(tlsApp.logger, tlsApp.Automation.OnDemand.Ask, name); err != nil {
// distinguish true errors from denials, because it's important to elevate actual errors
if errors.Is(err, errAskDenied) {
tlsApp.logger.Debug("certificate issuance denied",
zap.String("ask_endpoint", tlsApp.Automation.OnDemand.Ask),
zap.String("domain", name),
zap.Error(err))
} else {
tlsApp.logger.Error("request to 'ask' endpoint failed",
zap.String("ask_endpoint", tlsApp.Automation.OnDemand.Ask),
zap.String("domain", name),
zap.Error(err))
}
return err
}
// check the rate limiter last because
// doing so makes a reservation
if !onDemandRateLimiter.Allow() {
return fmt.Errorf("on-demand rate limit exceeded")
}
return nil
},
}
}
// we don't store loaded modules directly in the certmagic config since // we don't store loaded modules directly in the certmagic config since
// policy provisioning may happen more than once (during auto-HTTPS) and // policy provisioning may happen more than once (during auto-HTTPS) and
// loading a module clears its config bytes; thus, load the module and // loading a module clears its config bytes; thus, load the module and
@ -255,6 +221,40 @@ func (ap *AutomationPolicy) Provision(tlsApp *TLS) error {
storage = tlsApp.ctx.Storage() storage = tlsApp.ctx.Storage()
} }
// on-demand TLS
var ond *certmagic.OnDemandConfig
if ap.OnDemand {
// ask endpoint is now required after a number of negligence cases causing abuse
if !ap.onlyInternalIssuer() && (tlsApp.Automation == nil || tlsApp.Automation.OnDemand == nil || tlsApp.Automation.OnDemand.Ask == "") {
return fmt.Errorf("on-demand TLS cannot be enabled without an 'ask' endpoint to prevent abuse; please refer to documentation for details")
}
ond = &certmagic.OnDemandConfig{
DecisionFunc: func(name string) error {
if err := onDemandAskRequest(tlsApp.logger, tlsApp.Automation.OnDemand.Ask, name); err != nil {
// distinguish true errors from denials, because it's important to elevate actual errors
if errors.Is(err, errAskDenied) {
tlsApp.logger.Debug("certificate issuance denied",
zap.String("ask_endpoint", tlsApp.Automation.OnDemand.Ask),
zap.String("domain", name),
zap.Error(err))
} else {
tlsApp.logger.Error("request to 'ask' endpoint failed",
zap.String("ask_endpoint", tlsApp.Automation.OnDemand.Ask),
zap.String("domain", name),
zap.Error(err))
}
return err
}
// check the rate limiter last because
// doing so makes a reservation
if !onDemandRateLimiter.Allow() {
return fmt.Errorf("on-demand rate limit exceeded")
}
return nil
},
}
}
template := certmagic.Config{ template := certmagic.Config{
MustStaple: ap.MustStaple, MustStaple: ap.MustStaple,
RenewalWindowRatio: ap.RenewalWindowRatio, RenewalWindowRatio: ap.RenewalWindowRatio,
@ -286,6 +286,14 @@ func (ap *AutomationPolicy) Provision(tlsApp *TLS) error {
return nil return nil
} }
func (ap *AutomationPolicy) onlyInternalIssuer() bool {
if len(ap.Issuers) != 1 {
return false
}
_, ok := ap.Issuers[0].(*InternalIssuer)
return ok
}
// DefaultIssuers returns empty Issuers (not provisioned) to be used as defaults. // DefaultIssuers returns empty Issuers (not provisioned) to be used as defaults.
// This function is experimental and has no compatibility promises. // This function is experimental and has no compatibility promises.
func DefaultIssuers() []certmagic.Issuer { func DefaultIssuers() []certmagic.Issuer {