From 013675f0e3759336fdc9312bbdcba3bfc7e59bb9 Mon Sep 17 00:00:00 2001 From: Jeeva Kandasamy Date: Thu, 23 Jul 2026 00:41:27 +0530 Subject: [PATCH] print certificate validity on startup Signed-off-by: Jeeva Kandasamy --- pkg/service/http_listener/https/ssl.go | 19 ++++++++++++++++ pkg/service/http_listener/https/ssl_test.go | 25 +++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/pkg/service/http_listener/https/ssl.go b/pkg/service/http_listener/https/ssl.go index 3ffd94d..f76369b 100644 --- a/pkg/service/http_listener/https/ssl.go +++ b/pkg/service/http_listener/https/ssl.go @@ -206,9 +206,28 @@ func (m *SSLManager) loadOrCreate() error { m.mu.Lock() m.cert = &certificate m.mu.Unlock() + + // print certificate validity on startup (custom and managed) + logCertificateValidity(m.logger, &certificate) return nil } +// logCertificateValidity prints the loaded certificate's NotBefore/NotAfter and remaining lifetime. +func logCertificateValidity(logger *zap.Logger, certificate *tls.Certificate) { + if certificate == nil || len(certificate.Certificate) == 0 { + return + } + + x509Cert, err := x509.ParseCertificate(certificate.Certificate[0]) + if err != nil { + logger.Warn("unable to parse SSL certificate for validity info", zap.Error(err)) + return + } + + remaining := time.Until(x509Cert.NotAfter) + logger.Info("SSL certificate validity", zap.Time("notBefore", x509Cert.NotBefore), zap.Time("notAfter", x509Cert.NotAfter), zap.Duration("remaining", remaining)) +} + // isManagedByMyController is true when no operator-supplied custom cert/key pair is present. func isManagedByMyController(cfg config.HttpsSSLConfig) bool { customCertFile := filepath.Join(cfg.CertDir, CustomCertFileName) diff --git a/pkg/service/http_listener/https/ssl_test.go b/pkg/service/http_listener/https/ssl_test.go index fb0b288..f79824f 100644 --- a/pkg/service/http_listener/https/ssl_test.go +++ b/pkg/service/http_listener/https/ssl_test.go @@ -94,6 +94,31 @@ func TestShouldRegenerateCert_InvalidCert(t *testing.T) { } } +func TestNewSSLManager_LogsCertificateValidityOnStartup(t *testing.T) { + core, logs := observer.New(zap.InfoLevel) + logger := zap.New(core) + dir := t.TempDir() + + _, err := NewSSLManager(logger, config.HttpsSSLConfig{CertDir: dir}, nil) + if err != nil { + t.Fatalf("NewSSLManager failed: %v", err) + } + + var found bool + for _, e := range logs.All() { + if e.Message == "SSL certificate validity" { + found = true + if e.ContextMap()["notBefore"] == nil || e.ContextMap()["notAfter"] == nil || e.ContextMap()["remaining"] == nil { + t.Fatalf("expected notBefore, notAfter, and remaining fields, got: %v", e.ContextMap()) + } + break + } + } + if !found { + t.Fatal("expected SSL certificate validity log on startup") + } +} + func TestGetSSLTLSConfig_ReusesGeneratedCert(t *testing.T) { logger := zap.NewNop() dir := t.TempDir()