Skip to content

Commit 4a09cf0

Browse files
authored
caddytls: Sync distributed storage cleaning (#5940)
* caddytls: Log out remote addr to detect abuse * caddytls: Sync distributed storage cleaning * Handle errors * Update certmagic to fix tiny bug * Split off port when logging remote IP * Upgrade CertMagic
1 parent b24ae63 commit 4a09cf0

File tree

5 files changed

+36
-21
lines changed

5 files changed

+36
-21
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ require (
77
github.com/Masterminds/sprig/v3 v3.2.3
88
github.com/alecthomas/chroma/v2 v2.9.1
99
github.com/aryann/difflib v0.0.0-20210328193216-ff5ff6dc229b
10-
github.com/caddyserver/certmagic v0.19.3-0.20231030175448-e8e6167a2a51
10+
github.com/caddyserver/certmagic v0.20.0
1111
github.com/dustin/go-humanize v1.0.1
1212
github.com/go-chi/chi/v5 v5.0.10
1313
github.com/google/cel-go v0.15.1

go.sum

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
6161
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
6262
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
6363
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
64-
github.com/caddyserver/certmagic v0.19.2 h1:HZd1AKLx4592MalEGQS39DKs2ZOAJCEM/xYPMQ2/ui0=
65-
github.com/caddyserver/certmagic v0.19.2/go.mod h1:fsL01NomQ6N+kE2j37ZCnig2MFosG+MIO4ztnmG/zz8=
66-
github.com/caddyserver/certmagic v0.19.3-0.20231030175448-e8e6167a2a51 h1:9gmY8uzVBgUqJPjGBHMikvrxoyA+Ctu1u5WeVk5ktQ0=
67-
github.com/caddyserver/certmagic v0.19.3-0.20231030175448-e8e6167a2a51/go.mod h1:N4sXgpICQUskEWpj7zVzvWD41p3NYacrNoZYiRM2jTg=
64+
github.com/caddyserver/certmagic v0.20.0 h1:bTw7LcEZAh9ucYCRXyCpIrSAGplplI0vGYJ4BpCQ/Fc=
65+
github.com/caddyserver/certmagic v0.20.0/go.mod h1:N4sXgpICQUskEWpj7zVzvWD41p3NYacrNoZYiRM2jTg=
6866
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
6967
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
7068
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=

modules/caddytls/acmeissuer.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@ package caddytls
1616

1717
import (
1818
"context"
19+
"crypto/tls"
1920
"crypto/x509"
2021
"errors"
2122
"fmt"
23+
"net"
2224
"net/url"
2325
"os"
2426
"strconv"
@@ -496,7 +498,7 @@ func (iss *ACMEIssuer) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
496498
// to see if a certificate can be obtained for name.
497499
// The certificate request should be denied if this
498500
// returns an error.
499-
func onDemandAskRequest(logger *zap.Logger, ask string, name string) error {
501+
func onDemandAskRequest(ctx context.Context, logger *zap.Logger, ask string, name string) error {
500502
askURL, err := url.Parse(ask)
501503
if err != nil {
502504
return fmt.Errorf("parsing ask URL: %v", err)
@@ -513,7 +515,17 @@ func onDemandAskRequest(logger *zap.Logger, ask string, name string) error {
513515
}
514516
resp.Body.Close()
515517

518+
// logging out the client IP can be useful for servers that want to count
519+
// attempts from clients to detect patterns of abuse
520+
var clientIP string
521+
if hello, ok := ctx.Value(certmagic.ClientHelloInfoCtxKey).(*tls.ClientHelloInfo); ok && hello != nil {
522+
if remote := hello.Conn.RemoteAddr(); remote != nil {
523+
clientIP, _, _ = net.SplitHostPort(remote.String())
524+
}
525+
}
526+
516527
logger.Debug("response from ask endpoint",
528+
zap.String("client_ip", clientIP),
517529
zap.String("domain", name),
518530
zap.String("url", askURLString),
519531
zap.Int("status", resp.StatusCode))

modules/caddytls/automation.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ func (ap *AutomationPolicy) Provision(tlsApp *TLS) error {
256256
if tlsApp.Automation == nil || tlsApp.Automation.OnDemand == nil {
257257
return nil
258258
}
259-
if err := onDemandAskRequest(tlsApp.logger, tlsApp.Automation.OnDemand.Ask, name); err != nil {
259+
if err := onDemandAskRequest(ctx, tlsApp.logger, tlsApp.Automation.OnDemand.Ask, name); err != nil {
260260
// distinguish true errors from denials, because it's important to elevate actual errors
261261
if errors.Is(err, errAskDenied) {
262262
tlsApp.logger.Debug("certificate issuance denied",

modules/caddytls/tls.go

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,10 @@ func (t *TLS) cleanStorageUnits() {
551551
storageCleanMu.Lock()
552552
defer storageCleanMu.Unlock()
553553

554+
// TODO: This check might not be needed anymore now that CertMagic syncs
555+
// and throttles storage cleaning globally across the cluster.
556+
// The original comment below might be outdated:
557+
//
554558
// If storage was cleaned recently, don't do it again for now. Although the ticker
555559
// calling this function drops missed ticks for us, config reloads discard the old
556560
// ticker and replace it with a new one, possibly invoking a cleaning to happen again
@@ -563,35 +567,36 @@ func (t *TLS) cleanStorageUnits() {
563567
return
564568
}
565569

570+
id, err := caddy.InstanceID()
571+
if err != nil {
572+
t.logger.Warn("unable to get instance ID; storage clean stamps will be incomplete", zap.Error(err))
573+
}
566574
options := certmagic.CleanStorageOptions{
575+
Logger: t.logger,
576+
InstanceID: id.String(),
577+
Interval: t.storageCleanInterval(),
567578
OCSPStaples: true,
568579
ExpiredCerts: true,
569580
ExpiredCertGracePeriod: 24 * time.Hour * 14,
570581
}
571582

572-
// avoid cleaning same storage more than once per cleaning cycle
573-
storagesCleaned := make(map[string]struct{})
574-
575583
// start with the default/global storage
576-
storage := t.ctx.Storage()
577-
storageStr := fmt.Sprintf("%v", storage)
578-
t.logger.Info("cleaning storage unit", zap.String("description", storageStr))
579-
certmagic.CleanStorage(t.ctx, storage, options)
580-
storagesCleaned[storageStr] = struct{}{}
584+
err = certmagic.CleanStorage(t.ctx, t.ctx.Storage(), options)
585+
if err != nil {
586+
// probably don't want to return early, since we should still
587+
// see if any other storages can get cleaned up
588+
t.logger.Error("could not clean default/global storage", zap.Error(err))
589+
}
581590

582591
// then clean each storage defined in ACME automation policies
583592
if t.Automation != nil {
584593
for _, ap := range t.Automation.Policies {
585594
if ap.storage == nil {
586595
continue
587596
}
588-
storageStr := fmt.Sprintf("%v", ap.storage)
589-
if _, ok := storagesCleaned[storageStr]; ok {
590-
continue
597+
if err := certmagic.CleanStorage(t.ctx, ap.storage, options); err != nil {
598+
t.logger.Error("could not clean storage configured in automation policy", zap.Error(err))
591599
}
592-
t.logger.Info("cleaning storage unit", zap.String("description", storageStr))
593-
certmagic.CleanStorage(t.ctx, ap.storage, options)
594-
storagesCleaned[storageStr] = struct{}{}
595600
}
596601
}
597602

0 commit comments

Comments
 (0)