Skip to content

Commit 54359c8

Browse files
cahillsfclaude
andcommitted
wire certwatcher for dynamic client TLS cert reloading
Emissary rotates TLS certs on disk via atomic symlink swaps, but Crossplane's client mTLS config was loaded once at startup. This adds a controller-runtime certwatcher to dynamically reload client certs and CA on rotation, eliminating the need for manual rollout restarts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent a1314d1 commit 54359c8

1 file changed

Lines changed: 28 additions & 0 deletions

File tree

cmd/crossplane/core/core.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ package core
2020
import (
2121
"context"
2222
"crypto/tls"
23+
"crypto/x509"
2324
"fmt"
2425
"io"
2526
"os"
@@ -40,6 +41,7 @@ import (
4041
"k8s.io/client-go/tools/record"
4142
ctrl "sigs.k8s.io/controller-runtime"
4243
"sigs.k8s.io/controller-runtime/pkg/cache"
44+
"sigs.k8s.io/controller-runtime/pkg/certwatcher"
4345
"sigs.k8s.io/controller-runtime/pkg/client"
4446
"sigs.k8s.io/controller-runtime/pkg/healthz"
4547
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
@@ -306,6 +308,32 @@ func (c *startCommand) Run(s *runtime.Scheme, log logging.Logger) error { //noli
306308
return errors.Wrap(err, "cannot load client TLS certificates")
307309
}
308310

311+
clientCertWatcher, err := certwatcher.New(
312+
filepath.Join(c.TLSClientCertsDir, c.TLSClientCertFileName),
313+
filepath.Join(c.TLSClientCertsDir, c.TLSClientKeyFileName),
314+
)
315+
if err != nil {
316+
return errors.Wrap(err, "cannot create client certificate watcher")
317+
}
318+
clienttls.GetClientCertificate = func(_ *tls.CertificateRequestInfo) (*tls.Certificate, error) {
319+
return clientCertWatcher.GetCertificate(nil)
320+
}
321+
caPath := filepath.Join(c.TLSClientCertsDir, c.TLSClientCACertFileName)
322+
clientCertWatcher.RegisterCallback(func(_ tls.Certificate) {
323+
ca, err := os.ReadFile(filepath.Clean(caPath))
324+
if err != nil {
325+
log.Debug("Cannot reload CA certificate", "error", err)
326+
return
327+
}
328+
pool := x509.NewCertPool()
329+
if pool.AppendCertsFromPEM(ca) {
330+
clienttls.RootCAs = pool
331+
}
332+
})
333+
if err := mgr.Add(clientCertWatcher); err != nil {
334+
return errors.Wrap(err, "cannot add client certificate watcher to manager")
335+
}
336+
309337
pfrm := xfn.NewPrometheusMetrics()
310338
metrics.Registry.MustRegister(pfrm)
311339

0 commit comments

Comments
 (0)