From 4430756d5c3047564c4d5d72793de6685ba3efda Mon Sep 17 00:00:00 2001 From: Zen Dodd Date: Sat, 18 Apr 2026 06:56:42 +1000 Subject: [PATCH] admin: Redact sensitive request headers in API logs (#7578) * admin: Redact sensitive request headers in API logs * Fix govulncheck and typed atomic lint failures * Sync Go module metadata after dependency downgrade --- admin.go | 4 +- admin_test.go | 47 ++++++++++++++++ go.mod | 32 +++++------ go.sum | 72 ++++++++++++------------- internal/logmarshalers.go | 54 +++++++++++++++++++ modules/caddyhttp/marshalers.go | 47 +++------------- modules/caddyhttp/reverseproxy/hosts.go | 3 +- modules/logging/filters.go | 26 ++++----- modules/logging/filters_test.go | 32 +++++------ 9 files changed, 192 insertions(+), 125 deletions(-) create mode 100644 internal/logmarshalers.go diff --git a/admin.go b/admin.go index 9c9102120..a93595416 100644 --- a/admin.go +++ b/admin.go @@ -45,6 +45,8 @@ import ( "github.com/prometheus/client_golang/prometheus" "go.uber.org/zap" "go.uber.org/zap/zapcore" + + "github.com/caddyserver/caddy/v2/internal" ) // testCertMagicStorageOverride is a package-level test hook. Tests may set @@ -800,7 +802,7 @@ func (h adminHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { zap.String("uri", r.RequestURI), zap.String("remote_ip", ip), zap.String("remote_port", port), - zap.Reflect("headers", r.Header), + zap.Object("headers", internal.LoggableHTTPHeader{Header: r.Header}), ) if r.TLS != nil { log = log.With( diff --git a/admin_test.go b/admin_test.go index 97dc76f4d..3801c301a 100644 --- a/admin_test.go +++ b/admin_test.go @@ -31,6 +31,8 @@ import ( "github.com/caddyserver/certmagic" "github.com/prometheus/client_golang/prometheus" dto "github.com/prometheus/client_model/go" + "go.uber.org/zap" + "go.uber.org/zap/zaptest/observer" ) var testCfg = []byte(`{ @@ -242,6 +244,51 @@ func TestAdminHandlerErrorHandling(t *testing.T) { } } +func TestAdminHandlerServeHTTPRedactsSensitiveHeadersInLogs(t *testing.T) { + core, logs := observer.New(zap.InfoLevel) + + defaultLoggerMu.Lock() + origLogger := defaultLogger.logger + defaultLogger.logger = zap.New(core) + defaultLoggerMu.Unlock() + t.Cleanup(func() { + defaultLoggerMu.Lock() + defaultLogger.logger = origLogger + defaultLoggerMu.Unlock() + }) + + handler := adminHandler{ + mux: http.NewServeMux(), + } + req := httptest.NewRequest(http.MethodGet, "/", nil) + req.Header.Set("Authorization", "Bearer secret") + req.Header.Set("Cookie", "session=secret") + req.Header.Set("X-Test", "ok") + rr := httptest.NewRecorder() + + handler.ServeHTTP(rr, req) + + if logs.Len() == 0 { + t.Fatal("expected request log entry") + } + + ctx := logs.All()[0].ContextMap() + headers, ok := ctx["headers"].(map[string]any) + if !ok { + t.Fatalf("expected headers field in log context, got %T", ctx["headers"]) + } + + if got := headers["Authorization"]; !reflect.DeepEqual(got, []any{"REDACTED"}) { + t.Fatalf("expected redacted Authorization header, got %#v", got) + } + if got := headers["Cookie"]; !reflect.DeepEqual(got, []any{"REDACTED"}) { + t.Fatalf("expected redacted Cookie header, got %#v", got) + } + if got := headers["X-Test"]; !reflect.DeepEqual(got, []any{"ok"}) { + t.Fatalf("expected X-Test header to remain visible, got %#v", got) + } +} + func initAdminMetrics() { if adminMetrics.requestErrors != nil { prometheus.Unregister(adminMetrics.requestErrors) diff --git a/go.mod b/go.mod index 0df389b59..8796ad4d8 100644 --- a/go.mod +++ b/go.mod @@ -30,20 +30,20 @@ require ( github.com/tailscale/tscert v0.0.0-20251216020129-aea342f6d747 github.com/yuin/goldmark v1.8.2 github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc - go.opentelemetry.io/contrib/exporters/autoexport v0.68.0 - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 - go.opentelemetry.io/contrib/propagators/autoprop v0.68.0 + go.opentelemetry.io/contrib/exporters/autoexport v0.65.0 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0 + go.opentelemetry.io/contrib/propagators/autoprop v0.65.0 go.opentelemetry.io/otel v1.43.0 go.opentelemetry.io/otel/sdk v1.43.0 - go.step.sm/crypto v0.77.2 + go.step.sm/crypto v0.77.1 go.uber.org/automaxprocs v1.6.0 go.uber.org/zap v1.27.1 go.uber.org/zap/exp v0.3.0 - golang.org/x/crypto v0.50.0 - golang.org/x/crypto/x509roots/fallback v0.0.0-20260323153451-8400f4a93807 - golang.org/x/net v0.53.0 + golang.org/x/crypto v0.49.0 + golang.org/x/crypto/x509roots/fallback v0.0.0-20260213171211-a408498e5541 + golang.org/x/net v0.52.0 golang.org/x/sync v0.20.0 - golang.org/x/term v0.42.0 + golang.org/x/term v0.41.0 golang.org/x/time v0.15.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -68,7 +68,7 @@ require ( github.com/google/go-tspi v0.3.0 // indirect github.com/google/s2a-go v0.1.9 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.14 // indirect - github.com/googleapis/gax-go/v2 v2.19.0 // indirect + github.com/googleapis/gax-go/v2 v2.18.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect github.com/jackc/pgx/v5 v5.9.0 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect @@ -109,9 +109,9 @@ require ( go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect golang.org/x/oauth2 v0.36.0 // indirect - google.golang.org/api v0.272.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20260406210006-6f92a3bedf2d // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d // indirect + google.golang.org/api v0.271.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 // indirect google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 // indirect ) @@ -168,10 +168,10 @@ require ( go.opentelemetry.io/otel/trace v1.43.0 go.opentelemetry.io/proto/otlp v1.10.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/mod v0.34.0 // indirect - golang.org/x/sys v0.43.0 - golang.org/x/text v0.36.0 - golang.org/x/tools v0.43.0 // indirect + golang.org/x/mod v0.33.0 // indirect + golang.org/x/sys v0.42.0 + golang.org/x/text v0.35.0 + golang.org/x/tools v0.42.0 // indirect google.golang.org/grpc v1.80.0 // indirect google.golang.org/protobuf v1.36.11 // indirect howett.net/plist v1.0.0 // indirect diff --git a/go.sum b/go.sum index 4d6b748fa..48a7d22bd 100644 --- a/go.sum +++ b/go.sum @@ -179,8 +179,8 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo= github.com/google/go-tpm v0.9.8/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY= -github.com/google/go-tpm-tools v0.4.8 h1:V4oIYyAD3BykOycwYQzO29WefDouQMTsYZqmG3HxOfM= -github.com/google/go-tpm-tools v0.4.8/go.mod h1:4DfiOtiS1KppJjwf1+tqtW4K3PrCJjAAqFKj/TYTJKg= +github.com/google/go-tpm-tools v0.4.7 h1:J3ycC8umYxM9A4eF73EofRZu4BxY0jjQnUnkhIBbvws= +github.com/google/go-tpm-tools v0.4.7/go.mod h1:gSyXTZHe3fgbzb6WEGd90QucmsnT1SRdlye82gH8QjQ= github.com/google/go-tspi v0.3.0 h1:ADtq8RKfP+jrTyIWIZDIYcKOMecRqNJFOew2IT0Inus= github.com/google/go-tspi v0.3.0/go.mod h1:xfMGI3G0PhxCdNVcYr1C4C+EizojDg/TXuX5by8CiHI= github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= @@ -189,8 +189,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.14 h1:yh8ncqsbUY4shRD5dA6RlzjJaT4hi3kII+zYw8wmLb8= github.com/googleapis/enterprise-certificate-proxy v0.3.14/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg= -github.com/googleapis/gax-go/v2 v2.19.0 h1:fYQaUOiGwll0cGj7jmHT/0nPlcrZDFPrZRhTsoCr8hE= -github.com/googleapis/gax-go/v2 v2.19.0/go.mod h1:w2ROXVdfGEVFXzmlciUU4EdjHgWvB5h2n6x/8XSTTJA= +github.com/googleapis/gax-go/v2 v2.18.0 h1:jxP5Uuo3bxm3M6gGtV94P4lliVetoCB4Wk2x8QA86LI= +github.com/googleapis/gax-go/v2 v2.18.0/go.mod h1:uSzZN4a356eRG985CzJ3WfbFSpqkLTjsnhWGJR6EwrE= github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs= github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= @@ -375,14 +375,14 @@ go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/contrib/bridges/prometheus v0.68.0 h1:w3zlHYETbDwXyWHZlyyR58ZC39XGi8rAhkBgUgJ9d5w= go.opentelemetry.io/contrib/bridges/prometheus v0.68.0/go.mod h1:GR/mClR2nn7vE8RLwxKjoBNg+QtgdDhRzxVa93koy5o= -go.opentelemetry.io/contrib/exporters/autoexport v0.68.0 h1:0D3GFvELGIwQGfC6agLsbrEYSGWZTRTxIXxcQUqrOuk= -go.opentelemetry.io/contrib/exporters/autoexport v0.68.0/go.mod h1:DM2NV7Zb8CcGeVPt6glouY0FAiwZQ/iqgcWExhgWeN8= +go.opentelemetry.io/contrib/exporters/autoexport v0.65.0 h1:2gApdml7SznX9szEKFjKjM4qGcGSvAybYLBY319XG3g= +go.opentelemetry.io/contrib/exporters/autoexport v0.65.0/go.mod h1:0QqAGlbHXhmPYACG3n5hNzO5DnEqqtg4VcK5pr22RI0= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 h1:q4XOmH/0opmeuJtPsbFNivyl7bCt7yRBbeEm2sC/XtQ= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0/go.mod h1:snMWehoOh2wsEwnvvwtDyFCxVeDAODenXHtn5vzrKjo= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo= -go.opentelemetry.io/contrib/propagators/autoprop v0.68.0 h1:wLGFvNBPqQhzBn0QRBZjrriH8lZ9gqtTz8ufHEjLg7k= -go.opentelemetry.io/contrib/propagators/autoprop v0.68.0/go.mod h1:evWK9nCqCzH8nhclTlpkdUzmxrmJQ2mrWCdKIvyOYec= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0 h1:7iP2uCb7sGddAr30RRS6xjKy7AZ2JtTOPA3oolgVSw8= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0/go.mod h1:c7hN3ddxs/z6q9xwvfLPk+UHlWRQyaeR1LdgfL/66l0= +go.opentelemetry.io/contrib/propagators/autoprop v0.65.0 h1:kTaCycF9Xkm8VBBvH0rJ4wFeRjtIV55Erk3uuVsIs5s= +go.opentelemetry.io/contrib/propagators/autoprop v0.65.0/go.mod h1:rooPzAbXfxMX9fsPJjmOBg2SN4RhFEV8D7cfGK+N3tE= go.opentelemetry.io/contrib/propagators/aws v1.43.0 h1:EwnsB3cXRLAh7/Nr/9rMuGw73nfb3z6uAvVDjRrbeUg= go.opentelemetry.io/contrib/propagators/aws v1.43.0/go.mod h1:CJjTym6F87tEdm61Qvnz5xrV8vKlH4C92djiqcn62k8= go.opentelemetry.io/contrib/propagators/b3 v1.43.0 h1:CETqV3QLLPTy5yNrqyMr41VnAOOD4lsRved7n4QG00A= @@ -431,8 +431,8 @@ go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09 go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g= go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk= -go.step.sm/crypto v0.77.2 h1:qFjjei+RHc5kP5R7NW9OUWT7SqWIuAOvOkXqg4fNWj8= -go.step.sm/crypto v0.77.2/go.mod h1:W0YJb9onM5l78qgkXIJ2Up6grnwW8EtpCKIza/NCg0o= +go.step.sm/crypto v0.77.1 h1:4EEqfKdv0egQ1lqz2RhnU8Jv6QgXZfrgoxWMqJF9aDs= +go.step.sm/crypto v0.77.1/go.mod h1:U/SsmEm80mNnfD5WIkbhuW/B1eFp3fgFvdXyDLpU1AQ= go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -456,10 +456,10 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= -golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= -golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= -golang.org/x/crypto/x509roots/fallback v0.0.0-20260323153451-8400f4a93807 h1:sQVhWLXbNsa8CTzHOX3IHc7C4Q2JyxI5AweuMQZ/5H0= -golang.org/x/crypto/x509roots/fallback v0.0.0-20260323153451-8400f4a93807/go.mod h1:+UoQFNBq2p2wO+Q6ddVtYc25GZ6VNdOMyyrd4nrqrKs= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= +golang.org/x/crypto/x509roots/fallback v0.0.0-20260213171211-a408498e5541 h1:FmKxj9ocLKn45jiR2jQMwCVhDvaK7fKQFzfuT9GvyK8= +golang.org/x/crypto/x509roots/fallback v0.0.0-20260213171211-a408498e5541/go.mod h1:+UoQFNBq2p2wO+Q6ddVtYc25GZ6VNdOMyyrd4nrqrKs= golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY= golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -467,8 +467,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI= -golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY= +golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8= +golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= @@ -477,8 +477,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= -golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= +golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0= +golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw= golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -506,8 +506,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= -golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= +golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -517,8 +517,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= -golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= -golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= +golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU= +golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= @@ -528,8 +528,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= -golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= -golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= +golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= +golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -538,19 +538,19 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s= -golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0= +golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k= +golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= -google.golang.org/api v0.272.0 h1:eLUQZGnAS3OHn31URRf9sAmRk3w2JjMx37d2k8AjJmA= -google.golang.org/api v0.272.0/go.mod h1:wKjowi5LNJc5qarNvDCvNQBn3rVK8nSy6jg2SwRwzIA= -google.golang.org/genproto v0.0.0-20260316180232-0b37fe3546d5 h1:JNfk58HZ8lfmXbYK2vx/UvsqIL59TzByCxPIX4TDmsE= -google.golang.org/genproto v0.0.0-20260316180232-0b37fe3546d5/go.mod h1:x5julN69+ED4PcFk/XWayw35O0lf/nGa4aNgODCmNmw= -google.golang.org/genproto/googleapis/api v0.0.0-20260406210006-6f92a3bedf2d h1:/aDRtSZJjyLQzm75d+a1wOJaqyKBMvIAfeQmoa3ORiI= -google.golang.org/genproto/googleapis/api v0.0.0-20260406210006-6f92a3bedf2d/go.mod h1:etfGUgejTiadZAUaEP14NP97xi1RGeawqkjDARA/UOs= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d h1:wT2n40TBqFY6wiwazVK9/iTWbsQrgk5ZfCSVFLO9LQA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/api v0.271.0 h1:cIPN4qcUc61jlh7oXu6pwOQqbJW2GqYh5PS6rB2C/JY= +google.golang.org/api v0.271.0/go.mod h1:CGT29bhwkbF+i11qkRUJb2KMKqcJ1hdFceEIRd9u64Q= +google.golang.org/genproto v0.0.0-20260217215200-42d3e9bedb6d h1:vsOm753cOAMkt76efriTCDKjpCbK18XGHMJHo0JUKhc= +google.golang.org/genproto v0.0.0-20260217215200-42d3e9bedb6d/go.mod h1:0oz9d7g9QLSdv9/lgbIjowW1JoxMbxmBVNe8i6tORJI= +google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 h1:VPWxll4HlMw1Vs/qXtN7BvhZqsS9cdAittCNvVENElA= +google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:7QBABkRtR8z+TEnmXTqIqwJLlzrZKVfAUm7tY3yGv0M= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 h1:m8qni9SQFH0tJc1X0vmnpw/0t+AImlSvp30sEupozUg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 h1:F29+wU6Ee6qgu9TddPgooOdaqsxTMunOoj8KA5yuS5A= diff --git a/internal/logmarshalers.go b/internal/logmarshalers.go new file mode 100644 index 000000000..3a8a553e6 --- /dev/null +++ b/internal/logmarshalers.go @@ -0,0 +1,54 @@ +package internal + +import ( + "net/http" + "strings" + + "go.uber.org/zap/zapcore" +) + +// LoggableHTTPHeader makes an HTTP header loggable with zap.Object(). +// Headers with potentially sensitive information (Cookie, Set-Cookie, +// Authorization, and Proxy-Authorization) are logged with empty values. +type LoggableHTTPHeader struct { + http.Header + + ShouldLogCredentials bool +} + +// MarshalLogObject satisfies the zapcore.ObjectMarshaler interface. +func (h LoggableHTTPHeader) MarshalLogObject(enc zapcore.ObjectEncoder) error { + if h.Header == nil { + return nil + } + for key, val := range h.Header { + if !h.ShouldLogCredentials { + switch strings.ToLower(key) { + case "cookie", "set-cookie", "authorization", "proxy-authorization": + val = []string{"REDACTED"} // see #5669. I still think ▒▒▒▒ would be cool. + } + } + enc.AddArray(key, LoggableStringArray(val)) + } + return nil +} + +// LoggableStringArray makes a slice of strings marshalable for logging. +type LoggableStringArray []string + +// MarshalLogArray satisfies the zapcore.ArrayMarshaler interface. +func (sa LoggableStringArray) MarshalLogArray(enc zapcore.ArrayEncoder) error { + if sa == nil { + return nil + } + for _, s := range sa { + enc.AppendString(s) + } + return nil +} + +// Interface guards +var ( + _ zapcore.ObjectMarshaler = (*LoggableHTTPHeader)(nil) + _ zapcore.ArrayMarshaler = (*LoggableStringArray)(nil) +) diff --git a/modules/caddyhttp/marshalers.go b/modules/caddyhttp/marshalers.go index 2a40b6cd7..15fa3e8bc 100644 --- a/modules/caddyhttp/marshalers.go +++ b/modules/caddyhttp/marshalers.go @@ -18,9 +18,10 @@ import ( "crypto/tls" "net" "net/http" - "strings" "go.uber.org/zap/zapcore" + + "github.com/caddyserver/caddy/v2/internal" ) // LoggableHTTPRequest makes an HTTP request loggable with zap.Object(). @@ -47,12 +48,12 @@ func (r LoggableHTTPRequest) MarshalLogObject(enc zapcore.ObjectEncoder) error { enc.AddString("method", r.Method) enc.AddString("host", r.Host) enc.AddString("uri", r.RequestURI) - enc.AddObject("headers", LoggableHTTPHeader{ + enc.AddObject("headers", internal.LoggableHTTPHeader{ Header: r.Header, ShouldLogCredentials: r.ShouldLogCredentials, }) if r.TransferEncoding != nil { - enc.AddArray("transfer_encoding", LoggableStringArray(r.TransferEncoding)) + enc.AddArray("transfer_encoding", internal.LoggableStringArray(r.TransferEncoding)) } if r.TLS != nil { enc.AddObject("tls", LoggableTLSConnState(*r.TLS)) @@ -61,44 +62,10 @@ func (r LoggableHTTPRequest) MarshalLogObject(enc zapcore.ObjectEncoder) error { } // LoggableHTTPHeader makes an HTTP header loggable with zap.Object(). -// Headers with potentially sensitive information (Cookie, Set-Cookie, -// Authorization, and Proxy-Authorization) are logged with empty values. -type LoggableHTTPHeader struct { - http.Header - - ShouldLogCredentials bool -} - -// MarshalLogObject satisfies the zapcore.ObjectMarshaler interface. -func (h LoggableHTTPHeader) MarshalLogObject(enc zapcore.ObjectEncoder) error { - if h.Header == nil { - return nil - } - for key, val := range h.Header { - if !h.ShouldLogCredentials { - switch strings.ToLower(key) { - case "cookie", "set-cookie", "authorization", "proxy-authorization": - val = []string{"REDACTED"} // see #5669. I still think ▒▒▒▒ would be cool. - } - } - enc.AddArray(key, LoggableStringArray(val)) - } - return nil -} +type LoggableHTTPHeader = internal.LoggableHTTPHeader // LoggableStringArray makes a slice of strings marshalable for logging. -type LoggableStringArray []string - -// MarshalLogArray satisfies the zapcore.ArrayMarshaler interface. -func (sa LoggableStringArray) MarshalLogArray(enc zapcore.ArrayEncoder) error { - if sa == nil { - return nil - } - for _, s := range sa { - enc.AppendString(s) - } - return nil -} +type LoggableStringArray = internal.LoggableStringArray // LoggableTLSConnState makes a TLS connection state loggable with zap.Object(). type LoggableTLSConnState tls.ConnectionState @@ -121,7 +88,5 @@ func (t LoggableTLSConnState) MarshalLogObject(enc zapcore.ObjectEncoder) error // Interface guards var ( _ zapcore.ObjectMarshaler = (*LoggableHTTPRequest)(nil) - _ zapcore.ObjectMarshaler = (*LoggableHTTPHeader)(nil) - _ zapcore.ArrayMarshaler = (*LoggableStringArray)(nil) _ zapcore.ObjectMarshaler = (*LoggableTLSConnState)(nil) ) diff --git a/modules/caddyhttp/reverseproxy/hosts.go b/modules/caddyhttp/reverseproxy/hosts.go index a5406e04e..e58d6825f 100644 --- a/modules/caddyhttp/reverseproxy/hosts.go +++ b/modules/caddyhttp/reverseproxy/hosts.go @@ -174,7 +174,7 @@ func (u *Upstream) fillDynamicHost() { // Host is the basic, in-memory representation of the state of a remote host. // Its fields are accessed atomically and Host values must not be copied. type Host struct { - numRequests atomic.Int64 // atomic.Int64 is automatically aligned for us (see https://golang.org/pkg/sync/atomic/#pkg-note-BUG) + numRequests atomic.Int64 fails atomic.Int64 activePasses atomic.Int64 activeFails atomic.Int64 @@ -250,7 +250,6 @@ func (h *Host) resetHealth() { // (This returns the status only from the "active" health checks.) func (u *Upstream) healthy() bool { return u.unhealthy.Load() == 0 - // return atomic.LoadInt32(&u.unhealthy) == 0 } // SetHealthy sets the upstream has healthy or unhealthy diff --git a/modules/logging/filters.go b/modules/logging/filters.go index 4574b7ca0..087b872e7 100644 --- a/modules/logging/filters.go +++ b/modules/logging/filters.go @@ -29,7 +29,7 @@ import ( "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" - "github.com/caddyserver/caddy/v2/modules/caddyhttp" + "github.com/caddyserver/caddy/v2/internal" ) func init() { @@ -100,8 +100,8 @@ func (f *HashFilter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { // Filter filters the input field with the replacement value. func (f *HashFilter) Filter(in zapcore.Field) zapcore.Field { - if array, ok := in.Interface.(caddyhttp.LoggableStringArray); ok { - newArray := make(caddyhttp.LoggableStringArray, len(array)) + if array, ok := in.Interface.(internal.LoggableStringArray); ok { + newArray := make(internal.LoggableStringArray, len(array)) for i, s := range array { newArray[i] = hash(s) } @@ -241,8 +241,8 @@ func (m *IPMaskFilter) Provision(ctx caddy.Context) error { // Filter filters the input field. func (m IPMaskFilter) Filter(in zapcore.Field) zapcore.Field { - if array, ok := in.Interface.(caddyhttp.LoggableStringArray); ok { - newArray := make(caddyhttp.LoggableStringArray, len(array)) + if array, ok := in.Interface.(internal.LoggableStringArray); ok { + newArray := make(internal.LoggableStringArray, len(array)) for i, s := range array { newArray[i] = m.mask(s) } @@ -392,8 +392,8 @@ func (m *QueryFilter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { // Filter filters the input field. func (m QueryFilter) Filter(in zapcore.Field) zapcore.Field { - if array, ok := in.Interface.(caddyhttp.LoggableStringArray); ok { - newArray := make(caddyhttp.LoggableStringArray, len(array)) + if array, ok := in.Interface.(internal.LoggableStringArray); ok { + newArray := make(internal.LoggableStringArray, len(array)) for i, s := range array { newArray[i] = m.processQueryString(s) } @@ -523,7 +523,7 @@ func (m *CookieFilter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { // Filter filters the input field. func (m CookieFilter) Filter(in zapcore.Field) zapcore.Field { - cookiesSlice, ok := in.Interface.(caddyhttp.LoggableStringArray) + cookiesSlice, ok := in.Interface.(internal.LoggableStringArray) if !ok { return in } @@ -559,7 +559,7 @@ OUTER: transformedRequest.AddCookie(c) } - in.Interface = caddyhttp.LoggableStringArray(transformedRequest.Header["Cookie"]) + in.Interface = internal.LoggableStringArray(transformedRequest.Header["Cookie"]) return in } @@ -613,8 +613,8 @@ func (m *RegexpFilter) Provision(ctx caddy.Context) error { // Filter filters the input field with the replacement value if it matches the regexp. func (f *RegexpFilter) Filter(in zapcore.Field) zapcore.Field { - if array, ok := in.Interface.(caddyhttp.LoggableStringArray); ok { - newArray := make(caddyhttp.LoggableStringArray, len(array)) + if array, ok := in.Interface.(internal.LoggableStringArray); ok { + newArray := make(internal.LoggableStringArray, len(array)) for i, s := range array { newArray[i] = f.regexp.ReplaceAllString(s, f.Value) } @@ -783,8 +783,8 @@ func (f *MultiRegexpFilter) Validate() error { // Filter applies all regexp operations sequentially to the input field. // Input is sanitized and validated for security. func (f *MultiRegexpFilter) Filter(in zapcore.Field) zapcore.Field { - if array, ok := in.Interface.(caddyhttp.LoggableStringArray); ok { - newArray := make(caddyhttp.LoggableStringArray, len(array)) + if array, ok := in.Interface.(internal.LoggableStringArray); ok { + newArray := make(internal.LoggableStringArray, len(array)) for i, s := range array { newArray[i] = f.processString(s) } diff --git a/modules/logging/filters_test.go b/modules/logging/filters_test.go index cf35e7178..8fbaed6f8 100644 --- a/modules/logging/filters_test.go +++ b/modules/logging/filters_test.go @@ -8,7 +8,7 @@ import ( "go.uber.org/zap/zapcore" "github.com/caddyserver/caddy/v2" - "github.com/caddyserver/caddy/v2/modules/caddyhttp" + "github.com/caddyserver/caddy/v2/internal" ) func TestIPMaskSingleValue(t *testing.T) { @@ -55,11 +55,11 @@ func TestIPMaskMultiValue(t *testing.T) { f := IPMaskFilter{IPv4MaskRaw: 16, IPv6MaskRaw: 32} f.Provision(caddy.Context{}) - out := f.Filter(zapcore.Field{Interface: caddyhttp.LoggableStringArray{ + out := f.Filter(zapcore.Field{Interface: internal.LoggableStringArray{ "255.255.255.255", "244.244.244.244", }}) - arr, ok := out.Interface.(caddyhttp.LoggableStringArray) + arr, ok := out.Interface.(internal.LoggableStringArray) if !ok { t.Fatalf("field is wrong type: %T", out.Integer) } @@ -70,11 +70,11 @@ func TestIPMaskMultiValue(t *testing.T) { t.Fatalf("field entry 1 has not been filtered: %s", arr[1]) } - out = f.Filter(zapcore.Field{Interface: caddyhttp.LoggableStringArray{ + out = f.Filter(zapcore.Field{Interface: internal.LoggableStringArray{ "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "ff00:ffff:ffff:ffff:ffff:ffff:ffff:ffff", }}) - arr, ok = out.Interface.(caddyhttp.LoggableStringArray) + arr, ok = out.Interface.(internal.LoggableStringArray) if !ok { t.Fatalf("field is wrong type: %T", out.Integer) } @@ -120,11 +120,11 @@ func TestQueryFilterMultiValue(t *testing.T) { t.Fatalf("the filter must be valid") } - out := f.Filter(zapcore.Field{Interface: caddyhttp.LoggableStringArray{ + out := f.Filter(zapcore.Field{Interface: internal.LoggableStringArray{ "/path1?foo=a&foo=b&bar=c&bar=d&baz=e&hash=hashed", "/path2?foo=c&foo=d&bar=e&bar=f&baz=g&hash=hashed", }}) - arr, ok := out.Interface.(caddyhttp.LoggableStringArray) + arr, ok := out.Interface.(internal.LoggableStringArray) if !ok { t.Fatalf("field is wrong type: %T", out.Interface) } @@ -162,11 +162,11 @@ func TestCookieFilter(t *testing.T) { {hashAction, "hash", ""}, }} - out := f.Filter(zapcore.Field{Interface: caddyhttp.LoggableStringArray{ + out := f.Filter(zapcore.Field{Interface: internal.LoggableStringArray{ "foo=a; foo=b; bar=c; bar=d; baz=e; hash=hashed", }}) - outval := out.Interface.(caddyhttp.LoggableStringArray) - expected := caddyhttp.LoggableStringArray{ + outval := out.Interface.(internal.LoggableStringArray) + expected := internal.LoggableStringArray{ "foo=REDACTED; foo=REDACTED; baz=e; hash=1a06df82", } if outval[0] != expected[0] { @@ -204,8 +204,8 @@ func TestRegexpFilterMultiValue(t *testing.T) { f := RegexpFilter{RawRegexp: `secret`, Value: "REDACTED"} f.Provision(caddy.Context{}) - out := f.Filter(zapcore.Field{Interface: caddyhttp.LoggableStringArray{"foo-secret-bar", "bar-secret-foo"}}) - arr, ok := out.Interface.(caddyhttp.LoggableStringArray) + out := f.Filter(zapcore.Field{Interface: internal.LoggableStringArray{"foo-secret-bar", "bar-secret-foo"}}) + arr, ok := out.Interface.(internal.LoggableStringArray) if !ok { t.Fatalf("field is wrong type: %T", out.Integer) } @@ -229,8 +229,8 @@ func TestHashFilterSingleValue(t *testing.T) { func TestHashFilterMultiValue(t *testing.T) { f := HashFilter{} - out := f.Filter(zapcore.Field{Interface: caddyhttp.LoggableStringArray{"foo", "bar"}}) - arr, ok := out.Interface.(caddyhttp.LoggableStringArray) + out := f.Filter(zapcore.Field{Interface: internal.LoggableStringArray{"foo", "bar"}}) + arr, ok := out.Interface.(internal.LoggableStringArray) if !ok { t.Fatalf("field is wrong type: %T", out.Integer) } @@ -292,11 +292,11 @@ func TestMultiRegexpFilterMultiValue(t *testing.T) { t.Fatalf("unexpected error provisioning: %v", err) } - out := f.Filter(zapcore.Field{Interface: caddyhttp.LoggableStringArray{ + out := f.Filter(zapcore.Field{Interface: internal.LoggableStringArray{ "foo-secret-123", "bar-secret-456", }}) - arr, ok := out.Interface.(caddyhttp.LoggableStringArray) + arr, ok := out.Interface.(internal.LoggableStringArray) if !ok { t.Fatalf("field is wrong type: %T", out.Interface) }