Skip to content

Commit 16965cc

Browse files
committed
Use sigs.k8s.io certwatcher for convsersion webhook TLS config
1 parent 7221bd4 commit 16965cc

File tree

5 files changed

+71
-56
lines changed

5 files changed

+71
-56
lines changed

pkg/cmd/crdconversionwebhook/cmd.go

Lines changed: 59 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
package crdconversionwebhook
22

33
import (
4+
"context"
45
"crypto/tls"
56
"fmt"
67
"net/http"
78

89
"github.com/spf13/cobra"
10+
"k8s.io/klog/v2"
11+
"sigs.k8s.io/controller-runtime/pkg/certwatcher"
12+
"sigs.k8s.io/controller-runtime/pkg/log"
913

1014
converter "github.com/openshift/console-operator/pkg/cmd/crdconversionwebhook/converter"
1115
)
@@ -31,22 +35,63 @@ func NewConverter() *cobra.Command {
3135
return cmd
3236
}
3337

34-
// Config contains the server (the webhook) cert and key.
35-
type Config struct {
36-
CertFile string
37-
KeyFile string
38-
}
39-
4038
func startServer() {
41-
config := Config{CertFile: certFile, KeyFile: keyFile}
39+
ctx, cancel := context.WithCancel(context.Background())
40+
defer cancel()
41+
42+
// Initialize klog
43+
klog.InitFlags(nil)
44+
log.SetLogger(klog.NewKlogr()) // controller-runtime/log will complain if we don't set this
45+
46+
// Log flag values for debugging
47+
klog.Infof("Starting console conversion webhook server")
48+
klog.V(4).Infof("Using flags:\n\t--tls-cert-file %s\n\t--tls-private-key-file %s\n\t--port %d", certFile, keyFile, port)
49+
50+
// Initialize a new cert watcher with cert/key pair
51+
klog.V(4).Infof("Creating cert watcher")
52+
watcher, err := certwatcher.New(certFile, keyFile)
53+
if err != nil {
54+
klog.Fatalf("Error creating cert watcher: %v", err)
55+
}
56+
57+
// Start goroutine with certwatcher running fsnotify against supplied certdir
58+
go func() {
59+
klog.V(4).Infof("Starting cert watcher")
60+
if err := watcher.Start(ctx); err != nil {
61+
klog.Fatalf("Cert watcher failed: %v", err)
62+
}
63+
}()
4264

43-
http.HandleFunc("/crdconvert", converter.ServeExampleConvert)
65+
// Setup TLS config using GetCertficate for fetching the cert when it changes
66+
tlsConfig := &tls.Config{
67+
GetCertificate: watcher.GetCertificate,
68+
NextProtos: []string{"http/1.1"}, // Disable HTTP/2
69+
}
70+
71+
// Create TLS listener
72+
klog.V(4).Infof("Creating TLS listener on port %d", port)
73+
listener, err := tls.Listen("tcp", fmt.Sprintf(":%d", port), tlsConfig)
74+
if err != nil {
75+
klog.Fatalf("Error creating TLS listener: %v", err)
76+
}
77+
78+
// Setup handlers and server
79+
http.HandleFunc("/crdconvert", converter.ServeConsolePluginConvert)
4480
http.HandleFunc("/readyz", func(w http.ResponseWriter, req *http.Request) { w.Write([]byte("ok")) })
45-
clientset := getClient()
46-
server := &http.Server{
47-
Addr: fmt.Sprintf(":%d", port),
48-
TLSConfig: configTLS(config, clientset),
49-
TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler)), // disable HTTP/2
81+
server := &http.Server{}
82+
83+
// Shutdown server on context cancellation
84+
go func() {
85+
<-ctx.Done()
86+
klog.V(4).Info("Shutting down server")
87+
if err := server.Shutdown(context.Background()); err != nil {
88+
klog.Fatalf("Error shutting down server: %v", err)
89+
}
90+
}()
91+
92+
// Serve
93+
klog.Infof("Serving on %s", listener.Addr().String())
94+
if err = server.Serve(listener); err != nil && err != http.ErrServerClosed {
95+
klog.Fatalf("Error serving: %v", err)
5096
}
51-
server.ListenAndServeTLS("", "")
5297
}

pkg/cmd/crdconversionwebhook/config.go

Lines changed: 0 additions & 32 deletions
This file was deleted.

pkg/cmd/crdconversionwebhook/converter/converter.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
"github.com/openshift/console-operator/pkg/api"
1212
)
1313

14-
func convertCRD(object *unstructured.Unstructured, toVersion string) (*unstructured.Unstructured, metav1.Status) {
14+
func convertConsolePlugin(object *unstructured.Unstructured, toVersion string) (*unstructured.Unstructured, metav1.Status) {
1515
originalObject := object.DeepCopy()
1616
fromVersion := object.GetAPIVersion()
1717
convertedObject := &unstructured.Unstructured{}

pkg/cmd/crdconversionwebhook/converter/converter_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ spec:
290290
unstructuredOriginalObject := getUnstructuredObject(t, tc.originalObject)
291291
unstructuredWantedObject := getUnstructuredObject(t, tc.wantedObject)
292292

293-
convertedCR, status := convertCRD(unstructuredOriginalObject, unstructuredWantedObject.GetAPIVersion())
293+
convertedCR, status := convertConsolePlugin(unstructuredOriginalObject, unstructuredWantedObject.GetAPIVersion())
294294
if status.Status == metav1.StatusFailure {
295295
t.Errorf("error converting object: %s", status.Message)
296296
}

pkg/cmd/crdconversionwebhook/converter/framework.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package converter
22

33
import (
4+
"bytes"
45
"fmt"
56
"io"
67
"net/http"
@@ -83,15 +84,14 @@ func serve(w http.ResponseWriter, r *http.Request, convert convertFunc) {
8384
return
8485
}
8586

86-
klog.Infof("handling request: %v", body)
87+
klog.V(4).Infof("Handling request body: \n%v", string(body))
8788
obj, gvk, err := serializer.Decode(body, nil, nil)
8889
if err != nil {
8990
msg := fmt.Sprintf("failed to deserialize body (%v) with error %v", string(body), err)
9091
klog.Error(err)
9192
http.Error(w, msg, http.StatusBadRequest)
9293
return
9394
}
94-
9595
var responseObj runtime.Object
9696
switch *gvk {
9797
case v1.SchemeGroupVersion.WithKind("ConversionReview"):
@@ -104,8 +104,6 @@ func serve(w http.ResponseWriter, r *http.Request, convert convertFunc) {
104104
}
105105
convertReview.Response = doConversionV1(convertReview.Request, convert)
106106
convertReview.Response.UID = convertReview.Request.UID
107-
klog.Info(fmt.Sprintf("sending response: %v", convertReview.Response))
108-
109107
// reset the request, it is not needed in a response.
110108
convertReview.Request = &v1.ConversionRequest{}
111109
responseObj = convertReview
@@ -124,17 +122,21 @@ func serve(w http.ResponseWriter, r *http.Request, convert convertFunc) {
124122
http.Error(w, msg, http.StatusBadRequest)
125123
return
126124
}
127-
err = outSerializer.Encode(responseObj, w)
125+
126+
var responseBuffer bytes.Buffer
127+
err = outSerializer.Encode(responseObj, &responseBuffer)
128128
if err != nil {
129129
klog.Error(err)
130130
http.Error(w, err.Error(), http.StatusInternalServerError)
131131
return
132132
}
133+
klog.V(4).Infof("Sending response: \n%v", responseBuffer.String())
134+
w.Write(responseBuffer.Bytes())
133135
}
134136

135-
// ServeExampleConvert servers endpoint for the example converter defined as convertExampleCRD function.
136-
func ServeExampleConvert(w http.ResponseWriter, r *http.Request) {
137-
serve(w, r, convertCRD)
137+
// ServeConsolePluginConvert serves endpoint for the console converter defined as convertCRD function.
138+
func ServeConsolePluginConvert(w http.ResponseWriter, r *http.Request) {
139+
serve(w, r, convertConsolePlugin)
138140
}
139141

140142
type mediaType struct {

0 commit comments

Comments
 (0)