From 748034e7af9694a55e83f792b8049f3ff3507f71 Mon Sep 17 00:00:00 2001
From: Nikolay <nik@victoriametrics.com>
Date: Mon, 14 Feb 2022 18:32:13 +0300
Subject: [PATCH] Adds server certificate reload for lib/http (#2186)

* Adds server certificate reload for lib/http
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2171

* Update lib/httpserver/httpserver.go

Co-authored-by: Aliaksandr Valialkin <valyala@victoriametrics.com>
---
 lib/httpserver/httpserver.go | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/lib/httpserver/httpserver.go b/lib/httpserver/httpserver.go
index e136ca71b9..f00450684d 100644
--- a/lib/httpserver/httpserver.go
+++ b/lib/httpserver/httpserver.go
@@ -93,14 +93,30 @@ func Serve(addr string, rh RequestHandler) {
 	ln := net.Listener(lnTmp)
 
 	if *tlsEnable {
-		cert, err := tls.LoadX509KeyPair(*tlsCertFile, *tlsKeyFile)
+		var certLock sync.Mutex
+		var certDeadline uint64
+		var cert *tls.Certificate
+		c, err := tls.LoadX509KeyPair(*tlsCertFile, *tlsKeyFile)
 		if err != nil {
 			logger.Fatalf("cannot load TLS cert from tlsCertFile=%q, tlsKeyFile=%q: %s", *tlsCertFile, *tlsKeyFile, err)
 		}
+		cert = &c
 		cfg := &tls.Config{
-			Certificates:             []tls.Certificate{cert},
 			MinVersion:               tls.VersionTLS12,
 			PreferServerCipherSuites: true,
+			GetCertificate: func(info *tls.ClientHelloInfo) (*tls.Certificate, error) {
+				certLock.Lock()
+				defer certLock.Unlock()
+				if fasttime.UnixTimestamp() > certDeadline {
+					c, err = tls.LoadX509KeyPair(*tlsCertFile, *tlsKeyFile)
+					if err != nil {
+						return nil, fmt.Errorf("cannot load TLS cert from tlsCertFile=%q, tlsKeyFile=%q: %w", *tlsCertFile, *tlsKeyFile, err)
+					}
+					certDeadline = fasttime.UnixTimestamp() + 1
+					cert = &c
+				}
+				return cert, nil
+			},
 		}
 		ln = tls.NewListener(ln, cfg)
 	}