Skip to content

Commit 621c0e7

Browse files
committed
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!
1 parent 7088605 commit 621c0e7

File tree

1 file changed

+36
-2
lines changed

1 file changed

+36
-2
lines changed

modules/caddytls/connpolicy.go

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package caddytls
1616

1717
import (
18+
"context"
1819
"crypto/tls"
1920
"crypto/x509"
2021
"encoding/base64"
@@ -77,6 +78,14 @@ func (cp ConnectionPolicies) Provision(ctx caddy.Context) error {
7778
cp[i].ClientAuthentication.verifiers = append(cp[i].ClientAuthentication.verifiers, validator.(ClientCertificateVerifier))
7879
}
7980
}
81+
82+
if len(pol.HandshakeContextRaw) > 0 {
83+
modIface, err := ctx.LoadModule(pol, "HandshakeContextRaw")
84+
if err != nil {
85+
return fmt.Errorf("loading handshake context module: %v", err)
86+
}
87+
cp[i].handshakeContext = modIface.(HandshakeContext)
88+
}
8089
}
8190

8291
return nil
@@ -136,6 +145,7 @@ type ConnectionPolicy struct {
136145
// How to match this policy with a TLS ClientHello. If
137146
// this policy is the first to match, it will be used.
138147
MatchersRaw caddy.ModuleMap `json:"match,omitempty" caddy:"namespace=tls.handshake_match"`
148+
matchers []ConnectionMatcher
139149

140150
// How to choose a certificate if more than one matched
141151
// the given ServerName (SNI) value.
@@ -191,15 +201,28 @@ type ConnectionPolicy struct {
191201
// This feature is EXPERIMENTAL and subject to change or removal.
192202
InsecureSecretsLog string `json:"insecure_secrets_log,omitempty"`
193203

204+
// A module that can manipulate the context passed into CertMagic's
205+
// certificate management functions during TLS handshakes.
206+
// EXPERIMENTAL - subject to change or removal.
207+
HandshakeContextRaw json.RawMessage `json:"handshake_context,omitempty" caddy:"namespace=tls.context"`
208+
handshakeContext HandshakeContext
209+
194210
// TLSConfig is the fully-formed, standard lib TLS config
195211
// used to serve TLS connections. Provision all
196212
// ConnectionPolicies to populate this. It is exported only
197213
// so it can be minimally adjusted after provisioning
198214
// if necessary (like to adjust NextProtos to disable HTTP/2),
199215
// and may be unexported in the future.
200216
TLSConfig *tls.Config `json:"-"`
217+
}
201218

202-
matchers []ConnectionMatcher
219+
type HandshakeContext interface {
220+
// HandshakeContext returns a context to pass into CertMagic's
221+
// GetCertificate function used to serve, load, and manage certs
222+
// during TLS handshakes. Generally you'll start with the context
223+
// from the ClientHelloInfo, but you may use other information
224+
// from it as well. Return an error to abort the handshake.
225+
HandshakeContext(*tls.ClientHelloInfo) (context.Context, error)
203226
}
204227

205228
func (p *ConnectionPolicy) buildStandardTLSConfig(ctx caddy.Context) error {
@@ -239,7 +262,18 @@ func (p *ConnectionPolicy) buildStandardTLSConfig(ctx caddy.Context) error {
239262
}
240263
cfg.DefaultServerName = p.DefaultSNI
241264
cfg.FallbackServerName = p.FallbackSNI
242-
return cfg.GetCertificate(hello)
265+
266+
// TODO: experimental: if a handshake context module is configured, allow it
267+
// to modify the context before passing it into CertMagic's GetCertificate
268+
ctx := hello.Context()
269+
if p.handshakeContext != nil {
270+
ctx, err = p.handshakeContext.HandshakeContext(hello)
271+
if err != nil {
272+
return nil, fmt.Errorf("handshake context: %v", err)
273+
}
274+
}
275+
276+
return cfg.GetCertificateWithContext(ctx, hello)
243277
},
244278
MinVersion: tls.VersionTLS12,
245279
MaxVersion: tls.VersionTLS13,

0 commit comments

Comments
 (0)