mirror of
https://github.com/caddyserver/caddy.git
synced 2025-12-08 06:09:53 +00:00
Compare commits
7 commits
v2.11.0-be
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
374b7a637f | ||
|
|
6e0cbd0fa0 | ||
|
|
bfdb04912d | ||
|
|
31960dc998 | ||
|
|
be5f49fbeb | ||
|
|
7ebe72bbfe | ||
|
|
8a87bb3ffb |
19 changed files with 897 additions and 154 deletions
|
|
@ -851,6 +851,20 @@ func (st *ServerType) serversFromPairings(
|
||||||
srv.ListenerWrappersRaw = append(srv.ListenerWrappersRaw, jsonListenerWrapper)
|
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
|
// set up each handler directive, making sure to honor directive order
|
||||||
dirRoutes := sblock.pile["route"]
|
dirRoutes := sblock.pile["route"]
|
||||||
siteSubroute, err := buildSubroute(dirRoutes, groupCounter, true)
|
siteSubroute, err := buildSubroute(dirRoutes, groupCounter, true)
|
||||||
|
|
|
||||||
|
|
@ -36,26 +36,27 @@ type serverOptions struct {
|
||||||
ListenerAddress string
|
ListenerAddress string
|
||||||
|
|
||||||
// These will all map 1:1 to the caddyhttp.Server struct
|
// These will all map 1:1 to the caddyhttp.Server struct
|
||||||
Name string
|
Name string
|
||||||
ListenerWrappersRaw []json.RawMessage
|
ListenerWrappersRaw []json.RawMessage
|
||||||
ReadTimeout caddy.Duration
|
PacketConnWrappersRaw []json.RawMessage
|
||||||
ReadHeaderTimeout caddy.Duration
|
ReadTimeout caddy.Duration
|
||||||
WriteTimeout caddy.Duration
|
ReadHeaderTimeout caddy.Duration
|
||||||
IdleTimeout caddy.Duration
|
WriteTimeout caddy.Duration
|
||||||
KeepAliveInterval caddy.Duration
|
IdleTimeout caddy.Duration
|
||||||
KeepAliveIdle caddy.Duration
|
KeepAliveInterval caddy.Duration
|
||||||
KeepAliveCount int
|
KeepAliveIdle caddy.Duration
|
||||||
MaxHeaderBytes int
|
KeepAliveCount int
|
||||||
EnableFullDuplex bool
|
MaxHeaderBytes int
|
||||||
Protocols []string
|
EnableFullDuplex bool
|
||||||
StrictSNIHost *bool
|
Protocols []string
|
||||||
TrustedProxiesRaw json.RawMessage
|
StrictSNIHost *bool
|
||||||
TrustedProxiesStrict int
|
TrustedProxiesRaw json.RawMessage
|
||||||
TrustedProxiesUnix bool
|
TrustedProxiesStrict int
|
||||||
ClientIPHeaders []string
|
TrustedProxiesUnix bool
|
||||||
ShouldLogCredentials bool
|
ClientIPHeaders []string
|
||||||
Metrics *caddyhttp.Metrics
|
ShouldLogCredentials bool
|
||||||
Trace bool // TODO: EXPERIMENTAL
|
Metrics *caddyhttp.Metrics
|
||||||
|
Trace bool // TODO: EXPERIMENTAL
|
||||||
}
|
}
|
||||||
|
|
||||||
func unmarshalCaddyfileServerOptions(d *caddyfile.Dispenser) (any, error) {
|
func unmarshalCaddyfileServerOptions(d *caddyfile.Dispenser) (any, error) {
|
||||||
|
|
@ -99,6 +100,26 @@ func unmarshalCaddyfileServerOptions(d *caddyfile.Dispenser) (any, error) {
|
||||||
serverOpts.ListenerWrappersRaw = append(serverOpts.ListenerWrappersRaw, jsonListenerWrapper)
|
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":
|
case "timeouts":
|
||||||
for nesting := d.Nesting(); d.NextBlock(nesting); {
|
for nesting := d.Nesting(); d.NextBlock(nesting); {
|
||||||
switch d.Val() {
|
switch d.Val() {
|
||||||
|
|
@ -335,6 +356,7 @@ func applyServerOptions(
|
||||||
|
|
||||||
// set all the options
|
// set all the options
|
||||||
server.ListenerWrappersRaw = opts.ListenerWrappersRaw
|
server.ListenerWrappersRaw = opts.ListenerWrappersRaw
|
||||||
|
server.PacketConnWrappersRaw = opts.PacketConnWrappersRaw
|
||||||
server.ReadTimeout = opts.ReadTimeout
|
server.ReadTimeout = opts.ReadTimeout
|
||||||
server.ReadHeaderTimeout = opts.ReadHeaderTimeout
|
server.ReadHeaderTimeout = opts.ReadHeaderTimeout
|
||||||
server.WriteTimeout = opts.WriteTimeout
|
server.WriteTimeout = opts.WriteTimeout
|
||||||
|
|
|
||||||
38
go.mod
38
go.mod
|
|
@ -21,7 +21,7 @@ require (
|
||||||
github.com/mholt/acmez/v3 v3.1.4
|
github.com/mholt/acmez/v3 v3.1.4
|
||||||
github.com/prometheus/client_golang v1.23.2
|
github.com/prometheus/client_golang v1.23.2
|
||||||
github.com/quic-go/quic-go v0.57.1
|
github.com/quic-go/quic-go v0.57.1
|
||||||
github.com/smallstep/certificates v0.28.4
|
github.com/smallstep/certificates v0.29.0
|
||||||
github.com/smallstep/nosql v0.7.0
|
github.com/smallstep/nosql v0.7.0
|
||||||
github.com/smallstep/truststore v0.13.0
|
github.com/smallstep/truststore v0.13.0
|
||||||
github.com/spf13/cobra v1.10.1
|
github.com/spf13/cobra v1.10.1
|
||||||
|
|
@ -35,6 +35,7 @@ require (
|
||||||
go.opentelemetry.io/contrib/propagators/autoprop v0.63.0
|
go.opentelemetry.io/contrib/propagators/autoprop v0.63.0
|
||||||
go.opentelemetry.io/otel v1.38.0
|
go.opentelemetry.io/otel v1.38.0
|
||||||
go.opentelemetry.io/otel/sdk 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/automaxprocs v1.6.0
|
||||||
go.uber.org/zap v1.27.1
|
go.uber.org/zap v1.27.1
|
||||||
go.uber.org/zap/exp v0.3.0
|
go.uber.org/zap/exp v0.3.0
|
||||||
|
|
@ -55,18 +56,18 @@ require (
|
||||||
dario.cat/mergo v1.0.1 // indirect
|
dario.cat/mergo v1.0.1 // indirect
|
||||||
github.com/Microsoft/go-winio v0.6.0 // indirect
|
github.com/Microsoft/go-winio v0.6.0 // indirect
|
||||||
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
|
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
|
||||||
github.com/ccoveille/go-safecast v1.6.1 // indirect
|
github.com/ccoveille/go-safecast/v2 v2.0.0 // indirect
|
||||||
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
|
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
|
||||||
github.com/coreos/go-oidc/v3 v3.14.1 // indirect
|
github.com/coreos/go-oidc/v3 v3.17.0 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/fxamacker/cbor/v2 v2.8.0 // indirect
|
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
|
||||||
github.com/go-jose/go-jose/v3 v3.0.4 // indirect
|
github.com/go-jose/go-jose/v3 v3.0.4 // indirect
|
||||||
github.com/go-jose/go-jose/v4 v4.1.2 // indirect
|
github.com/go-jose/go-jose/v4 v4.1.3 // indirect
|
||||||
github.com/google/certificate-transparency-go v1.1.8-0.20240110162603-74a5dd331745 // indirect
|
github.com/google/certificate-transparency-go v1.1.8-0.20240110162603-74a5dd331745 // indirect
|
||||||
github.com/google/go-tpm v0.9.6 // indirect
|
github.com/google/go-tpm v0.9.7 // indirect
|
||||||
github.com/google/go-tspi v0.3.0 // indirect
|
github.com/google/go-tspi v0.3.0 // indirect
|
||||||
github.com/google/s2a-go v0.1.9 // indirect
|
github.com/google/s2a-go v0.1.9 // indirect
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
|
github.com/googleapis/enterprise-certificate-proxy v0.3.7 // indirect
|
||||||
github.com/googleapis/gax-go/v2 v2.15.0 // indirect
|
github.com/googleapis/gax-go/v2 v2.15.0 // indirect
|
||||||
github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc // indirect
|
github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc // indirect
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
|
||||||
|
|
@ -78,14 +79,14 @@ require (
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/prometheus/otlptranslator v0.0.2 // indirect
|
github.com/prometheus/otlptranslator v0.0.2 // indirect
|
||||||
github.com/quic-go/qpack v0.6.0 // indirect
|
github.com/quic-go/qpack v0.6.0 // indirect
|
||||||
github.com/smallstep/cli-utils v0.12.1 // indirect
|
github.com/smallstep/cli-utils v0.12.2 // indirect
|
||||||
github.com/smallstep/go-attestation v0.4.4-0.20241119153605-2306d5b464ca // indirect
|
github.com/smallstep/go-attestation v0.4.4-0.20241119153605-2306d5b464ca // indirect
|
||||||
github.com/smallstep/linkedca v0.23.0 // indirect
|
github.com/smallstep/linkedca v0.25.0 // indirect
|
||||||
github.com/smallstep/pkcs7 v0.2.1 // indirect
|
github.com/smallstep/pkcs7 v0.2.1 // indirect
|
||||||
github.com/smallstep/scep v0.0.0-20240926084937-8cf1ca453101 // indirect
|
github.com/smallstep/scep v0.0.0-20250318231241-a25cabb69492 // indirect
|
||||||
github.com/x448/float16 v0.8.4 // indirect
|
github.com/x448/float16 v0.8.4 // indirect
|
||||||
github.com/zeebo/blake3 v0.2.4 // indirect
|
github.com/zeebo/blake3 v0.2.4 // indirect
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||||
go.opentelemetry.io/contrib/bridges/prometheus v0.63.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/aws v1.38.0 // indirect
|
||||||
go.opentelemetry.io/contrib/propagators/b3 v1.38.0 // indirect
|
go.opentelemetry.io/contrib/propagators/b3 v1.38.0 // indirect
|
||||||
|
|
@ -106,10 +107,10 @@ require (
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect
|
go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect
|
||||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||||
golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 // indirect
|
golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 // indirect
|
||||||
golang.org/x/oauth2 v0.32.0 // indirect
|
golang.org/x/oauth2 v0.33.0 // indirect
|
||||||
google.golang.org/api v0.254.0 // indirect
|
google.golang.org/api v0.256.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect
|
google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101 // indirect
|
||||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 // indirect
|
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -117,7 +118,7 @@ require (
|
||||||
filippo.io/edwards25519 v1.1.0 // indirect
|
filippo.io/edwards25519 v1.1.0 // indirect
|
||||||
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 // indirect
|
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 // indirect
|
||||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||||
github.com/Masterminds/semver/v3 v3.3.0 // indirect
|
github.com/Masterminds/semver/v3 v3.3.1 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/cespare/xxhash v1.1.0 // indirect
|
github.com/cespare/xxhash v1.1.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0
|
github.com/cespare/xxhash/v2 v2.3.0
|
||||||
|
|
@ -140,7 +141,7 @@ require (
|
||||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||||
github.com/libdns/libdns v1.1.1
|
github.com/libdns/libdns v1.1.1
|
||||||
github.com/manifoldco/promptui v0.9.0 // indirect
|
github.com/manifoldco/promptui v0.9.0 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
||||||
github.com/miekg/dns v1.1.68 // indirect
|
github.com/miekg/dns v1.1.68 // indirect
|
||||||
|
|
@ -166,13 +167,12 @@ require (
|
||||||
go.opentelemetry.io/otel/metric v1.38.0 // indirect
|
go.opentelemetry.io/otel/metric v1.38.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.38.0
|
go.opentelemetry.io/otel/trace v1.38.0
|
||||||
go.opentelemetry.io/proto/otlp v1.7.1 // indirect
|
go.opentelemetry.io/proto/otlp v1.7.1 // indirect
|
||||||
go.step.sm/crypto v0.74.0
|
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
golang.org/x/mod v0.29.0 // indirect
|
golang.org/x/mod v0.29.0 // indirect
|
||||||
golang.org/x/sys v0.38.0
|
golang.org/x/sys v0.38.0
|
||||||
golang.org/x/text v0.31.0 // indirect
|
golang.org/x/text v0.31.0 // indirect
|
||||||
golang.org/x/tools v0.38.0 // indirect
|
golang.org/x/tools v0.38.0 // indirect
|
||||||
google.golang.org/grpc v1.76.0 // indirect
|
google.golang.org/grpc v1.77.0 // indirect
|
||||||
google.golang.org/protobuf v1.36.10 // indirect
|
google.golang.org/protobuf v1.36.10 // indirect
|
||||||
howett.net/plist v1.0.0 // indirect
|
howett.net/plist v1.0.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
|
||||||
92
go.sum
92
go.sum
|
|
@ -1,7 +1,7 @@
|
||||||
cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY=
|
cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY=
|
||||||
cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
|
cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
|
||||||
cloud.google.com/go v0.120.0 h1:wc6bgG9DHyKqF5/vQvX1CiZrtHnxJjBlKUyF9nP6meA=
|
cloud.google.com/go v0.121.6 h1:waZiuajrI28iAf40cWgycWNgaXPO06dupuS+sgibK6c=
|
||||||
cloud.google.com/go v0.120.0/go.mod h1:/beW32s8/pGRuj4IILWQNd4uuebeT4dkOhKmkfit64Q=
|
cloud.google.com/go v0.121.6/go.mod h1:coChdst4Ea5vUpiALcYKXEpR1S9ZgXbhEzzMcMR66vI=
|
||||||
cloud.google.com/go/auth v0.17.0 h1:74yCm7hCj2rUyyAocqnFzsAYXgJhrG26XCFimrc/Kz4=
|
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 v0.17.0/go.mod h1:6wv/t5/6rOPAX4fJiRjKkJCvswLwdet7G8+UGXt7nCQ=
|
||||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
|
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/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 h1:4IYDQL5hG4L+HzJBhzejUySoUOheh3Lk5YT4PCyyW6k=
|
||||||
cloud.google.com/go/kms v1.23.2/go.mod h1:rZ5kK0I7Kn9W4erhYVoIRPtpizjunlrfU4fUkumUp8g=
|
cloud.google.com/go/kms v1.23.2/go.mod h1:rZ5kK0I7Kn9W4erhYVoIRPtpizjunlrfU4fUkumUp8g=
|
||||||
cloud.google.com/go/longrunning v0.6.7 h1:IGtfDWHhQCgCjwQjV9iiLnUta9LBCo8R9QmAFsS/PrE=
|
cloud.google.com/go/longrunning v0.7.0 h1:FV0+SYF1RIj59gyoWDRi45GiYUMM3K1qO51qoboQT1E=
|
||||||
cloud.google.com/go/longrunning v0.6.7/go.mod h1:EAFV3IZAKmM56TyiE6VAP3VoTzhZzySwI/YI1s/nRsY=
|
cloud.google.com/go/longrunning v0.7.0/go.mod h1:ySn2yXmjbK9Ba0zsQqunhDkYi0+9rlXIwnoAf+h+TPY=
|
||||||
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
|
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
|
||||||
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
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/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 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||||
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||||
github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0=
|
github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4=
|
||||||
github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
||||||
github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs=
|
github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs=
|
||||||
github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=
|
github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=
|
||||||
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
|
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/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 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+YTAyA=
|
||||||
github.com/caddyserver/zerossl v0.1.3/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4=
|
github.com/caddyserver/zerossl v0.1.3/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4=
|
||||||
github.com/ccoveille/go-safecast v1.6.1 h1:Nb9WMDR8PqhnKCVs2sCB+OqhohwO5qaXtCviZkIff5Q=
|
github.com/ccoveille/go-safecast/v2 v2.0.0 h1:+5eyITXAUj3wMjad6cRVJKGnC7vDS55zk0INzJagub0=
|
||||||
github.com/ccoveille/go-safecast v1.6.1/go.mod h1:QqwNjxQ7DAqY0C721OIO9InMk9zCwcsO7tnRuHytad8=
|
github.com/ccoveille/go-safecast/v2 v2.0.0/go.mod h1:JIYA4CAR33blIDuE6fSwCp2sz1oOBahXnvmdBhOAABs=
|
||||||
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
|
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/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
|
||||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
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/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/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-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||||
github.com/coreos/go-oidc/v3 v3.14.1 h1:9ePWwfdwC4QKRlCXsJGou56adA/owXczOzwKdOumLqk=
|
github.com/coreos/go-oidc/v3 v3.17.0 h1:hWBGaQfbi0iVviX4ibC7bk8OKT5qNr4klBaCHVNvehc=
|
||||||
github.com/coreos/go-oidc/v3 v3.14.1/go.mod h1:HaZ3szPaZ0e4r6ebqvsLWlk2Tn+aejfmrfah6hnSYEU=
|
github.com/coreos/go-oidc/v3 v3.17.0/go.mod h1:wqPbKFrVnE90vty060SB40FCJ8fTHTxSwyXJqZH+sI8=
|
||||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
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 v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
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 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
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/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU=
|
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
|
||||||
github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
github.com/fxamacker/cbor/v2 v2.9.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 h1:WQIt9uxdsAbgIYgid+BpYc+liqQZGMHRaUwp0JUcvdE=
|
||||||
github.com/go-chi/chi/v5 v5.2.3/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
|
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 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/v3 v3.0.4/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
|
||||||
github.com/go-jose/go-jose/v4 v4.1.2 h1:TK/7NqRQZfgAh+Td8AlsrvtPoUyiHh0LqVvokh+1vHI=
|
github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=
|
||||||
github.com/go-jose/go-jose/v4 v4.1.2/go.mod h1:22cg9HWM1pOlnRiY+9cQYJ9XHmya1bYW8OeDM6Ku6Oo=
|
github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
|
||||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
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 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
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.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 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
github.com/google/go-tpm v0.9.6 h1:Ku42PT4LmjDu1H5C5ISWLlpI1mj+Zq7sPGKoRw2XROA=
|
github.com/google/go-tpm v0.9.7 h1:u89J4tUUeDTlH8xxC3CTW7OHZjbjKoHdQ9W7gCUhtxA=
|
||||||
github.com/google/go-tpm v0.9.6/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
|
github.com/google/go-tpm v0.9.7/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 h1:hwIwPG7w4z5eQEBq11gYw8YYr9xXLfBQ/0JsKyq5AJM=
|
||||||
github.com/google/go-tpm-tools v0.4.6/go.mod h1:MsVQbJnRhKDfWwf5zgr3cDGpj13P1uLAFF0wMEP/n5w=
|
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=
|
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/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 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU9uHLo7OnF5tL52HFAgMmyrf4=
|
github.com/googleapis/enterprise-certificate-proxy v0.3.7 h1:zrn2Ee/nWmHulBx5sAVrGgAa0f2/R35S4DJwfFaUPFQ=
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.3.6/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA=
|
github.com/googleapis/enterprise-certificate-proxy v0.3.7/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 h1:SyjDc1mGgZU5LncH8gimWo9lW1DtIfPibOG81vgd/bo=
|
||||||
github.com/googleapis/gax-go/v2 v2.15.0/go.mod h1:zVVkkxAQHa1RQpg9z2AUCMnKhi0Qld9rcmyfL1OZhoc=
|
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=
|
github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc h1:GN2Lv3MGO7AS6PrRoT6yV5+wkrOpcszoIsO4+4ds248=
|
||||||
|
|
@ -227,9 +227,8 @@ 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/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 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA=
|
||||||
github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg=
|
github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg=
|
||||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||||
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 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
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=
|
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
|
||||||
|
|
@ -276,8 +275,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/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 h1:25KAAR9QR8KZrCZRThWMKVAwGoiHIrNbT72ULHTuI10=
|
||||||
github.com/quic-go/quic-go v0.57.1/go.mod h1:ly4QBAjHA2VhdnxhojRsCUOeJwKYg+taDlos92xb1+s=
|
github.com/quic-go/quic-go v0.57.1/go.mod h1:ly4QBAjHA2VhdnxhojRsCUOeJwKYg+taDlos92xb1+s=
|
||||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||||
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
|
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
|
||||||
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
|
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=
|
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||||
|
|
@ -296,21 +295,20 @@ github.com/slackhq/nebula v1.9.7 h1:v5u46efIyYHGdfjFnozQbRRhMdaB9Ma1SSTcUcE2lfE=
|
||||||
github.com/slackhq/nebula v1.9.7/go.mod h1:1+4q4wd3dDAjO8rKCttSb9JIVbklQhuJiBp5I0lbIsQ=
|
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 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/assert v0.0.0-20200723003110-82e2b9b3b262/go.mod h1:MyOHs9Po2fbM1LHej6sBUT8ozbxmMOFG+E+rx/GSGuc=
|
||||||
github.com/smallstep/certificates v0.28.4 h1:JTU6/A5Xes6m+OsR6fw1RACSA362vJc9SOFVG7poBEw=
|
github.com/smallstep/certificates v0.29.0 h1:f90szTKYTW62bmCc+qE5doGqIGPVxTQb8Ba37e/K8Zs=
|
||||||
github.com/smallstep/certificates v0.28.4/go.mod h1:LUqo+7mKZE7FZldlTb0zhU4A0bq4G4+akieFMcTaWvA=
|
github.com/smallstep/certificates v0.29.0/go.mod h1:27WI0od6gu84mvE4mYQ/QZGyYwHXvhsiSRNC+y3t+mo=
|
||||||
github.com/smallstep/cli-utils v0.12.1 h1:D9QvfbFqiKq3snGZ2xDcXEFrdFJ1mQfPHZMq/leerpE=
|
github.com/smallstep/cli-utils v0.12.2 h1:lGzM9PJrH/qawbzMC/s2SvgLdJPKDWKwKzx9doCVO+k=
|
||||||
github.com/smallstep/cli-utils v0.12.1/go.mod h1:skV2Neg8qjiKPu2fphM89H9bIxNpKiiRTnX9Q6Lc+20=
|
github.com/smallstep/cli-utils v0.12.2/go.mod h1:uCPqefO29goHLGqFnwk0i8W7XJu18X3WHQFRtOm/00Y=
|
||||||
github.com/smallstep/go-attestation v0.4.4-0.20241119153605-2306d5b464ca h1:VX8L0r8vybH0bPeaIxh4NQzafKQiqvlOn8pmOXbFLO4=
|
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/go-attestation v0.4.4-0.20241119153605-2306d5b464ca/go.mod h1:vNAduivU014fubg6ewygkAvQC0IQVXqdc8vaGl/0er4=
|
||||||
github.com/smallstep/linkedca v0.23.0 h1:5W/7EudlK1HcCIdZM68dJlZ7orqCCCyv6bm2l/0JmLU=
|
github.com/smallstep/linkedca v0.25.0 h1:txT9QHGbCsJq0MhAghBq7qhurGY727tQuqUi+n4BVBo=
|
||||||
github.com/smallstep/linkedca v0.23.0/go.mod h1:7cyRM9soAYySg9ag65QwytcgGOM+4gOlkJ/YA58A9E8=
|
github.com/smallstep/linkedca v0.25.0/go.mod h1:Q3jVAauFKNlF86W5/RFtgQeyDKz98GL/KN3KG4mJOvc=
|
||||||
github.com/smallstep/nosql v0.7.0 h1:YiWC9ZAHcrLCrayfaF+QJUv16I2bZ7KdLC3RpJcnAnE=
|
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/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 h1:6Kfzr/QizdIuB6LSv8y1LJdZ3aPSfTNhTLqAx9CTLfA=
|
||||||
github.com/smallstep/pkcs7 v0.2.1/go.mod h1:RcXHsMfL+BzH8tRhmrF1NkkpebKpq3JEM66cOFxanf0=
|
github.com/smallstep/pkcs7 v0.2.1/go.mod h1:RcXHsMfL+BzH8tRhmrF1NkkpebKpq3JEM66cOFxanf0=
|
||||||
github.com/smallstep/scep v0.0.0-20240926084937-8cf1ca453101 h1:LyZqn24/ZiVg8v9Hq07K6mx6RqPtpDeK+De5vf4QEY4=
|
github.com/smallstep/scep v0.0.0-20250318231241-a25cabb69492 h1:k23+s51sgYix4Zgbvpmy+1ZgXLjr4ZTkBTqXmpnImwA=
|
||||||
github.com/smallstep/scep v0.0.0-20240926084937-8cf1ca453101/go.mod h1:EuKQjYGQwhUa1mgD21zxIgOgUYLsqikJmvxNscxpS/Y=
|
github.com/smallstep/scep v0.0.0-20250318231241-a25cabb69492/go.mod h1:QQhwLqCS13nhv8L5ov7NgusowENUtXdEzdytjmJHdZQ=
|
||||||
github.com/smallstep/truststore v0.13.0 h1:90if9htAOblavbMeWlqNLnO9bsjjgVv2hQeQJCi/py4=
|
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/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=
|
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
|
|
@ -368,8 +366,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=
|
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 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0=
|
||||||
go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ=
|
go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ=
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||||
go.opentelemetry.io/contrib/bridges/prometheus v0.63.0 h1:/Rij/t18Y7rUayNg7Id6rPrEnHgorxYabm2E6wUdPP4=
|
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/bridges/prometheus v0.63.0/go.mod h1:AdyDPn6pkbkt2w01n3BubRVk7xAsCRq1Yg1mpfyA/0E=
|
||||||
go.opentelemetry.io/contrib/exporters/autoexport v0.63.0 h1:NLnZybb9KkfMXPwZhd5diBYJoVxiO9Qa06dacEA7ySY=
|
go.opentelemetry.io/contrib/exporters/autoexport v0.63.0 h1:NLnZybb9KkfMXPwZhd5diBYJoVxiO9Qa06dacEA7ySY=
|
||||||
|
|
@ -450,7 +448,6 @@ 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.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.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.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.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
|
||||||
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
|
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
|
||||||
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
|
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
|
||||||
|
|
@ -475,15 +472,14 @@ 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.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||||
golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=
|
golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
|
||||||
golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
golang.org/x/oauth2 v0.33.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-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.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.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.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.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sync v0.7.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.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 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
|
||||||
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||||
|
|
@ -498,14 +494,12 @@ 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-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-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-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.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.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.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.12.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.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.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.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 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
|
||||||
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
|
|
@ -517,7 +511,6 @@ 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.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
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.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.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 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
|
||||||
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
|
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
|
||||||
|
|
@ -529,7 +522,6 @@ 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.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.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/text v0.15.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.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||||
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
|
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
|
||||||
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
|
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
|
||||||
|
|
@ -546,16 +538,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=
|
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 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||||
google.golang.org/api v0.254.0 h1:jl3XrGj7lRjnlUvZAbAdhINTLbsg5dbjmR90+pTQvt4=
|
google.golang.org/api v0.256.0 h1:u6Khm8+F9sxbCTYNoBHg6/Hwv0N/i+V94MvkOSor6oI=
|
||||||
google.golang.org/api v0.254.0/go.mod h1:5BkSURm3D9kAqjGvBNgf0EcbX6Rnrf6UArKkwBzAyqQ=
|
google.golang.org/api v0.256.0/go.mod h1:KIgPhksXADEKJlnEoRa9qAII4rXcy40vfI8HRqcU964=
|
||||||
google.golang.org/genproto v0.0.0-20250603155806-513f23925822 h1:rHWScKit0gvAPuOnu87KpaYtjK5zBMLcULh7gxkCXu4=
|
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 v0.0.0-20250603155806-513f23925822/go.mod h1:HubltRL7rMh0LfnQPkMH4NPDFEWp0jw3vixw7jEM53s=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 h1:BIRfGDEjiHRrk0QKZe3Xv2ieMhtgRGeLcZQ0mIVn4EY=
|
google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 h1:mepRgnBZa07I4TRuomDE4sTIYieg/osKmzIf4USdWS4=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5/go.mod h1:j3QtIyytwqGr1JUDtYXwtMXWPKsEa5LtzIFN1Wn5WvE=
|
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-20251022142026-3a174f9686a8 h1:M1rk8KBnUsBDg1oPGHNCxG4vc1f49epmTO7xscSajMk=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101 h1:tRPGkdGHuewF4UisLzzHHr1spKw92qLM98nIzxbC0wY=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
|
||||||
google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A=
|
google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM=
|
||||||
google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c=
|
google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig=
|
||||||
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 h1:F29+wU6Ee6qgu9TddPgooOdaqsxTMunOoj8KA5yuS5A=
|
||||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1/go.mod h1:5KF+wpkbTSbGcR9zteSqZV6fqFOWBl4Yde8En8MryZA=
|
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=
|
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
|
||||||
|
|
|
||||||
34
listeners.go
34
listeners.go
|
|
@ -511,7 +511,7 @@ func JoinNetworkAddress(network, host, port string) string {
|
||||||
//
|
//
|
||||||
// NOTE: This API is EXPERIMENTAL and may be changed or removed.
|
// 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.
|
// 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) (http3.QUICListener, error) {
|
func (na NetworkAddress) ListenQUIC(ctx context.Context, portOffset uint, config net.ListenConfig, tlsConf *tls.Config, pcWrappers []PacketConnWrapper) (http3.QUICListener, error) {
|
||||||
lnKey := listenerKey("quic"+na.Network, na.JoinHostPort(portOffset))
|
lnKey := listenerKey("quic"+na.Network, na.JoinHostPort(portOffset))
|
||||||
|
|
||||||
sharedEarlyListener, _, err := listenerPool.LoadOrNew(lnKey, func() (Destructor, error) {
|
sharedEarlyListener, _, err := listenerPool.LoadOrNew(lnKey, func() (Destructor, error) {
|
||||||
|
|
@ -523,12 +523,19 @@ func (na NetworkAddress) ListenQUIC(ctx context.Context, portOffset uint, config
|
||||||
ln := lnAny.(net.PacketConn)
|
ln := lnAny.(net.PacketConn)
|
||||||
|
|
||||||
h3ln := ln
|
h3ln := ln
|
||||||
for {
|
if len(pcWrappers) == 0 {
|
||||||
// retrieve the underlying socket, so quic-go can optimize.
|
for {
|
||||||
if unwrapper, ok := h3ln.(interface{ Unwrap() net.PacketConn }); ok {
|
// retrieve the underlying socket, so quic-go can optimize.
|
||||||
h3ln = unwrapper.Unwrap()
|
if unwrapper, ok := h3ln.(interface{ Unwrap() net.PacketConn }); ok {
|
||||||
} else {
|
h3ln = unwrapper.Unwrap()
|
||||||
break
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// wrap packet conn before QUIC
|
||||||
|
for _, pcWrapper := range pcWrappers {
|
||||||
|
h3ln = pcWrapper.WrapPacketConn(h3ln)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -775,6 +782,19 @@ type ListenerWrapper interface {
|
||||||
WrapListener(net.Listener) net.Listener
|
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.
|
// listenerPool stores and allows reuse of active listeners.
|
||||||
var listenerPool = NewUsagePool()
|
var listenerPool = NewUsagePool()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,7 @@ func init() {
|
||||||
// `{http.request.tls.proto}` | The negotiated next protocol
|
// `{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.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.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.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}` | The public key of the client certificate.
|
||||||
// `{http.request.tls.client.public_key_sha256}` | The SHA256 checksum of the client's public key.
|
// `{http.request.tls.client.public_key_sha256}` | The SHA256 checksum of the client's public key.
|
||||||
|
|
@ -346,6 +347,20 @@ func (app *App) Provision(ctx caddy.Context) error {
|
||||||
srv.listenerWrappers = append([]caddy.ListenerWrapper{new(tlsPlaceholderWrapper)}, srv.listenerWrappers...)
|
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
|
// pre-compile the primary handler chain, and be sure to wrap it in our
|
||||||
// route handler so that important security checks are done, etc.
|
// route handler so that important security checks are done, etc.
|
||||||
primaryRoute := emptyHandler
|
primaryRoute := emptyHandler
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,7 @@ func (t LoggableTLSConnState) MarshalLogObject(enc zapcore.ObjectEncoder) error
|
||||||
enc.AddUint16("cipher_suite", t.CipherSuite)
|
enc.AddUint16("cipher_suite", t.CipherSuite)
|
||||||
enc.AddString("proto", t.NegotiatedProtocol)
|
enc.AddString("proto", t.NegotiatedProtocol)
|
||||||
enc.AddString("server_name", t.ServerName)
|
enc.AddString("server_name", t.ServerName)
|
||||||
|
enc.AddBool("ech", t.ECHAccepted)
|
||||||
if len(t.PeerCertificates) > 0 {
|
if len(t.PeerCertificates) > 0 {
|
||||||
enc.AddString("client_common_name", t.PeerCertificates[0].Subject.CommonName)
|
enc.AddString("client_common_name", t.PeerCertificates[0].Subject.CommonName)
|
||||||
enc.AddString("client_serial", t.PeerCertificates[0].SerialNumber.String())
|
enc.AddString("client_serial", t.PeerCertificates[0].SerialNumber.String())
|
||||||
|
|
|
||||||
|
|
@ -511,6 +511,8 @@ func getReqTLSReplacement(req *http.Request, key string) (any, bool) {
|
||||||
return true, true
|
return true, true
|
||||||
case "server_name":
|
case "server_name":
|
||||||
return req.TLS.ServerName, true
|
return req.TLS.ServerName, true
|
||||||
|
case "ech":
|
||||||
|
return req.TLS.ECHAccepted, true
|
||||||
}
|
}
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,10 @@ type Server struct {
|
||||||
// of the base listener. They are applied in the given order.
|
// 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"`
|
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
|
// How long to allow a read from a client's upload. Setting this
|
||||||
// to a short, non-zero value can mitigate slowloris attacks, but
|
// to a short, non-zero value can mitigate slowloris attacks, but
|
||||||
// may also affect legitimately slow clients.
|
// may also affect legitimately slow clients.
|
||||||
|
|
@ -258,7 +262,8 @@ type Server struct {
|
||||||
primaryHandlerChain Handler
|
primaryHandlerChain Handler
|
||||||
errorHandlerChain Handler
|
errorHandlerChain Handler
|
||||||
listenerWrappers []caddy.ListenerWrapper
|
listenerWrappers []caddy.ListenerWrapper
|
||||||
listeners []net.Listener // stdlib http.Server will close these
|
packetConnWrappers []caddy.PacketConnWrapper
|
||||||
|
listeners []net.Listener
|
||||||
quicListeners []http3.QUICListener // http3 now leave the quic.Listener management to us
|
quicListeners []http3.QUICListener // http3 now leave the quic.Listener management to us
|
||||||
|
|
||||||
tlsApp *caddytls.TLS
|
tlsApp *caddytls.TLS
|
||||||
|
|
@ -625,7 +630,7 @@ func (s *Server) serveHTTP3(addr caddy.NetworkAddress, tlsCfg *tls.Config) error
|
||||||
return fmt.Errorf("starting HTTP/3 QUIC listener: %v", err)
|
return fmt.Errorf("starting HTTP/3 QUIC listener: %v", err)
|
||||||
}
|
}
|
||||||
addr.Network = h3net
|
addr.Network = h3net
|
||||||
h3ln, err := addr.ListenQUIC(s.ctx, 0, net.ListenConfig{}, tlsCfg)
|
h3ln, err := addr.ListenQUIC(s.ctx, 0, net.ListenConfig{}, tlsCfg, s.packetConnWrappers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("starting HTTP/3 QUIC listener: %v", err)
|
return fmt.Errorf("starting HTTP/3 QUIC listener: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -763,9 +768,11 @@ func (s *Server) shouldLogRequest(r *http.Request) bool {
|
||||||
hostWithoutPort = r.Host
|
hostWithoutPort = r.Host
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := s.Logs.LoggerNames[hostWithoutPort]; ok {
|
for loggerName := range s.Logs.LoggerNames {
|
||||||
// this host is mapped to a particular logger name
|
if certmagic.MatchWildcard(hostWithoutPort, loggerName) {
|
||||||
return true
|
// this host is mapped to a particular logger name
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for _, dh := range s.Logs.SkipHosts {
|
for _, dh := range s.Logs.SkipHosts {
|
||||||
// logging for this particular host is disabled
|
// logging for this particular host is disabled
|
||||||
|
|
|
||||||
|
|
@ -306,6 +306,13 @@ func init() {
|
||||||
// find the documentation on time layouts [in Go's docs](https://pkg.go.dev/time#pkg-constants).
|
// 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`.
|
// 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`
|
// ##### `pathEscape`
|
||||||
//
|
//
|
||||||
// Passes a string through `url.PathEscape`, replacing characters that have
|
// Passes a string through `url.PathEscape`, replacing characters that have
|
||||||
|
|
@ -318,11 +325,22 @@ func init() {
|
||||||
// {{pathEscape "50%_valid_filename?.jpg"}}
|
// {{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.
|
||||||
|
//
|
||||||
// ```
|
// ```
|
||||||
// {{humanize "size" "2048000"}}
|
// {{ maybe "myOptionalFunc" "arg1" 2 }}
|
||||||
// {{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 {
|
type Templates struct {
|
||||||
// The root path from which to load files. Required if template functions
|
// The root path from which to load files. Required if template functions
|
||||||
|
|
|
||||||
|
|
@ -222,11 +222,16 @@ func rootAndIntermediatePEM(ca *CA) (root, inter []byte, err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return root, inter, err
|
return root, inter, err
|
||||||
}
|
}
|
||||||
inter, err = pemEncodeCert(ca.IntermediateCertificate().Raw)
|
|
||||||
if err != nil {
|
for _, interCert := range ca.IntermediateCertificateChain() {
|
||||||
return root, inter, err
|
pemBytes, err := pemEncodeCert(interCert.Raw)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
inter = append(inter, pemBytes...)
|
||||||
}
|
}
|
||||||
return root, inter, err
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// caInfo is the response structure for the CA info API endpoint.
|
// caInfo is the response structure for the CA info API endpoint.
|
||||||
|
|
|
||||||
|
|
@ -75,10 +75,11 @@ type CA struct {
|
||||||
// and module provisioning.
|
// and module provisioning.
|
||||||
ID string `json:"-"`
|
ID string `json:"-"`
|
||||||
|
|
||||||
storage certmagic.Storage
|
storage certmagic.Storage
|
||||||
root, inter *x509.Certificate
|
root *x509.Certificate
|
||||||
interKey any // TODO: should we just store these as crypto.Signer?
|
interChain []*x509.Certificate
|
||||||
mu *sync.RWMutex
|
interKey crypto.Signer
|
||||||
|
mu *sync.RWMutex
|
||||||
|
|
||||||
rootCertPath string // mainly used for logging purposes if trusting
|
rootCertPath string // mainly used for logging purposes if trusting
|
||||||
log *zap.Logger
|
log *zap.Logger
|
||||||
|
|
@ -127,14 +128,16 @@ func (ca *CA) Provision(ctx caddy.Context, id string, log *zap.Logger) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// load the certs and key that will be used for signing
|
// load the certs and key that will be used for signing
|
||||||
var rootCert, interCert *x509.Certificate
|
var rootCert *x509.Certificate
|
||||||
|
var rootCertChain, interCertChain []*x509.Certificate
|
||||||
var rootKey, interKey crypto.Signer
|
var rootKey, interKey crypto.Signer
|
||||||
var err error
|
var err error
|
||||||
if ca.Root != nil {
|
if ca.Root != nil {
|
||||||
if ca.Root.Format == "" || ca.Root.Format == "pem_file" {
|
if ca.Root.Format == "" || ca.Root.Format == "pem_file" {
|
||||||
ca.rootCertPath = ca.Root.Certificate
|
ca.rootCertPath = ca.Root.Certificate
|
||||||
}
|
}
|
||||||
rootCert, rootKey, err = ca.Root.Load()
|
rootCertChain, rootKey, err = ca.Root.Load()
|
||||||
|
rootCert = rootCertChain[0]
|
||||||
} else {
|
} else {
|
||||||
ca.rootCertPath = "storage:" + ca.storageKeyRootCert()
|
ca.rootCertPath = "storage:" + ca.storageKeyRootCert()
|
||||||
rootCert, rootKey, err = ca.loadOrGenRoot()
|
rootCert, rootKey, err = ca.loadOrGenRoot()
|
||||||
|
|
@ -142,21 +145,23 @@ func (ca *CA) Provision(ctx caddy.Context, id string, log *zap.Logger) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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 {
|
if ca.Intermediate != nil {
|
||||||
interCert, interKey, err = ca.Intermediate.Load()
|
interCertChain, interKey, err = ca.Intermediate.Load()
|
||||||
} else {
|
} else {
|
||||||
interCert, interKey, err = ca.loadOrGenIntermediate(rootCert, rootKey)
|
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)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ca.mu.Lock()
|
ca.mu.Lock()
|
||||||
ca.root, ca.inter, ca.interKey = rootCert, interCert, interKey
|
ca.root, ca.interChain, ca.interKey = rootCert, interCertChain, interKey
|
||||||
ca.mu.Unlock()
|
ca.mu.Unlock()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -172,21 +177,21 @@ func (ca CA) RootCertificate() *x509.Certificate {
|
||||||
// RootKey returns the CA's root private key. Since the root key is
|
// 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,
|
// not cached in memory long-term, it needs to be loaded from storage,
|
||||||
// which could yield an error.
|
// which could yield an error.
|
||||||
func (ca CA) RootKey() (any, error) {
|
func (ca CA) RootKey() (crypto.Signer, error) {
|
||||||
_, rootKey, err := ca.loadOrGenRoot()
|
_, rootKey, err := ca.loadOrGenRoot()
|
||||||
return rootKey, err
|
return rootKey, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// IntermediateCertificate returns the CA's intermediate
|
// IntermediateCertificateChain returns the CA's intermediate
|
||||||
// certificate (public key).
|
// certificate chain.
|
||||||
func (ca CA) IntermediateCertificate() *x509.Certificate {
|
func (ca CA) IntermediateCertificateChain() []*x509.Certificate {
|
||||||
ca.mu.RLock()
|
ca.mu.RLock()
|
||||||
defer ca.mu.RUnlock()
|
defer ca.mu.RUnlock()
|
||||||
return ca.inter
|
return ca.interChain
|
||||||
}
|
}
|
||||||
|
|
||||||
// IntermediateKey returns the CA's intermediate private key.
|
// IntermediateKey returns the CA's intermediate private key.
|
||||||
func (ca CA) IntermediateKey() any {
|
func (ca CA) IntermediateKey() crypto.Signer {
|
||||||
ca.mu.RLock()
|
ca.mu.RLock()
|
||||||
defer ca.mu.RUnlock()
|
defer ca.mu.RUnlock()
|
||||||
return ca.interKey
|
return ca.interKey
|
||||||
|
|
@ -207,26 +212,27 @@ func (ca *CA) NewAuthority(authorityConfig AuthorityConfig) (*authority.Authorit
|
||||||
// cert/key directly, since it's unlikely to expire
|
// cert/key directly, since it's unlikely to expire
|
||||||
// while Caddy is running (long lifetime)
|
// while Caddy is running (long lifetime)
|
||||||
var issuerCert *x509.Certificate
|
var issuerCert *x509.Certificate
|
||||||
var issuerKey any
|
var issuerKey crypto.Signer
|
||||||
issuerCert = rootCert
|
issuerCert = rootCert
|
||||||
var err error
|
var err error
|
||||||
issuerKey, err = ca.RootKey()
|
issuerKey, err = ca.RootKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("loading signing key: %v", err)
|
return nil, fmt.Errorf("loading signing key: %v", err)
|
||||||
}
|
}
|
||||||
signerOption = authority.WithX509Signer(issuerCert, issuerKey.(crypto.Signer))
|
signerOption = authority.WithX509Signer(issuerCert, issuerKey)
|
||||||
} else {
|
} else {
|
||||||
// if we're signing with intermediate, we need to make
|
// if we're signing with intermediate, we need to make
|
||||||
// sure it's always fresh, because the intermediate may
|
// sure it's always fresh, because the intermediate may
|
||||||
// renew while Caddy is running (medium lifetime)
|
// renew while Caddy is running (medium lifetime)
|
||||||
signerOption = authority.WithX509SignerFunc(func() ([]*x509.Certificate, crypto.Signer, error) {
|
signerOption = authority.WithX509SignerFunc(func() ([]*x509.Certificate, crypto.Signer, error) {
|
||||||
issuerCert := ca.IntermediateCertificate()
|
issuerChain := ca.IntermediateCertificateChain()
|
||||||
issuerKey := ca.IntermediateKey().(crypto.Signer)
|
issuerCert := issuerChain[0]
|
||||||
|
issuerKey := ca.IntermediateKey()
|
||||||
ca.log.Debug("using intermediate signer",
|
ca.log.Debug("using intermediate signer",
|
||||||
zap.String("serial", issuerCert.SerialNumber.String()),
|
zap.String("serial", issuerCert.SerialNumber.String()),
|
||||||
zap.String("not_before", issuerCert.NotBefore.String()),
|
zap.String("not_before", issuerCert.NotBefore.String()),
|
||||||
zap.String("not_after", issuerCert.NotAfter.String()))
|
zap.String("not_after", issuerCert.NotAfter.String()))
|
||||||
return []*x509.Certificate{issuerCert}, issuerKey, nil
|
return issuerChain, issuerKey, nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -252,7 +258,11 @@ func (ca *CA) NewAuthority(authorityConfig AuthorityConfig) (*authority.Authorit
|
||||||
|
|
||||||
func (ca CA) loadOrGenRoot() (rootCert *x509.Certificate, rootKey crypto.Signer, err error) {
|
func (ca CA) loadOrGenRoot() (rootCert *x509.Certificate, rootKey crypto.Signer, err error) {
|
||||||
if ca.Root != nil {
|
if ca.Root != nil {
|
||||||
return ca.Root.Load()
|
rootChain, rootSigner, err := ca.Root.Load()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return rootChain[0], rootSigner, nil
|
||||||
}
|
}
|
||||||
rootCertPEM, err := ca.storage.Load(ca.ctx, ca.storageKeyRootCert())
|
rootCertPEM, err := ca.storage.Load(ca.ctx, ca.storageKeyRootCert())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -268,7 +278,7 @@ func (ca CA) loadOrGenRoot() (rootCert *x509.Certificate, rootKey crypto.Signer,
|
||||||
}
|
}
|
||||||
|
|
||||||
if rootCert == nil {
|
if rootCert == nil {
|
||||||
rootCert, err = pemDecodeSingleCert(rootCertPEM)
|
rootCert, err = pemDecodeCertificate(rootCertPEM)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("parsing root certificate PEM: %v", err)
|
return nil, nil, fmt.Errorf("parsing root certificate PEM: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -314,7 +324,8 @@ func (ca CA) genRoot() (rootCert *x509.Certificate, rootKey crypto.Signer, err e
|
||||||
return rootCert, rootKey, nil
|
return rootCert, rootKey, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ca CA) loadOrGenIntermediate(rootCert *x509.Certificate, rootKey crypto.Signer) (interCert *x509.Certificate, interKey crypto.Signer, err error) {
|
func (ca CA) loadOrGenIntermediate(rootCert *x509.Certificate, rootKey crypto.Signer) (interCertChain []*x509.Certificate, interKey crypto.Signer, err error) {
|
||||||
|
var interCert *x509.Certificate
|
||||||
interCertPEM, err := ca.storage.Load(ca.ctx, ca.storageKeyIntermediateCert())
|
interCertPEM, err := ca.storage.Load(ca.ctx, ca.storageKeyIntermediateCert())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(err, fs.ErrNotExist) {
|
if !errors.Is(err, fs.ErrNotExist) {
|
||||||
|
|
@ -326,10 +337,12 @@ func (ca CA) loadOrGenIntermediate(rootCert *x509.Certificate, rootKey crypto.Si
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("generating new intermediate cert: %v", err)
|
return nil, nil, fmt.Errorf("generating new intermediate cert: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interCertChain = append(interCertChain, interCert)
|
||||||
}
|
}
|
||||||
|
|
||||||
if interCert == nil {
|
if len(interCertChain) == 0 {
|
||||||
interCert, err = pemDecodeSingleCert(interCertPEM)
|
interCertChain, err = pemDecodeCertificateChain(interCertPEM)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("decoding intermediate certificate PEM: %v", err)
|
return nil, nil, fmt.Errorf("decoding intermediate certificate PEM: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -346,7 +359,7 @@ func (ca CA) loadOrGenIntermediate(rootCert *x509.Certificate, rootKey crypto.Si
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return interCert, interKey, nil
|
return interCertChain, interKey, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ca CA) genIntermediate(rootCert *x509.Certificate, rootKey crypto.Signer) (interCert *x509.Certificate, interKey crypto.Signer, err error) {
|
func (ca CA) genIntermediate(rootCert *x509.Certificate, rootKey crypto.Signer) (interCert *x509.Certificate, interKey crypto.Signer, err error) {
|
||||||
|
|
|
||||||
|
|
@ -17,15 +17,20 @@ package caddypki
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto"
|
"crypto"
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"crypto/ed25519"
|
||||||
|
"crypto/rsa"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/caddyserver/certmagic"
|
"github.com/caddyserver/certmagic"
|
||||||
|
"go.step.sm/crypto/pemutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
func pemDecodeSingleCert(pemDER []byte) (*x509.Certificate, error) {
|
func pemDecodeCertificate(pemDER []byte) (*x509.Certificate, error) {
|
||||||
pemBlock, remaining := pem.Decode(pemDER)
|
pemBlock, remaining := pem.Decode(pemDER)
|
||||||
if pemBlock == nil {
|
if pemBlock == nil {
|
||||||
return nil, fmt.Errorf("no PEM block found")
|
return nil, fmt.Errorf("no PEM block found")
|
||||||
|
|
@ -39,6 +44,15 @@ func pemDecodeSingleCert(pemDER []byte) (*x509.Certificate, error) {
|
||||||
return x509.ParseCertificate(pemBlock.Bytes)
|
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) {
|
func pemEncodeCert(der []byte) ([]byte, error) {
|
||||||
return pemEncode("CERTIFICATE", der)
|
return pemEncode("CERTIFICATE", der)
|
||||||
}
|
}
|
||||||
|
|
@ -70,15 +84,18 @@ type KeyPair struct {
|
||||||
Format string `json:"format,omitempty"`
|
Format string `json:"format,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load loads the certificate and key.
|
// Load loads the certificate chain and (optional) private key from
|
||||||
func (kp KeyPair) Load() (*x509.Certificate, crypto.Signer, error) {
|
// 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) {
|
||||||
switch kp.Format {
|
switch kp.Format {
|
||||||
case "", "pem_file":
|
case "", "pem_file":
|
||||||
certData, err := os.ReadFile(kp.Certificate)
|
certData, err := os.ReadFile(kp.Certificate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
cert, err := pemDecodeSingleCert(certData)
|
chain, err := pemDecodeCertificateChain(certData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -93,11 +110,49 @@ func (kp KeyPair) Load() (*x509.Certificate, crypto.Signer, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
if err := verifyKeysMatch(chain[0], key); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return cert, key, nil
|
return chain, key, nil
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, nil, fmt.Errorf("unsupported format: %s", kp.Format)
|
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
|
||||||
|
}
|
||||||
|
|
|
||||||
314
modules/caddypki/crypto_test.go
Normal file
314
modules/caddypki/crypto_test.go
Normal file
|
|
@ -0,0 +1,314 @@
|
||||||
|
// 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))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -66,16 +66,16 @@ func (p *PKI) renewCertsForCA(ca *CA) error {
|
||||||
if needsRenewal(ca.root) {
|
if needsRenewal(ca.root) {
|
||||||
// TODO: implement root renewal (use same key)
|
// TODO: implement root renewal (use same key)
|
||||||
log.Warn("root certificate expiring soon (FIXME: ROOT RENEWAL NOT YET IMPLEMENTED)",
|
log.Warn("root certificate expiring soon (FIXME: ROOT RENEWAL NOT YET IMPLEMENTED)",
|
||||||
zap.Duration("time_remaining", time.Until(ca.inter.NotAfter)),
|
zap.Duration("time_remaining", time.Until(ca.interChain[0].NotAfter)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// only maintain the intermediate if it's not manually provided in the config
|
// only maintain the intermediate if it's not manually provided in the config
|
||||||
if ca.Intermediate == nil {
|
if ca.Intermediate == nil {
|
||||||
if needsRenewal(ca.inter) {
|
if needsRenewal(ca.interChain[0]) {
|
||||||
log.Info("intermediate expires soon; renewing",
|
log.Info("intermediate expires soon; renewing",
|
||||||
zap.Duration("time_remaining", time.Until(ca.inter.NotAfter)),
|
zap.Duration("time_remaining", time.Until(ca.interChain[0].NotAfter)),
|
||||||
)
|
)
|
||||||
|
|
||||||
rootCert, rootKey, err := ca.loadOrGenRoot()
|
rootCert, rootKey, err := ca.loadOrGenRoot()
|
||||||
|
|
@ -86,10 +86,10 @@ func (p *PKI) renewCertsForCA(ca *CA) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("generating new certificate: %v", err)
|
return fmt.Errorf("generating new certificate: %v", err)
|
||||||
}
|
}
|
||||||
ca.inter, ca.interKey = interCert, interKey
|
ca.interChain, ca.interKey = []*x509.Certificate{interCert}, interKey
|
||||||
|
|
||||||
log.Info("renewed intermediate",
|
log.Info("renewed intermediate",
|
||||||
zap.Time("new_expiration", ca.inter.NotAfter),
|
zap.Time("new_expiration", ca.interChain[0].NotAfter),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -671,7 +671,7 @@ func ParseCaddyfilePreferredChainsOptions(d *caddyfile.Dispenser) (*ChainPrefere
|
||||||
switch d.Val() {
|
switch d.Val() {
|
||||||
case "root_common_name":
|
case "root_common_name":
|
||||||
rootCommonNameOpt := d.RemainingArgs()
|
rootCommonNameOpt := d.RemainingArgs()
|
||||||
chainPref.RootCommonName = rootCommonNameOpt
|
chainPref.RootCommonName = append(chainPref.RootCommonName, rootCommonNameOpt...)
|
||||||
if rootCommonNameOpt == nil {
|
if rootCommonNameOpt == nil {
|
||||||
return nil, d.ArgErr()
|
return nil, d.ArgErr()
|
||||||
}
|
}
|
||||||
|
|
@ -681,7 +681,7 @@ func ParseCaddyfilePreferredChainsOptions(d *caddyfile.Dispenser) (*ChainPrefere
|
||||||
|
|
||||||
case "any_common_name":
|
case "any_common_name":
|
||||||
anyCommonNameOpt := d.RemainingArgs()
|
anyCommonNameOpt := d.RemainingArgs()
|
||||||
chainPref.AnyCommonName = anyCommonNameOpt
|
chainPref.AnyCommonName = append(chainPref.AnyCommonName, anyCommonNameOpt...)
|
||||||
if anyCommonNameOpt == nil {
|
if anyCommonNameOpt == nil {
|
||||||
return nil, d.ArgErr()
|
return nil, d.ArgErr()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -257,7 +257,7 @@ func (PKIIntermediateCAPool) CaddyModule() caddy.ModuleInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loads the PKI app and load the intermediate certificates into the certificate pool
|
// Loads the PKI app and loads the intermediate certificates into the certificate pool
|
||||||
func (p *PKIIntermediateCAPool) Provision(ctx caddy.Context) error {
|
func (p *PKIIntermediateCAPool) Provision(ctx caddy.Context) error {
|
||||||
pkiApp, err := ctx.AppIfConfigured("pki")
|
pkiApp, err := ctx.AppIfConfigured("pki")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -274,7 +274,9 @@ func (p *PKIIntermediateCAPool) Provision(ctx caddy.Context) error {
|
||||||
|
|
||||||
caPool := x509.NewCertPool()
|
caPool := x509.NewCertPool()
|
||||||
for _, ca := range p.ca {
|
for _, ca := range p.ca {
|
||||||
caPool.AddCert(ca.IntermediateCertificate())
|
for _, c := range ca.IntermediateCertificateChain() {
|
||||||
|
caPool.AddCert(c)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
p.pool = caPool
|
p.pool = caPool
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,8 @@ func (iss InternalIssuer) Issue(ctx context.Context, csr *x509.CertificateReques
|
||||||
if iss.SignWithRoot {
|
if iss.SignWithRoot {
|
||||||
issuerCert = iss.ca.RootCertificate()
|
issuerCert = iss.ca.RootCertificate()
|
||||||
} else {
|
} else {
|
||||||
issuerCert = iss.ca.IntermediateCertificate()
|
chain := iss.ca.IntermediateCertificateChain()
|
||||||
|
issuerCert = chain[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure issued certificate does not expire later than its issuer
|
// ensure issued certificate does not expire later than its issuer
|
||||||
|
|
|
||||||
262
modules/caddytls/internalissuer_test.go
Normal file
262
modules/caddytls/internalissuer_test.go
Normal file
|
|
@ -0,0 +1,262 @@
|
||||||
|
// 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))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue