From 7f85c1f9f14a9016dfdd9a93d304f2d002e32ab8 Mon Sep 17 00:00:00 2001 From: Jenny Zhu Date: Tue, 10 Dec 2024 19:41:51 -0500 Subject: [PATCH] OU-539: Dynamically reload TLS certificates --- cmd/plugin-backend.go | 13 +++++++++--- pkg/server/server.go | 48 ++++++++++++++++++++++++++----------------- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/cmd/plugin-backend.go b/cmd/plugin-backend.go index 8e8463636..c236b72d6 100644 --- a/cmd/plugin-backend.go +++ b/cmd/plugin-backend.go @@ -18,7 +18,7 @@ var ( staticPathArg = flag.String("static-path", "", "static files path to serve frontend (default: './web/dist')") configPathArg = flag.String("config-path", "", "config files path (default: './config')") pluginConfigArg = flag.String("plugin-config-path", "", "plugin yaml configuration") - logLevelArg = flag.String("log-level", "error", "verbosity of logs\noptions: ['panic', 'fatal', 'error', 'warn', 'info', 'debug', 'trace']\n'trace' level will log all incoming requests\n(default 'error')") + logLevelArg = flag.String("log-level", logrus.InfoLevel.String(), "verbosity of logs\noptions: ['panic', 'fatal', 'error', 'warn', 'info', 'debug', 'trace']\n'trace' level will log all incoming requests\n(default 'error')") log = logrus.WithField("module", "main") ) @@ -32,7 +32,7 @@ func main() { staticPath := mergeEnvValue("LOGGING_VIEW_PLUGIN_STATIC_PATH", *staticPathArg, "./web/dist") configPath := mergeEnvValue("LOGGING_VIEW_PLUGIN_MANIFEST_CONFIG_PATH", *configPathArg, "./config") pluginConfigPath := mergeEnvValue("LOGGING_VIEW_PLUGIN_CONFIG_PATH", *pluginConfigArg, "/etc/plugin/config.yaml") - logLevel := mergeEnvValue("LOGGING_VIEW_PLUGIN_LOG_LEVEL", *logLevelArg, "error") + logLevel := mergeEnvValue("LOGGING_VIEW_PLUGIN_LOG_LEVEL", *logLevelArg, logrus.InfoLevel.String()) featuresList := strings.Fields(strings.Join(strings.Split(strings.ToLower(features), ","), " ")) @@ -41,6 +41,14 @@ func main() { featuresSet[s] = true } + logrusLevel, err := logrus.ParseLevel(logLevel) + if err != nil { + logrusLevel = logrus.ErrorLevel + logrus.WithError(err).Warnf("Invalid log level. Defaulting to %q", logrusLevel.String()) + } + + logrus.SetLevel(logrusLevel) + log.Infof("enabled features: %+q\n", featuresList) server.Start(&server.Config{ @@ -51,7 +59,6 @@ func main() { StaticPath: staticPath, ConfigPath: configPath, PluginConfigPath: pluginConfigPath, - LogLevel: logLevel, }) } diff --git a/pkg/server/server.go b/pkg/server/server.go index 0ba17f37e..c542851e8 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -15,6 +15,10 @@ import ( "github.com/sirupsen/logrus" "gopkg.in/yaml.v3" "k8s.io/apiserver/pkg/server/dynamiccertificates" + + v1 "k8s.io/api/core/v1" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/tools/record" ) var slog = logrus.WithField("module", "server") @@ -27,7 +31,6 @@ type Config struct { StaticPath string ConfigPath string PluginConfigPath string - LogLevel string } type PluginConfig struct { @@ -63,31 +66,40 @@ func Start(cfg *Config) { if tlsEnabled { // Build and run the controller which reloads the certificate and key // files whenever they change. + ctx := context.Background() + certKeyPair, err := dynamiccertificates.NewDynamicServingContentFromFiles("serving-cert", cfg.CertFile, cfg.PrivateKeyFile) if err != nil { - logrus.WithError(err).Fatal("unable to create TLS controller") + slog.WithError(err).Fatal("unable to create TLS controller") + } + + if err := certKeyPair.RunOnce(ctx); err != nil { + slog.WithError(err).Fatal("failed to initialize cert/key content") } + + eventBroadcaster := record.NewBroadcaster() + eventBroadcaster.StartLogging(func(format string, args ...interface{}) { + slog.Infof(format, args...) + }) + ctrl := dynamiccertificates.NewDynamicServingCertificateController( tlsConfig, nil, certKeyPair, nil, - nil, + record.NewEventRecorderAdapter( + eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "logging-view-plugin"}), + ), ) - // Check that the cert and key files are valid. - if err := ctrl.RunOnce(); err != nil { - logrus.WithError(err).Fatal("invalid certificate/key files") - } + // Configure the server to use the cert/key pair for all client connections. + tlsConfig.GetConfigForClient = ctrl.GetConfigForClient - ctx := context.Background() - go ctrl.Run(1, ctx.Done()) - } + // Notify cert/key file changes to the controller. + certKeyPair.AddListener(ctrl) - logrusLevel, err := logrus.ParseLevel(cfg.LogLevel) - if err != nil { - logrus.WithError(err).Fatal("unable to set the log level") - logrusLevel = logrus.ErrorLevel + go ctrl.Run(1, ctx.Done()) + go certKeyPair.Run(ctx, 1) } httpServer := &http.Server{ @@ -98,18 +110,16 @@ func Start(cfg *Config) { WriteTimeout: 30 * time.Second, } - if logrusLevel == logrus.TraceLevel { + if logrus.GetLevel() == logrus.TraceLevel { loggedRouter := handlers.LoggingHandler(slog.Logger.Out, router) httpServer.Handler = loggedRouter } if tlsEnabled { - slog.Infof("listening on https://:%d", cfg.Port) - logrus.SetLevel(logrusLevel) + slog.Infof("listening for https on %s", httpServer.Addr) panic(httpServer.ListenAndServeTLS(cfg.CertFile, cfg.PrivateKeyFile)) } else { - slog.Infof("listening on http://:%d", cfg.Port) - logrus.SetLevel(logrusLevel) + slog.Infof("listening for http on %s", httpServer.Addr) panic(httpServer.ListenAndServe()) } }