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:
parent
f3aead0e4d
commit
9b4acc2449
1 changed files with 36 additions and 2 deletions
|
@ -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,
|
||||||
|
|
Loading…
Reference in a new issue