diff --git a/cmd/postgres_exporter/postgres_exporter_test.go b/cmd/postgres_exporter/postgres_exporter_test.go index 6017756a..c40bf7c1 100644 --- a/cmd/postgres_exporter/postgres_exporter_test.go +++ b/cmd/postgres_exporter/postgres_exporter_test.go @@ -421,3 +421,58 @@ func (s *FunctionalSuite) TestParseUserQueries(c *C) { } } } + +func (s *FunctionalSuite) TestLoggableDSN(c *C) { + type TestCase struct { + input string + expected string + } + + cases := []TestCase{ + { + input: "host=host.example.com user=postgres port=5432 password=s3cr3t", + expected: "host=host.example.com user=postgres port=5432 password=PASSWORD_REMOVED", + }, + + { + input: "host=host.example.com user=postgres port=5432 password=\"s3cr 3t\"", + expected: "host=host.example.com user=postgres port=5432 password=PASSWORD_REMOVED", + }, + + { + input: "password=abcde host=host.example.com user=postgres port=5432", + expected: "password=PASSWORD_REMOVED host=host.example.com user=postgres port=5432", + }, + + { + input: "password=abcde host=host.example.com user=postgres port=5432 password=\"s3cr 3t\"", + expected: "password=PASSWORD_REMOVED host=host.example.com user=postgres port=5432 password=PASSWORD_REMOVED", + }, + + { + input: "postgresql://host.example.com:5432/tsdb?user=postgres", + expected: "postgresql://host.example.com:5432/tsdb?user=postgres", + }, + + { + input: "postgresql://user:s3cret@host.example.com:5432/tsdb?user=postgres", + expected: "postgresql://user:PASSWORD_REMOVED@host.example.com:5432/tsdb?user=postgres", + }, + + { + input: "postgresql://host.example.com:5432/tsdb?user=postgres&password=s3cr3t", + expected: "postgresql://host.example.com:5432/tsdb?password=PASSWORD_REMOVED&user=postgres", + }, + + { + input: "host=host.example.com user=postgres port=5432", + expected: "host=host.example.com user=postgres port=5432", + }, + } + + for _, cs := range cases { + loggable := loggableDSN(cs.input) + c.Assert(loggable, Equals, cs.expected) + } + +} diff --git a/cmd/postgres_exporter/util.go b/cmd/postgres_exporter/util.go index 3a125f1d..8ba4bb67 100644 --- a/cmd/postgres_exporter/util.go +++ b/cmd/postgres_exporter/util.go @@ -17,6 +17,7 @@ import ( "fmt" "math" "net/url" + "regexp" "strconv" "strings" "time" @@ -212,10 +213,24 @@ func loggableDSN(dsn string) string { if err != nil { return "could not parse DATA_SOURCE_NAME" } + + // If the DSN is not a URL it is expected to be in the `key1=value1 key2=value2` format + if pDSN.Scheme == "" { + re := regexp.MustCompile(`(\s?password=([^"\s]+|"[^"]+"))`) + stripped := re.ReplaceAllString(dsn, " password=PASSWORD_REMOVED") + return strings.TrimSpace(stripped) + } + // Blank user info if not nil if pDSN.User != nil { pDSN.User = url.UserPassword(pDSN.User.Username(), "PASSWORD_REMOVED") } + // If the password is contained in a URL parameter, we should remove it there + if q, err := url.ParseQuery(pDSN.RawQuery); err == nil && q.Has("password") { + q.Set("password", "PASSWORD_REMOVED") + pDSN.RawQuery = q.Encode() + } + return pDSN.String() }