From 5b7da35861b9c9e75a1202f77dec0c1d267e7b5b Mon Sep 17 00:00:00 2001 From: Todd Short Date: Thu, 30 Jan 2025 16:09:40 -0500 Subject: [PATCH] Add support for SSL env vars to cert pool watcher (#1672) The SystemRoot store looks at the SSL_CERT_DIR and SSL_CERT_FILE environment variables for certificate locations. Because these variables are under control of the user, we should assume that the user wants to control the contents of the SystemRoot, and subsequently that those contents could change (as compared to certs located in the default /etc/pki location). Thus, we should watch those locations if they exist. Signed-off-by: Todd Short --- internal/httputil/certpoolwatcher.go | 24 +++++++++++++++++++++-- internal/httputil/certpoolwatcher_test.go | 4 ++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/internal/httputil/certpoolwatcher.go b/internal/httputil/certpoolwatcher.go index 2a250d069..0cce70312 100644 --- a/internal/httputil/certpoolwatcher.go +++ b/internal/httputil/certpoolwatcher.go @@ -4,6 +4,8 @@ import ( "crypto/x509" "fmt" "os" + "slices" + "strings" "sync" "time" @@ -44,8 +46,26 @@ func NewCertPoolWatcher(caDir string, log logr.Logger) (*CertPoolWatcher, error) if err != nil { return nil, err } - if err = watcher.Add(caDir); err != nil { - return nil, err + + // If the SSL_CERT_DIR or SSL_CERT_FILE environment variables are + // specified, this means that we have some control over the system root + // location, thus they may change, thus we should watch those locations. + watchPaths := strings.Split(os.Getenv("SSL_CERT_DIR"), ":") + watchPaths = append(watchPaths, caDir, os.Getenv("SSL_CERT_FILE")) + watchPaths = slices.DeleteFunc(watchPaths, func(p string) bool { + if p == "" { + return true + } + if _, err := os.Stat(p); err != nil { + return true + } + return false + }) + + for _, p := range watchPaths { + if err := watcher.Add(p); err != nil { + return nil, err + } } cpw := &CertPoolWatcher{ diff --git a/internal/httputil/certpoolwatcher_test.go b/internal/httputil/certpoolwatcher_test.go index bfebebd28..2ea3f862a 100644 --- a/internal/httputil/certpoolwatcher_test.go +++ b/internal/httputil/certpoolwatcher_test.go @@ -72,6 +72,10 @@ func TestCertPoolWatcher(t *testing.T) { t.Logf("Create cert file at %q\n", certName) createCert(t, certName) + // Update environment variables for the watcher - some of these should not exist + os.Setenv("SSL_CERT_DIR", tmpDir+":/tmp/does-not-exist.dir") + os.Setenv("SSL_CERT_FILE", "/tmp/does-not-exist.file") + // Create the cert pool watcher cpw, err := httputil.NewCertPoolWatcher(tmpDir, log.FromContext(context.Background())) require.NoError(t, err)