Skip to content

Commit

Permalink
Add support for SSL env vars to cert pool watcher (#1672)
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
tmshort authored Jan 30, 2025
1 parent da0e803 commit 5b7da35
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 2 deletions.
24 changes: 22 additions & 2 deletions internal/httputil/certpoolwatcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"crypto/x509"
"fmt"
"os"
"slices"
"strings"
"sync"
"time"

Expand Down Expand Up @@ -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{
Expand Down
4 changes: 4 additions & 0 deletions internal/httputil/certpoolwatcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 5b7da35

Please sign in to comment.