1
Fork 0
mirror of https://github.com/caddyserver/caddy.git synced 2024-12-16 21:56:40 -05:00

caddytls: Support new tls.context module (#6369)

* caddytls: Support new tls.context module

This allows modules to manipulate the context passed into CertMagic's GetCertificate function, which can be useful for tracing/metrics, or other
custom logic.

This is experimental and may resolve the request of a sponsor, so we'll see how it goes!

* Derpy derp
This commit is contained in:
Matt Holt 2024-10-01 17:18:17 -06:00 committed by GitHub
parent f3aead0e4d
commit 9b4acc2449
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -15,6 +15,7 @@
package caddytls package caddytls
import ( import (
"context"
"crypto/tls" "crypto/tls"
"crypto/x509" "crypto/x509"
"encoding/base64" "encoding/base64"
@ -78,6 +79,14 @@ func (cp ConnectionPolicies) Provision(ctx caddy.Context) error {
cp[i].ClientAuthentication.verifiers = append(cp[i].ClientAuthentication.verifiers, validator.(ClientCertificateVerifier)) cp[i].ClientAuthentication.verifiers = append(cp[i].ClientAuthentication.verifiers, validator.(ClientCertificateVerifier))
} }
} }
if len(pol.HandshakeContextRaw) > 0 {
modIface, err := ctx.LoadModule(pol, "HandshakeContextRaw")
if err != nil {
return fmt.Errorf("loading handshake context module: %v", err)
}
cp[i].handshakeContext = modIface.(HandshakeContext)
}
} }
return nil return nil
@ -137,6 +146,7 @@ type ConnectionPolicy struct {
// How to match this policy with a TLS ClientHello. If // How to match this policy with a TLS ClientHello. If
// this policy is the first to match, it will be used. // this policy is the first to match, it will be used.
MatchersRaw caddy.ModuleMap `json:"match,omitempty" caddy:"namespace=tls.handshake_match"` MatchersRaw caddy.ModuleMap `json:"match,omitempty" caddy:"namespace=tls.handshake_match"`
matchers []ConnectionMatcher
// How to choose a certificate if more than one matched // How to choose a certificate if more than one matched
// the given ServerName (SNI) value. // the given ServerName (SNI) value.
@ -192,6 +202,12 @@ type ConnectionPolicy struct {
// This feature is EXPERIMENTAL and subject to change or removal. // This feature is EXPERIMENTAL and subject to change or removal.
InsecureSecretsLog string `json:"insecure_secrets_log,omitempty"` InsecureSecretsLog string `json:"insecure_secrets_log,omitempty"`
// A module that can manipulate the context passed into CertMagic's
// certificate management functions during TLS handshakes.
// EXPERIMENTAL - subject to change or removal.
HandshakeContextRaw json.RawMessage `json:"handshake_context,omitempty" caddy:"namespace=tls.context inline_key=module"`
handshakeContext HandshakeContext
// TLSConfig is the fully-formed, standard lib TLS config // TLSConfig is the fully-formed, standard lib TLS config
// used to serve TLS connections. Provision all // used to serve TLS connections. Provision all
// ConnectionPolicies to populate this. It is exported only // ConnectionPolicies to populate this. It is exported only
@ -199,8 +215,15 @@ type ConnectionPolicy struct {
// if necessary (like to adjust NextProtos to disable HTTP/2), // if necessary (like to adjust NextProtos to disable HTTP/2),
// and may be unexported in the future. // and may be unexported in the future.
TLSConfig *tls.Config `json:"-"` TLSConfig *tls.Config `json:"-"`
}
matchers []ConnectionMatcher type HandshakeContext interface {
// HandshakeContext returns a context to pass into CertMagic's
// GetCertificate function used to serve, load, and manage certs
// during TLS handshakes. Generally you'll start with the context
// from the ClientHelloInfo, but you may use other information
// from it as well. Return an error to abort the handshake.
HandshakeContext(*tls.ClientHelloInfo) (context.Context, error)
} }
func (p *ConnectionPolicy) buildStandardTLSConfig(ctx caddy.Context) error { func (p *ConnectionPolicy) buildStandardTLSConfig(ctx caddy.Context) error {
@ -240,7 +263,18 @@ func (p *ConnectionPolicy) buildStandardTLSConfig(ctx caddy.Context) error {
} }
cfg.DefaultServerName = p.DefaultSNI cfg.DefaultServerName = p.DefaultSNI
cfg.FallbackServerName = p.FallbackSNI cfg.FallbackServerName = p.FallbackSNI
return cfg.GetCertificate(hello)
// TODO: experimental: if a handshake context module is configured, allow it
// to modify the context before passing it into CertMagic's GetCertificate
ctx := hello.Context()
if p.handshakeContext != nil {
ctx, err = p.handshakeContext.HandshakeContext(hello)
if err != nil {
return nil, fmt.Errorf("handshake context: %v", err)
}
}
return cfg.GetCertificateWithContext(ctx, hello)
}, },
MinVersion: tls.VersionTLS12, MinVersion: tls.VersionTLS12,
MaxVersion: tls.VersionTLS13, MaxVersion: tls.VersionTLS13,