diff --git a/plugins/inputs/x509_cert/x509_cert.go b/plugins/inputs/x509_cert/x509_cert.go index d861441ca..cce786d26 100644 --- a/plugins/inputs/x509_cert/x509_cert.go +++ b/plugins/inputs/x509_cert/x509_cert.go @@ -16,6 +16,7 @@ import ( "net/url" "os" "path/filepath" + "regexp" "strings" "time" @@ -32,6 +33,9 @@ import ( //go:embed sample.conf var sampleConfig string +// Regexp for handling file URIs containing a drive letter and leading slash +var reDriveLetter = regexp.MustCompile(`^/([a-zA-Z]:/)`) + // X509Cert holds the configuration of the plugin. type X509Cert struct { Sources []string `toml:"sources"` @@ -86,12 +90,9 @@ func (c *X509Cert) Init() error { // Gather adds metrics into the accumulator. func (c *X509Cert) Gather(acc telegraf.Accumulator) error { now := time.Now() - collectedUrls, err := c.collectCertURLs() - if err != nil { - acc.AddError(fmt.Errorf("getting some certificates failed: %w", err)) - } - for _, location := range append(c.locations, collectedUrls...) { + collectedUrls := append(c.locations, c.collectCertURLs()...) + for _, location := range collectedUrls { certs, err := c.getCert(location, time.Duration(c.Timeout)) if err != nil { acc.AddError(fmt.Errorf("cannot get SSL cert '%s': %s", location, err.Error())) @@ -153,9 +154,11 @@ func (c *X509Cert) Gather(acc telegraf.Accumulator) error { func (c *X509Cert) sourcesToURLs() error { for _, source := range c.Sources { - if strings.HasPrefix(source, "file://") || - strings.HasPrefix(source, "/") { + if strings.HasPrefix(source, "file://") || strings.HasPrefix(source, "/") { source = filepath.ToSlash(strings.TrimPrefix(source, "file://")) + // Removing leading slash in Windows path containing a drive-letter + // like "file:///C:/Windows/..." + source = reDriveLetter.ReplaceAllString(source, "$1") g, err := globpath.Compile(source) if err != nil { return fmt.Errorf("could not compile glob %v: %v", source, err) @@ -381,26 +384,22 @@ func getTags(cert *x509.Certificate, location string) map[string]string { return tags } -func (c *X509Cert) collectCertURLs() ([]*url.URL, error) { +func (c *X509Cert) collectCertURLs() []*url.URL { var urls []*url.URL for _, path := range c.globpaths { files := path.Match() if len(files) <= 0 { - c.Log.Errorf("could not find file: %v", path) + c.Log.Errorf("could not find file: %v", path.GetRoots()) continue } for _, file := range files { - file = "file://" + file - u, err := url.Parse(file) - if err != nil { - return urls, fmt.Errorf("failed to parse cert location - %s", err.Error()) - } - urls = append(urls, u) + fn := filepath.ToSlash(file) + urls = append(urls, &url.URL{Scheme: "file", Path: fn}) } } - return urls, nil + return urls } func init() { diff --git a/plugins/inputs/x509_cert/x509_cert_test.go b/plugins/inputs/x509_cert/x509_cert_test.go index 81a8cbca6..4e3012323 100644 --- a/plugins/inputs/x509_cert/x509_cert_test.go +++ b/plugins/inputs/x509_cert/x509_cert_test.go @@ -388,14 +388,42 @@ func TestSourcesToURLs(t *testing.T) { "tcp://influxdata.com:443", "smtp://influxdata.com:25", "file:///dummy_test_path_file.pem", + "file:///windows/temp/test.pem", + `file://C:\windows\temp\test.pem`, + `file:///C:/windows/temp/test.pem`, "/tmp/dummy_test_path_glob*.pem", }, Log: testutil.Logger{}, } require.NoError(t, m.Init()) - require.Equal(t, len(m.globpaths), 2) + expected := []string{ + "https://www.influxdata.com:443", + "tcp://influxdata.com:443", + "smtp://influxdata.com:25", + } + + expectedPaths := []string{ + "/dummy_test_path_file.pem", + "/windows/temp/test.pem", + "C:\\windows\\temp\\test.pem", + "C:/windows/temp/test.pem", + } + + for _, p := range expectedPaths { + expected = append(expected, filepath.FromSlash(p)) + } + + actual := make([]string, 0, len(m.globpaths)+len(m.locations)) + for _, p := range m.globpaths { + actual = append(actual, p.GetRoots()...) + } + for _, p := range m.locations { + actual = append(actual, p.String()) + } + require.Equal(t, len(m.globpaths), 5) require.Equal(t, len(m.locations), 3) + require.ElementsMatch(t, expected, actual) } func TestServerName(t *testing.T) {