diff --git a/cmd/controller/main.go b/cmd/controller/main.go index 2f5751159a..a3248449e6 100644 --- a/cmd/controller/main.go +++ b/cmd/controller/main.go @@ -61,7 +61,7 @@ import ( ) const ( - certDir = "/certs/" + tlsDir = "/home/agones/certs/" ) const ( @@ -173,7 +173,21 @@ func main() { } // https server and the items that share the Mux for routing httpsServer := https.NewServer(ctlConf.CertFile, ctlConf.KeyFile) - watchCertsDirectory(httpsServer, logger) + + cancelTLS, err := fswatch.Watch(logger, tlsDir, time.Second, func() { + tlsCert, err := readTLSCert() + if err != nil { + logger.WithError(err).Error("could not load TLS certs; keeping old one") + return + } + httpsServer.SetCertificate(tlsCert) + logger.Info("TLS certs updated") + }) + if err != nil { + logger.WithError(err).Fatal("could not create watcher for TLS certs") + } + defer cancelTLS() + wh := webhooks.NewWebHook(httpsServer.Mux) api := apiserver.NewAPIServer(httpsServer.Mux) @@ -269,42 +283,8 @@ func main() { }) } -func watchCertsDirectory(httpsServer *https.Server, logger *logrus.Entry) { - cancel, err := fswatch.Watch(logger, certDir, time.Second*5, func() { - logger.Info("Certificate files changed. Reloading...") - - newCert, err := readCertFile() - if err != nil { - logger.WithError(err).Error("Failed to reload certificates") - return - } - - // Create a new http.Server with the updated TLS configuration - newHTTPServer := &http.Server{ - Addr: ":8081", - Handler: httpsServer.Mux, - } - newHTTPServer.TLSConfig = &tls.Config{ - Certificates: []tls.Certificate{*newCert}, - } - - // Update the TLS configuration - go func() { - if err := newHTTPServer.ListenAndServeTLS("", ""); err != nil { - logger.WithError(err).Error("Failed to update TLS configuration") - } - }() - logger.Info("Certificates reloaded.") - }) - defer cancel() - - if err != nil { - logger.WithError(err).Error("Failed to set up certificate watch") - } -} - -func readCertFile() (*tls.Certificate, error) { - tlsCert, err := tls.LoadX509KeyPair(certDir+"tls.crt", certDir+"tls.key") +func readTLSCert() (*tls.Certificate, error) { + tlsCert, err := tls.LoadX509KeyPair(tlsDir+"server.crt", tlsDir+"server.key") if err != nil { return nil, err } diff --git a/cmd/extensions/main.go b/cmd/extensions/main.go index 33c0411004..5e5f253d99 100644 --- a/cmd/extensions/main.go +++ b/cmd/extensions/main.go @@ -17,6 +17,7 @@ package main import ( "context" + "crypto/tls" "io" "net/http" "os" @@ -35,6 +36,7 @@ import ( "agones.dev/agones/pkg/gameserversets" "agones.dev/agones/pkg/metrics" "agones.dev/agones/pkg/util/apiserver" + "agones.dev/agones/pkg/util/fswatch" "agones.dev/agones/pkg/util/https" "agones.dev/agones/pkg/util/runtime" "agones.dev/agones/pkg/util/signals" @@ -51,6 +53,10 @@ import ( "k8s.io/client-go/tools/clientcmd" ) +const ( + tlsDir = "/home/agones/certs/" +) + const ( enableStackdriverMetricsFlag = "stackdriver-exporter" stackdriverLabels = "stackdriver-labels" @@ -139,6 +145,21 @@ func main() { } // https server and the items that share the Mux for routing httpsServer := https.NewServer(ctlConf.CertFile, ctlConf.KeyFile) + + cancelTLS, err := fswatch.Watch(logger, tlsDir, time.Second, func() { + tlsCert, err := readTLSCert() + if err != nil { + logger.WithError(err).Error("could not load TLS certs; keeping old one") + return + } + httpsServer.SetCertificate(tlsCert) + logger.Info("TLS certs updated") + }) + if err != nil { + logger.WithError(err).Fatal("could not create watcher for TLS certs") + } + defer cancelTLS() + wh := webhooks.NewWebHook(httpsServer.Mux) api := apiserver.NewAPIServer(httpsServer.Mux) @@ -221,6 +242,14 @@ func main() { logger.Info("Shut down agones extensions") } +func readTLSCert() (*tls.Certificate, error) { + tlsCert, err := tls.LoadX509KeyPair(tlsDir+"server.crt", tlsDir+"server.key") + if err != nil { + return nil, err + } + return &tlsCert, nil +} + func parseEnvFlags() config { exec, err := os.Executable() if err != nil { diff --git a/pkg/util/https/server.go b/pkg/util/https/server.go index b1b6311571..0e8824d3fa 100644 --- a/pkg/util/https/server.go +++ b/pkg/util/https/server.go @@ -16,7 +16,9 @@ package https import ( "context" + "crypto/tls" "net/http" + "sync" "agones.dev/agones/pkg/util/runtime" "github.com/pkg/errors" @@ -24,7 +26,7 @@ import ( ) // tls is a http server interface to enable easier testing -type tls interface { +type testTLS interface { Close() error ListenAndServeTLS(certFile, keyFile string) error } @@ -35,7 +37,9 @@ type tls interface { type Server struct { logger *logrus.Entry Mux *http.ServeMux - tls tls + tls testTLS + certMu sync.RWMutex + cert *tls.Certificate certFile string keyFile string } @@ -53,6 +57,7 @@ func NewServer(certFile, keyFile string) *Server { tls: tls, certFile: certFile, keyFile: keyFile, + cert: nil, } wh.Mux.HandleFunc("/", wh.defaultHandler) wh.logger = runtime.NewLoggerWithType(wh) @@ -60,6 +65,12 @@ func NewServer(certFile, keyFile string) *Server { return wh } +func (s *Server) SetCertificate(cert *tls.Certificate) { + s.certMu.Lock() + defer s.certMu.Unlock() + s.cert = cert +} + // Run runs the webhook server, starting a https listener. // Will close the http server on stop channel close. func (s *Server) Run(ctx context.Context, _ int) error {