Compare commits

..

No commits in common. "master" and "v2.11.0-beta.1" have entirely different histories.

19 changed files with 154 additions and 897 deletions

View file

@ -851,20 +851,6 @@ func (st *ServerType) serversFromPairings(
srv.ListenerWrappersRaw = append(srv.ListenerWrappersRaw, jsonListenerWrapper)
}
// Look for any config values that provide packet conn wrappers on the server block
for _, listenerConfig := range sblock.pile["packet_conn_wrapper"] {
packetConnWrapper, ok := listenerConfig.Value.(caddy.PacketConnWrapper)
if !ok {
return nil, fmt.Errorf("config for a packet conn wrapper did not provide a value that implements caddy.PacketConnWrapper")
}
jsonPacketConnWrapper := caddyconfig.JSONModuleObject(
packetConnWrapper,
"wrapper",
packetConnWrapper.(caddy.Module).CaddyModule().ID.Name(),
warnings)
srv.PacketConnWrappersRaw = append(srv.PacketConnWrappersRaw, jsonPacketConnWrapper)
}
// set up each handler directive, making sure to honor directive order
dirRoutes := sblock.pile["route"]
siteSubroute, err := buildSubroute(dirRoutes, groupCounter, true)

View file

@ -36,27 +36,26 @@ type serverOptions struct {
ListenerAddress string
// These will all map 1:1 to the caddyhttp.Server struct
Name string
ListenerWrappersRaw []json.RawMessage
PacketConnWrappersRaw []json.RawMessage
ReadTimeout caddy.Duration
ReadHeaderTimeout caddy.Duration
WriteTimeout caddy.Duration
IdleTimeout caddy.Duration
KeepAliveInterval caddy.Duration
KeepAliveIdle caddy.Duration
KeepAliveCount int
MaxHeaderBytes int
EnableFullDuplex bool
Protocols []string
StrictSNIHost *bool
TrustedProxiesRaw json.RawMessage
TrustedProxiesStrict int
TrustedProxiesUnix bool
ClientIPHeaders []string
ShouldLogCredentials bool
Metrics *caddyhttp.Metrics
Trace bool // TODO: EXPERIMENTAL
Name string
ListenerWrappersRaw []json.RawMessage
ReadTimeout caddy.Duration
ReadHeaderTimeout caddy.Duration
WriteTimeout caddy.Duration
IdleTimeout caddy.Duration
KeepAliveInterval caddy.Duration
KeepAliveIdle caddy.Duration
KeepAliveCount int
MaxHeaderBytes int
EnableFullDuplex bool
Protocols []string
StrictSNIHost *bool
TrustedProxiesRaw json.RawMessage
TrustedProxiesStrict int
TrustedProxiesUnix bool
ClientIPHeaders []string
ShouldLogCredentials bool
Metrics *caddyhttp.Metrics
Trace bool // TODO: EXPERIMENTAL
}
func unmarshalCaddyfileServerOptions(d *caddyfile.Dispenser) (any, error) {
@ -100,26 +99,6 @@ func unmarshalCaddyfileServerOptions(d *caddyfile.Dispenser) (any, error) {
serverOpts.ListenerWrappersRaw = append(serverOpts.ListenerWrappersRaw, jsonListenerWrapper)
}
case "packet_conn_wrappers":
for nesting := d.Nesting(); d.NextBlock(nesting); {
modID := "caddy.packetconns." + d.Val()
unm, err := caddyfile.UnmarshalModule(d, modID)
if err != nil {
return nil, err
}
packetConnWrapper, ok := unm.(caddy.PacketConnWrapper)
if !ok {
return nil, fmt.Errorf("module %s (%T) is not a packet conn wrapper", modID, unm)
}
jsonPacketConnWrapper := caddyconfig.JSONModuleObject(
packetConnWrapper,
"wrapper",
packetConnWrapper.(caddy.Module).CaddyModule().ID.Name(),
nil,
)
serverOpts.PacketConnWrappersRaw = append(serverOpts.PacketConnWrappersRaw, jsonPacketConnWrapper)
}
case "timeouts":
for nesting := d.Nesting(); d.NextBlock(nesting); {
switch d.Val() {
@ -356,7 +335,6 @@ func applyServerOptions(
// set all the options
server.ListenerWrappersRaw = opts.ListenerWrappersRaw
server.PacketConnWrappersRaw = opts.PacketConnWrappersRaw
server.ReadTimeout = opts.ReadTimeout
server.ReadHeaderTimeout = opts.ReadHeaderTimeout
server.WriteTimeout = opts.WriteTimeout

38
go.mod
View file

@ -21,7 +21,7 @@ require (
github.com/mholt/acmez/v3 v3.1.4
github.com/prometheus/client_golang v1.23.2
github.com/quic-go/quic-go v0.57.1
github.com/smallstep/certificates v0.29.0
github.com/smallstep/certificates v0.28.4
github.com/smallstep/nosql v0.7.0
github.com/smallstep/truststore v0.13.0
github.com/spf13/cobra v1.10.1
@ -35,7 +35,6 @@ require (
go.opentelemetry.io/contrib/propagators/autoprop v0.63.0
go.opentelemetry.io/otel v1.38.0
go.opentelemetry.io/otel/sdk v1.38.0
go.step.sm/crypto v0.74.0
go.uber.org/automaxprocs v1.6.0
go.uber.org/zap v1.27.1
go.uber.org/zap/exp v0.3.0
@ -56,18 +55,18 @@ require (
dario.cat/mergo v1.0.1 // indirect
github.com/Microsoft/go-winio v0.6.0 // indirect
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
github.com/ccoveille/go-safecast/v2 v2.0.0 // indirect
github.com/ccoveille/go-safecast v1.6.1 // indirect
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
github.com/coreos/go-oidc/v3 v3.17.0 // indirect
github.com/coreos/go-oidc/v3 v3.14.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
github.com/fxamacker/cbor/v2 v2.8.0 // indirect
github.com/go-jose/go-jose/v3 v3.0.4 // indirect
github.com/go-jose/go-jose/v4 v4.1.3 // indirect
github.com/go-jose/go-jose/v4 v4.1.2 // indirect
github.com/google/certificate-transparency-go v1.1.8-0.20240110162603-74a5dd331745 // indirect
github.com/google/go-tpm v0.9.7 // indirect
github.com/google/go-tpm v0.9.6 // indirect
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.7 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
github.com/googleapis/gax-go/v2 v2.15.0 // indirect
github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
@ -79,14 +78,14 @@ require (
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/otlptranslator v0.0.2 // indirect
github.com/quic-go/qpack v0.6.0 // indirect
github.com/smallstep/cli-utils v0.12.2 // indirect
github.com/smallstep/cli-utils v0.12.1 // indirect
github.com/smallstep/go-attestation v0.4.4-0.20241119153605-2306d5b464ca // indirect
github.com/smallstep/linkedca v0.25.0 // indirect
github.com/smallstep/linkedca v0.23.0 // indirect
github.com/smallstep/pkcs7 v0.2.1 // indirect
github.com/smallstep/scep v0.0.0-20250318231241-a25cabb69492 // indirect
github.com/smallstep/scep v0.0.0-20240926084937-8cf1ca453101 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/zeebo/blake3 v0.2.4 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/bridges/prometheus v0.63.0 // indirect
go.opentelemetry.io/contrib/propagators/aws v1.38.0 // indirect
go.opentelemetry.io/contrib/propagators/b3 v1.38.0 // indirect
@ -107,10 +106,10 @@ require (
go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect
go.yaml.in/yaml/v2 v2.4.3 // indirect
golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 // indirect
golang.org/x/oauth2 v0.33.0 // indirect
google.golang.org/api v0.256.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101 // indirect
golang.org/x/oauth2 v0.32.0 // indirect
google.golang.org/api v0.254.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 // indirect
)
@ -118,7 +117,7 @@ require (
filippo.io/edwards25519 v1.1.0 // indirect
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.3.1 // indirect
github.com/Masterminds/semver/v3 v3.3.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash v1.1.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0
@ -141,7 +140,7 @@ require (
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/libdns/libdns v1.1.1
github.com/manifoldco/promptui v0.9.0 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
github.com/miekg/dns v1.1.68 // indirect
@ -167,12 +166,13 @@ require (
go.opentelemetry.io/otel/metric v1.38.0 // indirect
go.opentelemetry.io/otel/trace v1.38.0
go.opentelemetry.io/proto/otlp v1.7.1 // indirect
go.step.sm/crypto v0.74.0
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/mod v0.29.0 // indirect
golang.org/x/sys v0.38.0
golang.org/x/text v0.31.0 // indirect
golang.org/x/tools v0.38.0 // indirect
google.golang.org/grpc v1.77.0 // indirect
google.golang.org/grpc v1.76.0 // indirect
google.golang.org/protobuf v1.36.10 // indirect
howett.net/plist v1.0.0 // indirect
)

92
go.sum
View file

@ -1,7 +1,7 @@
cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY=
cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
cloud.google.com/go v0.121.6 h1:waZiuajrI28iAf40cWgycWNgaXPO06dupuS+sgibK6c=
cloud.google.com/go v0.121.6/go.mod h1:coChdst4Ea5vUpiALcYKXEpR1S9ZgXbhEzzMcMR66vI=
cloud.google.com/go v0.120.0 h1:wc6bgG9DHyKqF5/vQvX1CiZrtHnxJjBlKUyF9nP6meA=
cloud.google.com/go v0.120.0/go.mod h1:/beW32s8/pGRuj4IILWQNd4uuebeT4dkOhKmkfit64Q=
cloud.google.com/go/auth v0.17.0 h1:74yCm7hCj2rUyyAocqnFzsAYXgJhrG26XCFimrc/Kz4=
cloud.google.com/go/auth v0.17.0/go.mod h1:6wv/t5/6rOPAX4fJiRjKkJCvswLwdet7G8+UGXt7nCQ=
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
@ -12,8 +12,8 @@ cloud.google.com/go/iam v1.5.2 h1:qgFRAGEmd8z6dJ/qyEchAuL9jpswyODjA2lS+w234g8=
cloud.google.com/go/iam v1.5.2/go.mod h1:SE1vg0N81zQqLzQEwxL2WI6yhetBdbNQuTvIKCSkUHE=
cloud.google.com/go/kms v1.23.2 h1:4IYDQL5hG4L+HzJBhzejUySoUOheh3Lk5YT4PCyyW6k=
cloud.google.com/go/kms v1.23.2/go.mod h1:rZ5kK0I7Kn9W4erhYVoIRPtpizjunlrfU4fUkumUp8g=
cloud.google.com/go/longrunning v0.7.0 h1:FV0+SYF1RIj59gyoWDRi45GiYUMM3K1qO51qoboQT1E=
cloud.google.com/go/longrunning v0.7.0/go.mod h1:ySn2yXmjbK9Ba0zsQqunhDkYi0+9rlXIwnoAf+h+TPY=
cloud.google.com/go/longrunning v0.6.7 h1:IGtfDWHhQCgCjwQjV9iiLnUta9LBCo8R9QmAFsS/PrE=
cloud.google.com/go/longrunning v0.6.7/go.mod h1:EAFV3IZAKmM56TyiE6VAP3VoTzhZzySwI/YI1s/nRsY=
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
@ -29,8 +29,8 @@ github.com/KimMachineGun/automemlimit v0.7.5 h1:RkbaC0MwhjL1ZuBKunGDjE/ggwAX43Dw
github.com/KimMachineGun/automemlimit v0.7.5/go.mod h1:QZxpHaGOQoYvFhv/r4u3U0JTC2ZcOwbSr11UZF46UBM=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4=
github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0=
github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs=
github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
@ -84,8 +84,8 @@ github.com/caddyserver/certmagic v0.25.0 h1:VMleO/XA48gEWes5l+Fh6tRWo9bHkhwAEhx6
github.com/caddyserver/certmagic v0.25.0/go.mod h1:m9yB7Mud24OQbPHOiipAoyKPn9pKHhpSJxXR1jydBxA=
github.com/caddyserver/zerossl v0.1.3 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+YTAyA=
github.com/caddyserver/zerossl v0.1.3/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4=
github.com/ccoveille/go-safecast/v2 v2.0.0 h1:+5eyITXAUj3wMjad6cRVJKGnC7vDS55zk0INzJagub0=
github.com/ccoveille/go-safecast/v2 v2.0.0/go.mod h1:JIYA4CAR33blIDuE6fSwCp2sz1oOBahXnvmdBhOAABs=
github.com/ccoveille/go-safecast v1.6.1 h1:Nb9WMDR8PqhnKCVs2sCB+OqhohwO5qaXtCviZkIff5Q=
github.com/ccoveille/go-safecast v1.6.1/go.mod h1:QqwNjxQ7DAqY0C721OIO9InMk9zCwcsO7tnRuHytad8=
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
@ -105,8 +105,8 @@ github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-oidc/v3 v3.17.0 h1:hWBGaQfbi0iVviX4ibC7bk8OKT5qNr4klBaCHVNvehc=
github.com/coreos/go-oidc/v3 v3.17.0/go.mod h1:wqPbKFrVnE90vty060SB40FCJ8fTHTxSwyXJqZH+sI8=
github.com/coreos/go-oidc/v3 v3.14.1 h1:9ePWwfdwC4QKRlCXsJGou56adA/owXczOzwKdOumLqk=
github.com/coreos/go-oidc/v3 v3.14.1/go.mod h1:HaZ3szPaZ0e4r6ebqvsLWlk2Tn+aejfmrfah6hnSYEU=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
@ -140,14 +140,14 @@ github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHqu
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU=
github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/go-chi/chi/v5 v5.2.3 h1:WQIt9uxdsAbgIYgid+BpYc+liqQZGMHRaUwp0JUcvdE=
github.com/go-chi/chi/v5 v5.2.3/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
github.com/go-jose/go-jose/v3 v3.0.4 h1:Wp5HA7bLQcKnf6YYao/4kpRpVMp/yf6+pJKV8WFSaNY=
github.com/go-jose/go-jose/v3 v3.0.4/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=
github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
github.com/go-jose/go-jose/v4 v4.1.2 h1:TK/7NqRQZfgAh+Td8AlsrvtPoUyiHh0LqVvokh+1vHI=
github.com/go-jose/go-jose/v4 v4.1.2/go.mod h1:22cg9HWM1pOlnRiY+9cQYJ9XHmya1bYW8OeDM6Ku6Oo=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
@ -172,8 +172,8 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
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.7 h1:u89J4tUUeDTlH8xxC3CTW7OHZjbjKoHdQ9W7gCUhtxA=
github.com/google/go-tpm v0.9.7/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
github.com/google/go-tpm v0.9.6 h1:Ku42PT4LmjDu1H5C5ISWLlpI1mj+Zq7sPGKoRw2XROA=
github.com/google/go-tpm v0.9.6/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
github.com/google/go-tpm-tools v0.4.6 h1:hwIwPG7w4z5eQEBq11gYw8YYr9xXLfBQ/0JsKyq5AJM=
github.com/google/go-tpm-tools v0.4.6/go.mod h1:MsVQbJnRhKDfWwf5zgr3cDGpj13P1uLAFF0wMEP/n5w=
github.com/google/go-tspi v0.3.0 h1:ADtq8RKfP+jrTyIWIZDIYcKOMecRqNJFOew2IT0Inus=
@ -182,8 +182,8 @@ github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
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.7 h1:zrn2Ee/nWmHulBx5sAVrGgAa0f2/R35S4DJwfFaUPFQ=
github.com/googleapis/enterprise-certificate-proxy v0.3.7/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA=
github.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU9uHLo7OnF5tL52HFAgMmyrf4=
github.com/googleapis/enterprise-certificate-proxy v0.3.6/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA=
github.com/googleapis/gax-go/v2 v2.15.0 h1:SyjDc1mGgZU5LncH8gimWo9lW1DtIfPibOG81vgd/bo=
github.com/googleapis/gax-go/v2 v2.15.0/go.mod h1:zVVkkxAQHa1RQpg9z2AUCMnKhi0Qld9rcmyfL1OZhoc=
github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc h1:GN2Lv3MGO7AS6PrRoT6yV5+wkrOpcszoIsO4+4ds248=
@ -227,8 +227,9 @@ github.com/libdns/libdns v1.1.1/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfs
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA=
github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
@ -275,8 +276,8 @@ github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
github.com/quic-go/quic-go v0.57.1 h1:25KAAR9QR8KZrCZRThWMKVAwGoiHIrNbT72ULHTuI10=
github.com/quic-go/quic-go v0.57.1/go.mod h1:ly4QBAjHA2VhdnxhojRsCUOeJwKYg+taDlos92xb1+s=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
@ -295,20 +296,21 @@ github.com/slackhq/nebula v1.9.7 h1:v5u46efIyYHGdfjFnozQbRRhMdaB9Ma1SSTcUcE2lfE=
github.com/slackhq/nebula v1.9.7/go.mod h1:1+4q4wd3dDAjO8rKCttSb9JIVbklQhuJiBp5I0lbIsQ=
github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262 h1:unQFBIznI+VYD1/1fApl1A+9VcBk+9dcqGfnePY87LY=
github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262/go.mod h1:MyOHs9Po2fbM1LHej6sBUT8ozbxmMOFG+E+rx/GSGuc=
github.com/smallstep/certificates v0.29.0 h1:f90szTKYTW62bmCc+qE5doGqIGPVxTQb8Ba37e/K8Zs=
github.com/smallstep/certificates v0.29.0/go.mod h1:27WI0od6gu84mvE4mYQ/QZGyYwHXvhsiSRNC+y3t+mo=
github.com/smallstep/cli-utils v0.12.2 h1:lGzM9PJrH/qawbzMC/s2SvgLdJPKDWKwKzx9doCVO+k=
github.com/smallstep/cli-utils v0.12.2/go.mod h1:uCPqefO29goHLGqFnwk0i8W7XJu18X3WHQFRtOm/00Y=
github.com/smallstep/certificates v0.28.4 h1:JTU6/A5Xes6m+OsR6fw1RACSA362vJc9SOFVG7poBEw=
github.com/smallstep/certificates v0.28.4/go.mod h1:LUqo+7mKZE7FZldlTb0zhU4A0bq4G4+akieFMcTaWvA=
github.com/smallstep/cli-utils v0.12.1 h1:D9QvfbFqiKq3snGZ2xDcXEFrdFJ1mQfPHZMq/leerpE=
github.com/smallstep/cli-utils v0.12.1/go.mod h1:skV2Neg8qjiKPu2fphM89H9bIxNpKiiRTnX9Q6Lc+20=
github.com/smallstep/go-attestation v0.4.4-0.20241119153605-2306d5b464ca h1:VX8L0r8vybH0bPeaIxh4NQzafKQiqvlOn8pmOXbFLO4=
github.com/smallstep/go-attestation v0.4.4-0.20241119153605-2306d5b464ca/go.mod h1:vNAduivU014fubg6ewygkAvQC0IQVXqdc8vaGl/0er4=
github.com/smallstep/linkedca v0.25.0 h1:txT9QHGbCsJq0MhAghBq7qhurGY727tQuqUi+n4BVBo=
github.com/smallstep/linkedca v0.25.0/go.mod h1:Q3jVAauFKNlF86W5/RFtgQeyDKz98GL/KN3KG4mJOvc=
github.com/smallstep/linkedca v0.23.0 h1:5W/7EudlK1HcCIdZM68dJlZ7orqCCCyv6bm2l/0JmLU=
github.com/smallstep/linkedca v0.23.0/go.mod h1:7cyRM9soAYySg9ag65QwytcgGOM+4gOlkJ/YA58A9E8=
github.com/smallstep/nosql v0.7.0 h1:YiWC9ZAHcrLCrayfaF+QJUv16I2bZ7KdLC3RpJcnAnE=
github.com/smallstep/nosql v0.7.0/go.mod h1:H5VnKMCbeq9QA6SRY5iqPylfxLfYcLwvUff3onQ8+HU=
github.com/smallstep/pkcs7 v0.0.0-20240911091500-b1cae6277023/go.mod h1:CM5KrX7rxWgwDdMj9yef/pJB2OPgy/56z4IEx2UIbpc=
github.com/smallstep/pkcs7 v0.2.1 h1:6Kfzr/QizdIuB6LSv8y1LJdZ3aPSfTNhTLqAx9CTLfA=
github.com/smallstep/pkcs7 v0.2.1/go.mod h1:RcXHsMfL+BzH8tRhmrF1NkkpebKpq3JEM66cOFxanf0=
github.com/smallstep/scep v0.0.0-20250318231241-a25cabb69492 h1:k23+s51sgYix4Zgbvpmy+1ZgXLjr4ZTkBTqXmpnImwA=
github.com/smallstep/scep v0.0.0-20250318231241-a25cabb69492/go.mod h1:QQhwLqCS13nhv8L5ov7NgusowENUtXdEzdytjmJHdZQ=
github.com/smallstep/scep v0.0.0-20240926084937-8cf1ca453101 h1:LyZqn24/ZiVg8v9Hq07K6mx6RqPtpDeK+De5vf4QEY4=
github.com/smallstep/scep v0.0.0-20240926084937-8cf1ca453101/go.mod h1:EuKQjYGQwhUa1mgD21zxIgOgUYLsqikJmvxNscxpS/Y=
github.com/smallstep/truststore v0.13.0 h1:90if9htAOblavbMeWlqNLnO9bsjjgVv2hQeQJCi/py4=
github.com/smallstep/truststore v0.13.0/go.mod h1:3tmMp2aLKZ/OA/jnFUB0cYPcho402UG2knuJoPh4j7A=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
@ -366,8 +368,8 @@ github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0=
go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/contrib/bridges/prometheus v0.63.0 h1:/Rij/t18Y7rUayNg7Id6rPrEnHgorxYabm2E6wUdPP4=
go.opentelemetry.io/contrib/bridges/prometheus v0.63.0/go.mod h1:AdyDPn6pkbkt2w01n3BubRVk7xAsCRq1Yg1mpfyA/0E=
go.opentelemetry.io/contrib/exporters/autoexport v0.63.0 h1:NLnZybb9KkfMXPwZhd5diBYJoVxiO9Qa06dacEA7ySY=
@ -448,6 +450,7 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
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.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
@ -472,14 +475,15 @@ 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.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=
golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
@ -494,12 +498,14 @@ golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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.25.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.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
@ -511,6 +517,7 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
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.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
@ -522,6 +529,7 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
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.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
@ -538,16 +546,16 @@ golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/api v0.256.0 h1:u6Khm8+F9sxbCTYNoBHg6/Hwv0N/i+V94MvkOSor6oI=
google.golang.org/api v0.256.0/go.mod h1:KIgPhksXADEKJlnEoRa9qAII4rXcy40vfI8HRqcU964=
google.golang.org/api v0.254.0 h1:jl3XrGj7lRjnlUvZAbAdhINTLbsg5dbjmR90+pTQvt4=
google.golang.org/api v0.254.0/go.mod h1:5BkSURm3D9kAqjGvBNgf0EcbX6Rnrf6UArKkwBzAyqQ=
google.golang.org/genproto v0.0.0-20250603155806-513f23925822 h1:rHWScKit0gvAPuOnu87KpaYtjK5zBMLcULh7gxkCXu4=
google.golang.org/genproto v0.0.0-20250603155806-513f23925822/go.mod h1:HubltRL7rMh0LfnQPkMH4NPDFEWp0jw3vixw7jEM53s=
google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 h1:mepRgnBZa07I4TRuomDE4sTIYieg/osKmzIf4USdWS4=
google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8/go.mod h1:fDMmzKV90WSg1NbozdqrE64fkuTv6mlq2zxo9ad+3yo=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101 h1:tRPGkdGHuewF4UisLzzHHr1spKw92qLM98nIzxbC0wY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM=
google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig=
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 h1:BIRfGDEjiHRrk0QKZe3Xv2ieMhtgRGeLcZQ0mIVn4EY=
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5/go.mod h1:j3QtIyytwqGr1JUDtYXwtMXWPKsEa5LtzIFN1Wn5WvE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 h1:M1rk8KBnUsBDg1oPGHNCxG4vc1f49epmTO7xscSajMk=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A=
google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 h1:F29+wU6Ee6qgu9TddPgooOdaqsxTMunOoj8KA5yuS5A=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1/go.mod h1:5KF+wpkbTSbGcR9zteSqZV6fqFOWBl4Yde8En8MryZA=
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=

View file

@ -511,7 +511,7 @@ func JoinNetworkAddress(network, host, port string) string {
//
// NOTE: This API is EXPERIMENTAL and may be changed or removed.
// NOTE: user should close the returned listener twice, once to stop accepting new connections, the second time to free up the packet conn.
func (na NetworkAddress) ListenQUIC(ctx context.Context, portOffset uint, config net.ListenConfig, tlsConf *tls.Config, pcWrappers []PacketConnWrapper) (http3.QUICListener, error) {
func (na NetworkAddress) ListenQUIC(ctx context.Context, portOffset uint, config net.ListenConfig, tlsConf *tls.Config) (http3.QUICListener, error) {
lnKey := listenerKey("quic"+na.Network, na.JoinHostPort(portOffset))
sharedEarlyListener, _, err := listenerPool.LoadOrNew(lnKey, func() (Destructor, error) {
@ -523,19 +523,12 @@ func (na NetworkAddress) ListenQUIC(ctx context.Context, portOffset uint, config
ln := lnAny.(net.PacketConn)
h3ln := ln
if len(pcWrappers) == 0 {
for {
// retrieve the underlying socket, so quic-go can optimize.
if unwrapper, ok := h3ln.(interface{ Unwrap() net.PacketConn }); ok {
h3ln = unwrapper.Unwrap()
} else {
break
}
}
} else {
// wrap packet conn before QUIC
for _, pcWrapper := range pcWrappers {
h3ln = pcWrapper.WrapPacketConn(h3ln)
for {
// retrieve the underlying socket, so quic-go can optimize.
if unwrapper, ok := h3ln.(interface{ Unwrap() net.PacketConn }); ok {
h3ln = unwrapper.Unwrap()
} else {
break
}
}
@ -782,19 +775,6 @@ type ListenerWrapper interface {
WrapListener(net.Listener) net.Listener
}
// PacketConnWrapper is a type that wraps a packet conn
// so it can modify the input packet conn methods.
// Modules that implement this interface are found
// in the caddy.packetconns namespace. Usually, to
// wrap a packet conn, you will define your own struct
// type that embeds the input packet conn, then
// implement your own methods that you want to wrap,
// calling the underlying packet conn methods where
// appropriate.
type PacketConnWrapper interface {
WrapPacketConn(net.PacketConn) net.PacketConn
}
// listenerPool stores and allows reuse of active listeners.
var listenerPool = NewUsagePool()

View file

@ -82,7 +82,6 @@ func init() {
// `{http.request.tls.proto}` | The negotiated next protocol
// `{http.request.tls.proto_mutual}` | The negotiated next protocol was advertised by the server
// `{http.request.tls.server_name}` | The server name requested by the client, if any
// `{http.request.tls.ech}` | Whether ECH was offered by the client and accepted by the server
// `{http.request.tls.client.fingerprint}` | The SHA256 checksum of the client certificate
// `{http.request.tls.client.public_key}` | The public key of the client certificate.
// `{http.request.tls.client.public_key_sha256}` | The SHA256 checksum of the client's public key.
@ -347,20 +346,6 @@ func (app *App) Provision(ctx caddy.Context) error {
srv.listenerWrappers = append([]caddy.ListenerWrapper{new(tlsPlaceholderWrapper)}, srv.listenerWrappers...)
}
}
// set up each packet conn modifier
if srv.PacketConnWrappersRaw != nil {
vals, err := ctx.LoadModule(srv, "PacketConnWrappersRaw")
if err != nil {
return fmt.Errorf("loading packet conn wrapper modules: %v", err)
}
// if any wrappers were configured, they come before the QUIC handshake;
// unlike TLS above, there is no QUIC placeholder
for _, val := range vals.([]any) {
srv.packetConnWrappers = append(srv.packetConnWrappers, val.(caddy.PacketConnWrapper))
}
}
// pre-compile the primary handler chain, and be sure to wrap it in our
// route handler so that important security checks are done, etc.
primaryRoute := emptyHandler

View file

@ -110,7 +110,6 @@ func (t LoggableTLSConnState) MarshalLogObject(enc zapcore.ObjectEncoder) error
enc.AddUint16("cipher_suite", t.CipherSuite)
enc.AddString("proto", t.NegotiatedProtocol)
enc.AddString("server_name", t.ServerName)
enc.AddBool("ech", t.ECHAccepted)
if len(t.PeerCertificates) > 0 {
enc.AddString("client_common_name", t.PeerCertificates[0].Subject.CommonName)
enc.AddString("client_serial", t.PeerCertificates[0].SerialNumber.String())

View file

@ -511,8 +511,6 @@ func getReqTLSReplacement(req *http.Request, key string) (any, bool) {
return true, true
case "server_name":
return req.TLS.ServerName, true
case "ech":
return req.TLS.ECHAccepted, true
}
return nil, false
}

View file

@ -55,10 +55,6 @@ type Server struct {
// of the base listener. They are applied in the given order.
ListenerWrappersRaw []json.RawMessage `json:"listener_wrappers,omitempty" caddy:"namespace=caddy.listeners inline_key=wrapper"`
// A list of packet conn wrapper modules, which can modify the behavior
// of the base packet conn. They are applied in the given order.
PacketConnWrappersRaw []json.RawMessage `json:"packet_conn_wrappers,omitempty" caddy:"namespace=caddy.packetconns inline_key=wrapper"`
// How long to allow a read from a client's upload. Setting this
// to a short, non-zero value can mitigate slowloris attacks, but
// may also affect legitimately slow clients.
@ -262,8 +258,7 @@ type Server struct {
primaryHandlerChain Handler
errorHandlerChain Handler
listenerWrappers []caddy.ListenerWrapper
packetConnWrappers []caddy.PacketConnWrapper
listeners []net.Listener
listeners []net.Listener // stdlib http.Server will close these
quicListeners []http3.QUICListener // http3 now leave the quic.Listener management to us
tlsApp *caddytls.TLS
@ -630,7 +625,7 @@ func (s *Server) serveHTTP3(addr caddy.NetworkAddress, tlsCfg *tls.Config) error
return fmt.Errorf("starting HTTP/3 QUIC listener: %v", err)
}
addr.Network = h3net
h3ln, err := addr.ListenQUIC(s.ctx, 0, net.ListenConfig{}, tlsCfg, s.packetConnWrappers)
h3ln, err := addr.ListenQUIC(s.ctx, 0, net.ListenConfig{}, tlsCfg)
if err != nil {
return fmt.Errorf("starting HTTP/3 QUIC listener: %v", err)
}
@ -768,11 +763,9 @@ func (s *Server) shouldLogRequest(r *http.Request) bool {
hostWithoutPort = r.Host
}
for loggerName := range s.Logs.LoggerNames {
if certmagic.MatchWildcard(hostWithoutPort, loggerName) {
// this host is mapped to a particular logger name
return true
}
if _, ok := s.Logs.LoggerNames[hostWithoutPort]; ok {
// this host is mapped to a particular logger name
return true
}
for _, dh := range s.Logs.SkipHosts {
// logging for this particular host is disabled

View file

@ -306,13 +306,6 @@ func init() {
// find the documentation on time layouts [in Go's docs](https://pkg.go.dev/time#pkg-constants).
// The default time layout is `RFC1123Z`, i.e. `Mon, 02 Jan 2006 15:04:05 -0700`.
//
// ```
// {{humanize "size" "2048000"}}
// {{placeholder "http.response.header.Content-Length" | humanize "size"}}
// {{humanize "time" "Fri, 05 May 2022 15:04:05 +0200"}}
// {{humanize "time:2006-Jan-02" "2022-May-05"}}
// ```
//
// ##### `pathEscape`
//
// Passes a string through `url.PathEscape`, replacing characters that have
@ -325,22 +318,11 @@ func init() {
// {{pathEscape "50%_valid_filename?.jpg"}}
// ```
//
// ##### `maybe`
//
// Invokes a custom template function only if it is registered (plugged-in)
// in the `http.handlers.templates.functions.*` namespace.
//
// The first argument is the function name, and any subsequent arguments
// are forwarded to that function. If the named function is not available,
// the invocation is ignored and a log message is emitted.
//
// This is useful for templates that optionally use components which may
// not be present in every build or environment.
//
// NOTE: This function is EXPERIMENTAL and subject to change or removal.
//
// ```
// {{ maybe "myOptionalFunc" "arg1" 2 }}
// {{humanize "size" "2048000"}}
// {{placeholder "http.response.header.Content-Length" | humanize "size"}}
// {{humanize "time" "Fri, 05 May 2022 15:04:05 +0200"}}
// {{humanize "time:2006-Jan-02" "2022-May-05"}}
// ```
type Templates struct {
// The root path from which to load files. Required if template functions

View file

@ -222,16 +222,11 @@ func rootAndIntermediatePEM(ca *CA) (root, inter []byte, err error) {
if err != nil {
return root, inter, err
}
for _, interCert := range ca.IntermediateCertificateChain() {
pemBytes, err := pemEncodeCert(interCert.Raw)
if err != nil {
return nil, nil, err
}
inter = append(inter, pemBytes...)
inter, err = pemEncodeCert(ca.IntermediateCertificate().Raw)
if err != nil {
return root, inter, err
}
return
return root, inter, err
}
// caInfo is the response structure for the CA info API endpoint.

View file

@ -75,11 +75,10 @@ type CA struct {
// and module provisioning.
ID string `json:"-"`
storage certmagic.Storage
root *x509.Certificate
interChain []*x509.Certificate
interKey crypto.Signer
mu *sync.RWMutex
storage certmagic.Storage
root, inter *x509.Certificate
interKey any // TODO: should we just store these as crypto.Signer?
mu *sync.RWMutex
rootCertPath string // mainly used for logging purposes if trusting
log *zap.Logger
@ -128,16 +127,14 @@ func (ca *CA) Provision(ctx caddy.Context, id string, log *zap.Logger) error {
}
// load the certs and key that will be used for signing
var rootCert *x509.Certificate
var rootCertChain, interCertChain []*x509.Certificate
var rootCert, interCert *x509.Certificate
var rootKey, interKey crypto.Signer
var err error
if ca.Root != nil {
if ca.Root.Format == "" || ca.Root.Format == "pem_file" {
ca.rootCertPath = ca.Root.Certificate
}
rootCertChain, rootKey, err = ca.Root.Load()
rootCert = rootCertChain[0]
rootCert, rootKey, err = ca.Root.Load()
} else {
ca.rootCertPath = "storage:" + ca.storageKeyRootCert()
rootCert, rootKey, err = ca.loadOrGenRoot()
@ -145,23 +142,21 @@ func (ca *CA) Provision(ctx caddy.Context, id string, log *zap.Logger) error {
if err != nil {
return err
}
actualRootLifetime := time.Until(rootCert.NotAfter)
if time.Duration(ca.IntermediateLifetime) >= actualRootLifetime {
return fmt.Errorf("intermediate certificate lifetime must be less than actual root certificate lifetime (%s)", actualRootLifetime)
}
if ca.Intermediate != nil {
interCertChain, interKey, err = ca.Intermediate.Load()
interCert, interKey, err = ca.Intermediate.Load()
} else {
actualRootLifetime := time.Until(rootCert.NotAfter)
if time.Duration(ca.IntermediateLifetime) >= actualRootLifetime {
return fmt.Errorf("intermediate certificate lifetime must be less than actual root certificate lifetime (%s)", actualRootLifetime)
}
interCertChain, interKey, err = ca.loadOrGenIntermediate(rootCert, rootKey)
interCert, interKey, err = ca.loadOrGenIntermediate(rootCert, rootKey)
}
if err != nil {
return err
}
ca.mu.Lock()
ca.root, ca.interChain, ca.interKey = rootCert, interCertChain, interKey
ca.root, ca.inter, ca.interKey = rootCert, interCert, interKey
ca.mu.Unlock()
return nil
@ -177,21 +172,21 @@ func (ca CA) RootCertificate() *x509.Certificate {
// RootKey returns the CA's root private key. Since the root key is
// not cached in memory long-term, it needs to be loaded from storage,
// which could yield an error.
func (ca CA) RootKey() (crypto.Signer, error) {
func (ca CA) RootKey() (any, error) {
_, rootKey, err := ca.loadOrGenRoot()
return rootKey, err
}
// IntermediateCertificateChain returns the CA's intermediate
// certificate chain.
func (ca CA) IntermediateCertificateChain() []*x509.Certificate {
// IntermediateCertificate returns the CA's intermediate
// certificate (public key).
func (ca CA) IntermediateCertificate() *x509.Certificate {
ca.mu.RLock()
defer ca.mu.RUnlock()
return ca.interChain
return ca.inter
}
// IntermediateKey returns the CA's intermediate private key.
func (ca CA) IntermediateKey() crypto.Signer {
func (ca CA) IntermediateKey() any {
ca.mu.RLock()
defer ca.mu.RUnlock()
return ca.interKey
@ -212,27 +207,26 @@ func (ca *CA) NewAuthority(authorityConfig AuthorityConfig) (*authority.Authorit
// cert/key directly, since it's unlikely to expire
// while Caddy is running (long lifetime)
var issuerCert *x509.Certificate
var issuerKey crypto.Signer
var issuerKey any
issuerCert = rootCert
var err error
issuerKey, err = ca.RootKey()
if err != nil {
return nil, fmt.Errorf("loading signing key: %v", err)
}
signerOption = authority.WithX509Signer(issuerCert, issuerKey)
signerOption = authority.WithX509Signer(issuerCert, issuerKey.(crypto.Signer))
} else {
// if we're signing with intermediate, we need to make
// sure it's always fresh, because the intermediate may
// renew while Caddy is running (medium lifetime)
signerOption = authority.WithX509SignerFunc(func() ([]*x509.Certificate, crypto.Signer, error) {
issuerChain := ca.IntermediateCertificateChain()
issuerCert := issuerChain[0]
issuerKey := ca.IntermediateKey()
issuerCert := ca.IntermediateCertificate()
issuerKey := ca.IntermediateKey().(crypto.Signer)
ca.log.Debug("using intermediate signer",
zap.String("serial", issuerCert.SerialNumber.String()),
zap.String("not_before", issuerCert.NotBefore.String()),
zap.String("not_after", issuerCert.NotAfter.String()))
return issuerChain, issuerKey, nil
return []*x509.Certificate{issuerCert}, issuerKey, nil
})
}
@ -258,11 +252,7 @@ func (ca *CA) NewAuthority(authorityConfig AuthorityConfig) (*authority.Authorit
func (ca CA) loadOrGenRoot() (rootCert *x509.Certificate, rootKey crypto.Signer, err error) {
if ca.Root != nil {
rootChain, rootSigner, err := ca.Root.Load()
if err != nil {
return nil, nil, err
}
return rootChain[0], rootSigner, nil
return ca.Root.Load()
}
rootCertPEM, err := ca.storage.Load(ca.ctx, ca.storageKeyRootCert())
if err != nil {
@ -278,7 +268,7 @@ func (ca CA) loadOrGenRoot() (rootCert *x509.Certificate, rootKey crypto.Signer,
}
if rootCert == nil {
rootCert, err = pemDecodeCertificate(rootCertPEM)
rootCert, err = pemDecodeSingleCert(rootCertPEM)
if err != nil {
return nil, nil, fmt.Errorf("parsing root certificate PEM: %v", err)
}
@ -324,8 +314,7 @@ func (ca CA) genRoot() (rootCert *x509.Certificate, rootKey crypto.Signer, err e
return rootCert, rootKey, nil
}
func (ca CA) loadOrGenIntermediate(rootCert *x509.Certificate, rootKey crypto.Signer) (interCertChain []*x509.Certificate, interKey crypto.Signer, err error) {
var interCert *x509.Certificate
func (ca CA) loadOrGenIntermediate(rootCert *x509.Certificate, rootKey crypto.Signer) (interCert *x509.Certificate, interKey crypto.Signer, err error) {
interCertPEM, err := ca.storage.Load(ca.ctx, ca.storageKeyIntermediateCert())
if err != nil {
if !errors.Is(err, fs.ErrNotExist) {
@ -337,12 +326,10 @@ func (ca CA) loadOrGenIntermediate(rootCert *x509.Certificate, rootKey crypto.Si
if err != nil {
return nil, nil, fmt.Errorf("generating new intermediate cert: %v", err)
}
interCertChain = append(interCertChain, interCert)
}
if len(interCertChain) == 0 {
interCertChain, err = pemDecodeCertificateChain(interCertPEM)
if interCert == nil {
interCert, err = pemDecodeSingleCert(interCertPEM)
if err != nil {
return nil, nil, fmt.Errorf("decoding intermediate certificate PEM: %v", err)
}
@ -359,7 +346,7 @@ func (ca CA) loadOrGenIntermediate(rootCert *x509.Certificate, rootKey crypto.Si
}
}
return interCertChain, interKey, nil
return interCert, interKey, nil
}
func (ca CA) genIntermediate(rootCert *x509.Certificate, rootKey crypto.Signer) (interCert *x509.Certificate, interKey crypto.Signer, err error) {

View file

@ -17,20 +17,15 @@ package caddypki
import (
"bytes"
"crypto"
"crypto/ecdsa"
"crypto/ed25519"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"os"
"github.com/caddyserver/certmagic"
"go.step.sm/crypto/pemutil"
)
func pemDecodeCertificate(pemDER []byte) (*x509.Certificate, error) {
func pemDecodeSingleCert(pemDER []byte) (*x509.Certificate, error) {
pemBlock, remaining := pem.Decode(pemDER)
if pemBlock == nil {
return nil, fmt.Errorf("no PEM block found")
@ -44,15 +39,6 @@ func pemDecodeCertificate(pemDER []byte) (*x509.Certificate, error) {
return x509.ParseCertificate(pemBlock.Bytes)
}
func pemDecodeCertificateChain(pemDER []byte) ([]*x509.Certificate, error) {
chain, err := pemutil.ParseCertificateBundle(pemDER)
if err != nil {
return nil, fmt.Errorf("failed parsing certificate chain: %w", err)
}
return chain, nil
}
func pemEncodeCert(der []byte) ([]byte, error) {
return pemEncode("CERTIFICATE", der)
}
@ -84,18 +70,15 @@ type KeyPair struct {
Format string `json:"format,omitempty"`
}
// Load loads the certificate chain and (optional) private key from
// the corresponding files, using the configured format. If a
// private key is read, it will be verified to belong to the first
// certificate in the chain.
func (kp KeyPair) Load() ([]*x509.Certificate, crypto.Signer, error) {
// Load loads the certificate and key.
func (kp KeyPair) Load() (*x509.Certificate, crypto.Signer, error) {
switch kp.Format {
case "", "pem_file":
certData, err := os.ReadFile(kp.Certificate)
if err != nil {
return nil, nil, err
}
chain, err := pemDecodeCertificateChain(certData)
cert, err := pemDecodeSingleCert(certData)
if err != nil {
return nil, nil, err
}
@ -110,49 +93,11 @@ func (kp KeyPair) Load() ([]*x509.Certificate, crypto.Signer, error) {
if err != nil {
return nil, nil, err
}
if err := verifyKeysMatch(chain[0], key); err != nil {
return nil, nil, err
}
}
return chain, key, nil
return cert, key, nil
default:
return nil, nil, fmt.Errorf("unsupported format: %s", kp.Format)
}
}
// verifyKeysMatch verifies that the public key in the [x509.Certificate] matches
// the public key of the [crypto.Signer].
func verifyKeysMatch(crt *x509.Certificate, signer crypto.Signer) error {
switch pub := crt.PublicKey.(type) {
case *rsa.PublicKey:
pk, ok := signer.Public().(*rsa.PublicKey)
if !ok {
return fmt.Errorf("private key type %T does not match issuer public key type %T", signer.Public(), pub)
}
if !pub.Equal(pk) {
return errors.New("private key does not match issuer public key")
}
case *ecdsa.PublicKey:
pk, ok := signer.Public().(*ecdsa.PublicKey)
if !ok {
return fmt.Errorf("private key type %T does not match issuer public key type %T", signer.Public(), pub)
}
if !pub.Equal(pk) {
return errors.New("private key does not match issuer public key")
}
case ed25519.PublicKey:
pk, ok := signer.Public().(ed25519.PublicKey)
if !ok {
return fmt.Errorf("private key type %T does not match issuer public key type %T", signer.Public(), pub)
}
if !pub.Equal(pk) {
return errors.New("private key does not match issuer public key")
}
default:
return fmt.Errorf("unsupported key type: %T", pub)
}
return nil
}

View file

@ -1,314 +0,0 @@
// Copyright 2015 Matthew Holt and The Caddy Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package caddypki
import (
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"os"
"path/filepath"
"testing"
"time"
"go.step.sm/crypto/keyutil"
"go.step.sm/crypto/pemutil"
)
func TestKeyPair_Load(t *testing.T) {
rootSigner, err := keyutil.GenerateDefaultSigner()
if err != nil {
t.Fatalf("Failed creating signer: %v", err)
}
tmpl := &x509.Certificate{
Subject: pkix.Name{CommonName: "test-root"},
IsCA: true,
MaxPathLen: 3,
}
rootBytes, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, rootSigner.Public(), rootSigner)
if err != nil {
t.Fatalf("Creating root certificate failed: %v", err)
}
root, err := x509.ParseCertificate(rootBytes)
if err != nil {
t.Fatalf("Parsing root certificate failed: %v", err)
}
intermediateSigner, err := keyutil.GenerateDefaultSigner()
if err != nil {
t.Fatalf("Creating intermedaite signer failed: %v", err)
}
intermediateBytes, err := x509.CreateCertificate(rand.Reader, &x509.Certificate{
Subject: pkix.Name{CommonName: "test-first-intermediate"},
IsCA: true,
MaxPathLen: 2,
NotAfter: time.Now().Add(time.Hour),
}, root, intermediateSigner.Public(), rootSigner)
if err != nil {
t.Fatalf("Creating intermediate certificate failed: %v", err)
}
intermediate, err := x509.ParseCertificate(intermediateBytes)
if err != nil {
t.Fatalf("Parsing intermediate certificate failed: %v", err)
}
var chainContents []byte
chain := []*x509.Certificate{intermediate, root}
for _, cert := range chain {
b, err := pemutil.Serialize(cert)
if err != nil {
t.Fatalf("Failed serializing intermediate certificate: %v", err)
}
chainContents = append(chainContents, pem.EncodeToMemory(b)...)
}
dir := t.TempDir()
rootCertFile := filepath.Join(dir, "root.pem")
if _, err = pemutil.Serialize(root, pemutil.WithFilename(rootCertFile)); err != nil {
t.Fatalf("Failed serializing root certificate: %v", err)
}
rootKeyFile := filepath.Join(dir, "root.key")
if _, err = pemutil.Serialize(rootSigner, pemutil.WithFilename(rootKeyFile)); err != nil {
t.Fatalf("Failed serializing root key: %v", err)
}
intermediateCertFile := filepath.Join(dir, "intermediate.pem")
if _, err = pemutil.Serialize(intermediate, pemutil.WithFilename(intermediateCertFile)); err != nil {
t.Fatalf("Failed serializing intermediate certificate: %v", err)
}
intermediateKeyFile := filepath.Join(dir, "intermediate.key")
if _, err = pemutil.Serialize(intermediateSigner, pemutil.WithFilename(intermediateKeyFile)); err != nil {
t.Fatalf("Failed serializing intermediate key: %v", err)
}
chainFile := filepath.Join(dir, "chain.pem")
if err := os.WriteFile(chainFile, chainContents, 0644); err != nil {
t.Fatalf("Failed writing intermediate chain: %v", err)
}
t.Run("ok/single-certificate-without-signer", func(t *testing.T) {
kp := KeyPair{
Certificate: rootCertFile,
}
chain, signer, err := kp.Load()
if err != nil {
t.Fatalf("Failed loading KeyPair: %v", err)
}
if len(chain) != 1 {
t.Errorf("Expected 1 certificate in chain; got %d", len(chain))
}
if signer != nil {
t.Error("Expected no signer to be returned")
}
})
t.Run("ok/single-certificate-with-signer", func(t *testing.T) {
kp := KeyPair{
Certificate: rootCertFile,
PrivateKey: rootKeyFile,
}
chain, signer, err := kp.Load()
if err != nil {
t.Fatalf("Failed loading KeyPair: %v", err)
}
if len(chain) != 1 {
t.Errorf("Expected 1 certificate in chain; got %d", len(chain))
}
if signer == nil {
t.Error("Expected signer to be returned")
}
})
t.Run("ok/multiple-certificates-with-signer", func(t *testing.T) {
kp := KeyPair{
Certificate: chainFile,
PrivateKey: intermediateKeyFile,
}
chain, signer, err := kp.Load()
if err != nil {
t.Fatalf("Failed loading KeyPair: %v", err)
}
if len(chain) != 2 {
t.Errorf("Expected 2 certificates in chain; got %d", len(chain))
}
if signer == nil {
t.Error("Expected signer to be returned")
}
})
t.Run("fail/non-matching-public-key", func(t *testing.T) {
kp := KeyPair{
Certificate: intermediateCertFile,
PrivateKey: rootKeyFile,
}
chain, signer, err := kp.Load()
if err == nil {
t.Error("Expected loading KeyPair to return an error")
}
if chain != nil {
t.Error("Expected no chain to be returned")
}
if signer != nil {
t.Error("Expected no signer to be returned")
}
})
}
func Test_pemDecodeCertificate(t *testing.T) {
signer, err := keyutil.GenerateDefaultSigner()
if err != nil {
t.Fatalf("Failed creating signer: %v", err)
}
tmpl := &x509.Certificate{
Subject: pkix.Name{CommonName: "test-cert"},
IsCA: true,
MaxPathLen: 3,
}
derBytes, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, signer.Public(), signer)
if err != nil {
t.Fatalf("Creating root certificate failed: %v", err)
}
cert, err := x509.ParseCertificate(derBytes)
if err != nil {
t.Fatalf("Parsing root certificate failed: %v", err)
}
pemBlock, err := pemutil.Serialize(cert)
if err != nil {
t.Fatalf("Failed serializing certificate: %v", err)
}
pemData := pem.EncodeToMemory(pemBlock)
t.Run("ok", func(t *testing.T) {
cert, err := pemDecodeCertificate(pemData)
if err != nil {
t.Fatalf("Failed decoding PEM data: %v", err)
}
if cert == nil {
t.Errorf("Expected a certificate in PEM data")
}
})
t.Run("fail/no-pem-data", func(t *testing.T) {
cert, err := pemDecodeCertificate(nil)
if err == nil {
t.Fatalf("Expected pemDecodeCertificate to return an error")
}
if cert != nil {
t.Errorf("Expected pemDecodeCertificate to return nil")
}
})
t.Run("fail/multiple", func(t *testing.T) {
multiplePEMData := append(pemData, pemData...)
cert, err := pemDecodeCertificate(multiplePEMData)
if err == nil {
t.Fatalf("Expected pemDecodeCertificate to return an error")
}
if cert != nil {
t.Errorf("Expected pemDecodeCertificate to return nil")
}
})
t.Run("fail/no-pem-certificate", func(t *testing.T) {
pkData := pem.EncodeToMemory(&pem.Block{
Type: "PRIVATE KEY",
Bytes: []byte("some-bogus-private-key"),
})
cert, err := pemDecodeCertificate(pkData)
if err == nil {
t.Fatalf("Expected pemDecodeCertificate to return an error")
}
if cert != nil {
t.Errorf("Expected pemDecodeCertificate to return nil")
}
})
}
func Test_pemDecodeCertificateChain(t *testing.T) {
signer, err := keyutil.GenerateDefaultSigner()
if err != nil {
t.Fatalf("Failed creating signer: %v", err)
}
tmpl := &x509.Certificate{
Subject: pkix.Name{CommonName: "test-cert"},
IsCA: true,
MaxPathLen: 3,
}
derBytes, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, signer.Public(), signer)
if err != nil {
t.Fatalf("Creating root certificate failed: %v", err)
}
cert, err := x509.ParseCertificate(derBytes)
if err != nil {
t.Fatalf("Parsing root certificate failed: %v", err)
}
pemBlock, err := pemutil.Serialize(cert)
if err != nil {
t.Fatalf("Failed serializing certificate: %v", err)
}
pemData := pem.EncodeToMemory(pemBlock)
t.Run("ok/single", func(t *testing.T) {
certs, err := pemDecodeCertificateChain(pemData)
if err != nil {
t.Fatalf("Failed decoding PEM data: %v", err)
}
if len(certs) != 1 {
t.Errorf("Expected 1 certificate in PEM data; got %d", len(certs))
}
})
t.Run("ok/multiple", func(t *testing.T) {
multiplePEMData := append(pemData, pemData...)
certs, err := pemDecodeCertificateChain(multiplePEMData)
if err != nil {
t.Fatalf("Failed decoding PEM data: %v", err)
}
if len(certs) != 2 {
t.Errorf("Expected 2 certificates in PEM data; got %d", len(certs))
}
})
t.Run("fail/no-pem-certificate", func(t *testing.T) {
pkData := pem.EncodeToMemory(&pem.Block{
Type: "PRIVATE KEY",
Bytes: []byte("some-bogus-private-key"),
})
certs, err := pemDecodeCertificateChain(pkData)
if err == nil {
t.Fatalf("Expected pemDecodeCertificateChain to return an error")
}
if len(certs) != 0 {
t.Errorf("Expected 0 certificates in PEM data; got %d", len(certs))
}
})
t.Run("fail/no-der-certificate", func(t *testing.T) {
certs, err := pemDecodeCertificateChain([]byte("invalid-der-data"))
if err == nil {
t.Fatalf("Expected pemDecodeCertificateChain to return an error")
}
if len(certs) != 0 {
t.Errorf("Expected 0 certificates in PEM data; got %d", len(certs))
}
})
}

View file

@ -66,16 +66,16 @@ func (p *PKI) renewCertsForCA(ca *CA) error {
if needsRenewal(ca.root) {
// TODO: implement root renewal (use same key)
log.Warn("root certificate expiring soon (FIXME: ROOT RENEWAL NOT YET IMPLEMENTED)",
zap.Duration("time_remaining", time.Until(ca.interChain[0].NotAfter)),
zap.Duration("time_remaining", time.Until(ca.inter.NotAfter)),
)
}
}
// only maintain the intermediate if it's not manually provided in the config
if ca.Intermediate == nil {
if needsRenewal(ca.interChain[0]) {
if needsRenewal(ca.inter) {
log.Info("intermediate expires soon; renewing",
zap.Duration("time_remaining", time.Until(ca.interChain[0].NotAfter)),
zap.Duration("time_remaining", time.Until(ca.inter.NotAfter)),
)
rootCert, rootKey, err := ca.loadOrGenRoot()
@ -86,10 +86,10 @@ func (p *PKI) renewCertsForCA(ca *CA) error {
if err != nil {
return fmt.Errorf("generating new certificate: %v", err)
}
ca.interChain, ca.interKey = []*x509.Certificate{interCert}, interKey
ca.inter, ca.interKey = interCert, interKey
log.Info("renewed intermediate",
zap.Time("new_expiration", ca.interChain[0].NotAfter),
zap.Time("new_expiration", ca.inter.NotAfter),
)
}
}

View file

@ -671,7 +671,7 @@ func ParseCaddyfilePreferredChainsOptions(d *caddyfile.Dispenser) (*ChainPrefere
switch d.Val() {
case "root_common_name":
rootCommonNameOpt := d.RemainingArgs()
chainPref.RootCommonName = append(chainPref.RootCommonName, rootCommonNameOpt...)
chainPref.RootCommonName = rootCommonNameOpt
if rootCommonNameOpt == nil {
return nil, d.ArgErr()
}
@ -681,7 +681,7 @@ func ParseCaddyfilePreferredChainsOptions(d *caddyfile.Dispenser) (*ChainPrefere
case "any_common_name":
anyCommonNameOpt := d.RemainingArgs()
chainPref.AnyCommonName = append(chainPref.AnyCommonName, anyCommonNameOpt...)
chainPref.AnyCommonName = anyCommonNameOpt
if anyCommonNameOpt == nil {
return nil, d.ArgErr()
}

View file

@ -257,7 +257,7 @@ func (PKIIntermediateCAPool) CaddyModule() caddy.ModuleInfo {
}
}
// Loads the PKI app and loads the intermediate certificates into the certificate pool
// Loads the PKI app and load the intermediate certificates into the certificate pool
func (p *PKIIntermediateCAPool) Provision(ctx caddy.Context) error {
pkiApp, err := ctx.AppIfConfigured("pki")
if err != nil {
@ -274,9 +274,7 @@ func (p *PKIIntermediateCAPool) Provision(ctx caddy.Context) error {
caPool := x509.NewCertPool()
for _, ca := range p.ca {
for _, c := range ca.IntermediateCertificateChain() {
caPool.AddCert(c)
}
caPool.AddCert(ca.IntermediateCertificate())
}
p.pool = caPool
return nil

View file

@ -115,8 +115,7 @@ func (iss InternalIssuer) Issue(ctx context.Context, csr *x509.CertificateReques
if iss.SignWithRoot {
issuerCert = iss.ca.RootCertificate()
} else {
chain := iss.ca.IntermediateCertificateChain()
issuerCert = chain[0]
issuerCert = iss.ca.IntermediateCertificate()
}
// ensure issued certificate does not expire later than its issuer

View file

@ -1,262 +0,0 @@
// Copyright 2015 Matthew Holt and The Caddy Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package caddytls
import (
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"os"
"path/filepath"
"testing"
"time"
"github.com/caddyserver/caddy/v2"
"github.com/caddyserver/caddy/v2/modules/caddypki"
"go.uber.org/zap"
"go.step.sm/crypto/keyutil"
"go.step.sm/crypto/pemutil"
)
func TestInternalIssuer_Issue(t *testing.T) {
rootSigner, err := keyutil.GenerateDefaultSigner()
if err != nil {
t.Fatalf("Creating root signer failed: %v", err)
}
tmpl := &x509.Certificate{
Subject: pkix.Name{CommonName: "test-root"},
IsCA: true,
MaxPathLen: 3,
NotAfter: time.Now().Add(7 * 24 * time.Hour),
NotBefore: time.Now().Add(-7 * 24 * time.Hour),
}
rootBytes, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, rootSigner.Public(), rootSigner)
if err != nil {
t.Fatalf("Creating root certificate failed: %v", err)
}
root, err := x509.ParseCertificate(rootBytes)
if err != nil {
t.Fatalf("Parsing root certificate failed: %v", err)
}
firstIntermediateSigner, err := keyutil.GenerateDefaultSigner()
if err != nil {
t.Fatalf("Creating intermedaite signer failed: %v", err)
}
firstIntermediateBytes, err := x509.CreateCertificate(rand.Reader, &x509.Certificate{
Subject: pkix.Name{CommonName: "test-first-intermediate"},
IsCA: true,
MaxPathLen: 2,
NotAfter: time.Now().Add(24 * time.Hour),
NotBefore: time.Now().Add(-24 * time.Hour),
}, root, firstIntermediateSigner.Public(), rootSigner)
if err != nil {
t.Fatalf("Creating intermediate certificate failed: %v", err)
}
firstIntermediate, err := x509.ParseCertificate(firstIntermediateBytes)
if err != nil {
t.Fatalf("Parsing intermediate certificate failed: %v", err)
}
secondIntermediateSigner, err := keyutil.GenerateDefaultSigner()
if err != nil {
t.Fatalf("Creating second intermedaite signer failed: %v", err)
}
secondIntermediateBytes, err := x509.CreateCertificate(rand.Reader, &x509.Certificate{
Subject: pkix.Name{CommonName: "test-second-intermediate"},
IsCA: true,
MaxPathLen: 2,
NotAfter: time.Now().Add(24 * time.Hour),
NotBefore: time.Now().Add(-24 * time.Hour),
}, firstIntermediate, secondIntermediateSigner.Public(), firstIntermediateSigner)
if err != nil {
t.Fatalf("Creating second intermediate certificate failed: %v", err)
}
secondIntermediate, err := x509.ParseCertificate(secondIntermediateBytes)
if err != nil {
t.Fatalf("Parsing second intermediate certificate failed: %v", err)
}
dir := t.TempDir()
storageDir := filepath.Join(dir, "certmagic")
rootCertFile := filepath.Join(dir, "root.pem")
if _, err = pemutil.Serialize(root, pemutil.WithFilename(rootCertFile)); err != nil {
t.Fatalf("Failed serializing root certificate: %v", err)
}
intermediateCertFile := filepath.Join(dir, "intermediate.pem")
if _, err = pemutil.Serialize(firstIntermediate, pemutil.WithFilename(intermediateCertFile)); err != nil {
t.Fatalf("Failed serializing intermediate certificate: %v", err)
}
intermediateKeyFile := filepath.Join(dir, "intermediate.key")
if _, err = pemutil.Serialize(firstIntermediateSigner, pemutil.WithFilename(intermediateKeyFile)); err != nil {
t.Fatalf("Failed serializing intermediate key: %v", err)
}
var intermediateChainContents []byte
intermediateChain := []*x509.Certificate{secondIntermediate, firstIntermediate}
for _, cert := range intermediateChain {
b, err := pemutil.Serialize(cert)
if err != nil {
t.Fatalf("Failed serializing intermediate certificate: %v", err)
}
intermediateChainContents = append(intermediateChainContents, pem.EncodeToMemory(b)...)
}
intermediateChainFile := filepath.Join(dir, "intermediates.pem")
if err := os.WriteFile(intermediateChainFile, intermediateChainContents, 0644); err != nil {
t.Fatalf("Failed writing intermediate chain: %v", err)
}
intermediateChainKeyFile := filepath.Join(dir, "intermediates.key")
if _, err = pemutil.Serialize(secondIntermediateSigner, pemutil.WithFilename(intermediateChainKeyFile)); err != nil {
t.Fatalf("Failed serializing intermediate key: %v", err)
}
signer, err := keyutil.GenerateDefaultSigner()
if err != nil {
t.Fatalf("Failed creating signer: %v", err)
}
csrBytes, err := x509.CreateCertificateRequest(rand.Reader, &x509.CertificateRequest{
Subject: pkix.Name{CommonName: "test"},
}, signer)
if err != nil {
t.Fatalf("Failed creating CSR: %v", err)
}
csr, err := x509.ParseCertificateRequest(csrBytes)
if err != nil {
t.Fatalf("Failed parsing CSR: %v", err)
}
t.Run("generated-with-defaults", func(t *testing.T) {
caddyCtx, cancel := caddy.NewContext(caddy.Context{Context: t.Context()})
t.Cleanup(cancel)
logger := zap.NewNop()
ca := &caddypki.CA{
StorageRaw: []byte(fmt.Sprintf(`{"module": "file_system", "root": %q}`, storageDir)),
}
if err := ca.Provision(caddyCtx, "local-test-generated", logger); err != nil {
t.Fatalf("Failed provisioning CA: %v", err)
}
iss := InternalIssuer{
SignWithRoot: false,
ca: ca,
logger: logger,
}
c, err := iss.Issue(t.Context(), csr)
if err != nil {
t.Fatalf("Failed issuing certificate: %v", err)
}
chain, err := pemutil.ParseCertificateBundle(c.Certificate)
if err != nil {
t.Errorf("Failed issuing certificate: %v", err)
}
if len(chain) != 2 {
t.Errorf("Expected 2 certificates in chain; got %d", len(chain))
}
})
t.Run("single-intermediate-from-disk", func(t *testing.T) {
caddyCtx, cancel := caddy.NewContext(caddy.Context{Context: t.Context()})
t.Cleanup(cancel)
logger := zap.NewNop()
ca := &caddypki.CA{
Root: &caddypki.KeyPair{
Certificate: rootCertFile,
},
Intermediate: &caddypki.KeyPair{
Certificate: intermediateCertFile,
PrivateKey: intermediateKeyFile,
},
StorageRaw: []byte(fmt.Sprintf(`{"module": "file_system", "root": %q}`, storageDir)),
}
if err := ca.Provision(caddyCtx, "local-test-single-intermediate", logger); err != nil {
t.Fatalf("Failed provisioning CA: %v", err)
}
iss := InternalIssuer{
ca: ca,
SignWithRoot: false,
logger: logger,
}
c, err := iss.Issue(t.Context(), csr)
if err != nil {
t.Fatalf("Failed issuing certificate: %v", err)
}
chain, err := pemutil.ParseCertificateBundle(c.Certificate)
if err != nil {
t.Errorf("Failed issuing certificate: %v", err)
}
if len(chain) != 2 {
t.Errorf("Expected 2 certificates in chain; got %d", len(chain))
}
})
t.Run("multiple-intermediates-from-disk", func(t *testing.T) {
caddyCtx, cancel := caddy.NewContext(caddy.Context{Context: t.Context()})
t.Cleanup(cancel)
logger := zap.NewNop()
ca := &caddypki.CA{
Root: &caddypki.KeyPair{
Certificate: rootCertFile,
},
Intermediate: &caddypki.KeyPair{
Certificate: intermediateChainFile,
PrivateKey: intermediateChainKeyFile,
},
StorageRaw: []byte(fmt.Sprintf(`{"module": "file_system", "root": %q}`, storageDir)),
}
if err := ca.Provision(caddyCtx, "local-test", zap.NewNop()); err != nil {
t.Fatalf("Failed provisioning CA: %v", err)
}
iss := InternalIssuer{
ca: ca,
SignWithRoot: false,
logger: logger,
}
c, err := iss.Issue(t.Context(), csr)
if err != nil {
t.Fatalf("Failed issuing certificate: %v", err)
}
chain, err := pemutil.ParseCertificateBundle(c.Certificate)
if err != nil {
t.Errorf("Failed issuing certificate: %v", err)
}
if len(chain) != 3 {
t.Errorf("Expected 3 certificates in chain; got %d", len(chain))
}
})
}