Skip to content

Commit

Permalink
Allow TLS config to be entirely configured on webhook server
Browse files Browse the repository at this point in the history
Some operators might want to respect cluster-wide TLS ciphers for example,
which means that these will eventually have to be passed down to the webhook server.

Signed-off-by: Alex Kalenyuk <akalenyu@redhat.com>
  • Loading branch information
akalenyu committed May 16, 2022
1 parent 3f265c3 commit 187187e
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 1 deletion.
8 changes: 8 additions & 0 deletions pkg/webhook/server.go
Expand Up @@ -76,6 +76,9 @@ type Server struct {
// "", "1.0", "1.1", "1.2" and "1.3" only ("" is equivalent to "1.0" for backwards compatibility)
TLSMinVersion string

// TLSOpts is used to allow configuring the TLS config used for the server
TLSOpts []func(*tls.Config)

// WebhookMux is the multiplexer that handles different webhooks.
WebhookMux *http.ServeMux

Expand Down Expand Up @@ -254,6 +257,11 @@ func (s *Server) Start(ctx context.Context) error {
cfg.ClientAuth = tls.RequireAndVerifyClientCert
}

// fallback TLS config ready, will now mutate if passer wants full control over it
for _, op := range s.TLSOpts {
op(cfg)
}

listener, err := tls.Listen("tcp", net.JoinHostPort(s.Host, strconv.Itoa(s.Port)), cfg)
if err != nil {
return err
Expand Down
43 changes: 42 additions & 1 deletion pkg/webhook/server_test.go
Expand Up @@ -18,6 +18,7 @@ package webhook_test

import (
"context"
"crypto/tls"
"fmt"
"io"
"net"
Expand Down Expand Up @@ -186,7 +187,7 @@ var _ = Describe("Webhook Server", func() {
})
})

It("should serve be able to serve in unmanaged mode", func() {
It("should be able to serve in unmanaged mode", func() {
server = &webhook.Server{
Host: servingOpts.LocalServingHost,
Port: servingOpts.LocalServingPort,
Expand All @@ -207,6 +208,46 @@ var _ = Describe("Webhook Server", func() {
ctxCancel()
Eventually(doneCh, "4s").Should(BeClosed())
})

It("should respect passed in TLS configurations", func() {
var finalCfg *tls.Config
tlsCfgFunc := func(cfg *tls.Config) {
cfg.CipherSuites = []uint16{
tls.TLS_AES_128_GCM_SHA256,
tls.TLS_AES_256_GCM_SHA384,
}
// save cfg after changes to test against
finalCfg = cfg
}
server = &webhook.Server{
Host: servingOpts.LocalServingHost,
Port: servingOpts.LocalServingPort,
CertDir: servingOpts.LocalServingCertDir,
TLSMinVersion: "1.2",
TLSOpts: []func(*tls.Config){
tlsCfgFunc,
},
}
server.Register("/somepath", &testHandler{})
doneCh := genericStartServer(func(ctx context.Context) {
Expect(server.StartStandalone(ctx, scheme.Scheme))
})

Eventually(func() ([]byte, error) {
resp, err := client.Get(fmt.Sprintf("https://%s/somepath", testHostPort))
Expect(err).NotTo(HaveOccurred())
defer resp.Body.Close()
return io.ReadAll(resp.Body)
}).Should(Equal([]byte("gadzooks!")))
Expect(finalCfg.MinVersion).To(Equal(uint16(tls.VersionTLS12)))
Expect(finalCfg.CipherSuites).To(ContainElements(
tls.TLS_AES_128_GCM_SHA256,
tls.TLS_AES_256_GCM_SHA384,
))

ctxCancel()
Eventually(doneCh, "4s").Should(BeClosed())
})
})

type testHandler struct {
Expand Down

0 comments on commit 187187e

Please sign in to comment.