Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add user and password to uri if the uri does not contain user password #560

Merged
merged 12 commits into from
Sep 13, 2023
15 changes: 13 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,25 @@ Connecting user should have sufficient rights to query needed stats:
More info about roles in MongoDB [documentation](https://docs.mongodb.com/manual/reference/built-in-roles/#mongodb-authrole-clusterMonitor).

#### Example
```
```sh
mongodb_exporter_linux_amd64/mongodb_exporter --mongodb.uri=mongodb://127.0.0.1:17001
```

#### MongoDB Authentication
You can supply the mongodb user/password direct in the `--mongodb.uri=` like `--mongodb.uri=mongodb://user:[email protected]:17001`, you can also supply the mongodb user/password with `--mongodb.user=`, `--mongodb.password=`
but the user and password info will be leaked via `ps` or `top` command, for security issue, you can use `MONGODB_USER` and `MONGODB_PASSWORD` env variable to set user/password for given uri
```sh
MONGODB_USER=XXX MONGODB_PASSWORD=YYY mongodb_exporter_linux_amd64/mongodb_exporter --mongodb.uri=mongodb://127.0.0.1:17001 --mongodb.collstats-colls=db1.c1,db2.c2
# or
export MONGODB_USER=XXX
export MONGODB_PASSWORD=YYY
mongodb_exporter_linux_amd64/mongodb_exporter --mongodb.uri=mongodb://127.0.0.1:17001 --mongodb.collstats-colls=db1.c1,db2.c2
```

#### Enabling collstats metrics gathering
`--mongodb.collstats-colls` receives a list of databases and collections to monitor using collstats.
Usage example: `--mongodb.collstats-colls=database1.collection1,database2.collection2`
```
```sh
mongodb_exporter_linux_amd64/mongodb_exporter --mongodb.uri=mongodb://127.0.0.1:17001 --mongodb.collstats-colls=db1.c1,db2.c2
```
#### Enabling compatibility mode.
Expand Down
23 changes: 19 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@

// GlobalFlags has command line flags to configure the exporter.
type GlobalFlags struct {
User string `name:"mongodb.user" help:"monitor user, need clusterMonitor role in admin db and read role in local db" env:"MONGODB_USER" placeholder:"monitorUser"`

Check failure on line 37 in main.go

View workflow job for this annotation

GitHub Actions / Lint Check

[golangci-lint] reported by reviewdog 🐶 tag is not aligned, should be: env:"MONGODB_USER" help:"monitor user, need clusterMonitor role in admin db and read role in local db" name:"mongodb.user" placeholder:"monitorUser" (tagalign) Raw Output: main.go:37:31: tag is not aligned, should be: env:"MONGODB_USER" help:"monitor user, need clusterMonitor role in admin db and read role in local db" name:"mongodb.user" placeholder:"monitorUser" (tagalign) User string `name:"mongodb.user" help:"monitor user, need clusterMonitor role in admin db and read role in local db" env:"MONGODB_USER" placeholder:"monitorUser"` ^
Password string `name:"mongodb.password" help:"monitor user password" env:"MONGODB_PASSWORD" placeholder:"monitorPassword"`

Check failure on line 38 in main.go

View workflow job for this annotation

GitHub Actions / Lint Check

[golangci-lint] reported by reviewdog 🐶 tag is not aligned, should be: env:"MONGODB_PASSWORD" help:"monitor user password" name:"mongodb.password" placeholder:"monitorPassword" (tagalign) Raw Output: main.go:38:31: tag is not aligned, should be: env:"MONGODB_PASSWORD" help:"monitor user password" name:"mongodb.password" placeholder:"monitorPassword" (tagalign) Password string `name:"mongodb.password" help:"monitor user password" env:"MONGODB_PASSWORD" placeholder:"monitorPassword"` ^
CollStatsNamespaces string `name:"mongodb.collstats-colls" help:"List of comma separared databases.collections to get $collStats" placeholder:"db1,db2.col2"`
IndexStatsCollections string `name:"mongodb.indexstats-colls" help:"List of comma separared databases.collections to get $indexStats" placeholder:"db1.col1,db2.col2"`
URI string `name:"mongodb.uri" help:"MongoDB connection URI" env:"MONGODB_URI" placeholder:"mongodb://user:[email protected]:27017/admin?ssl=true"`
Expand Down Expand Up @@ -89,6 +91,22 @@
e.Run()
}

func buildURI(uri string, user string, password string) string {
// IF user@pass not contained in uri AND custom user and pass supplied in arguments
// DO concat a new uri with user and pass arguments value
if !strings.Contains(uri, "@") && user != "" && password != "" {
// trim mongodb:// prefix to handle user and pass logic
uri = strings.TrimPrefix(uri, "mongodb://")

// log.Debugf("add user and pass to the uri")
uri = fmt.Sprintf("%s:%s@%s", user, password, uri)

// add back mongodb://
uri = "mongodb://" + uri
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's remove it, anyway we do it a few lines later

}
return uri

Check failure on line 107 in main.go

View workflow job for this annotation

GitHub Actions / Lint Check

[golangci-lint] reported by reviewdog 🐶 return with no blank line before (nlreturn) Raw Output: main.go:107:2: return with no blank line before (nlreturn) return uri ^
}

func buildExporter(opts GlobalFlags) *exporter.Exporter {
log := logrus.New()

Expand All @@ -103,10 +121,7 @@

log.Debugf("Compatible mode: %v", opts.CompatibleMode)

if !strings.HasPrefix(opts.URI, "mongodb") {
log.Debugf("Prepending mongodb:// to the URI")
opts.URI = "mongodb://" + opts.URI
}
opts.URI = buildURI(opts.URI, opts.User, opts.Password)

log.Debugf("Connection URI: %s", opts.URI)

Expand Down
97 changes: 97 additions & 0 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,100 @@

buildExporter(opts)
}

func TestBuildURI(t *testing.T) {

Check failure on line 41 in main_test.go

View workflow job for this annotation

GitHub Actions / Lint Check

[golangci-lint] reported by reviewdog 🐶 Function 'TestBuildURI' has too many statements (74 > 40) (funlen) Raw Output: main_test.go:41: Function 'TestBuildURI' has too many statements (74 > 40) (funlen) func TestBuildURI(t *testing.T) {
const newUser = "xxx"
const newPass = "yyy"

const originalBareURI = "127.0.0.1"
const originalAuthURI = "usr:[email protected]"

const originalPrefixBareURI = "mongodb://127.0.0.1"
const originalPrefixAuthURI = "mongodb://usr:[email protected]"
const changedPrefixAuthURI = "mongodb://xxx:[email protected]"

var newUri string

Check failure on line 52 in main_test.go

View workflow job for this annotation

GitHub Actions / Lint Check

[golangci-lint] reported by reviewdog 🐶 var-naming: var newUri should be newURI (revive) Raw Output: main_test.go:52:6: var-naming: var newUri should be newURI (revive) var newUri string ^
resetNewUri := func() {

Check failure on line 53 in main_test.go

View workflow job for this annotation

GitHub Actions / Lint Check

[golangci-lint] reported by reviewdog 🐶 var-naming: var resetNewUri should be resetNewURI (revive) Raw Output: main_test.go:53:2: var-naming: var resetNewUri should be resetNewURI (revive) resetNewUri := func() { ^
newUri = ""
}

t.Log("\nuri with prefix and auth, and auth supplied in opt.User/Password")
newUri = buildURI(originalPrefixAuthURI, newUser, newPass)
t.Logf("Origin: %s", originalPrefixAuthURI)
t.Logf("Expect: %s", originalPrefixAuthURI)
t.Logf("Result: %s", newUri)
if newUri != originalPrefixAuthURI {
t.Fail()
}
resetNewUri()

t.Log("\nuri with prefix and auth, no auth supplied in opt.User/Password")
newUri = buildURI(originalPrefixAuthURI, "", "")
t.Logf("Origin: %s", originalPrefixAuthURI)
t.Logf("Expect: %s", originalPrefixAuthURI)
t.Logf("Result: %s", newUri)
if newUri != originalPrefixAuthURI {
t.Fail()
}
resetNewUri()

t.Log("\nuri with no prefix and auth, and auth supplied in opt.User/Password")
newUri = buildURI(originalAuthURI, newUser, newPass)
t.Logf("Origin: %s", originalAuthURI)
t.Logf("Expect: %s", originalAuthURI)
t.Logf("Result: %s", newUri)
if newUri != originalAuthURI {
t.Fail()
}
resetNewUri()

t.Log("\nuri with no prefix and auth, no auth supplied in opt.User/Password")
newUri = buildURI(originalAuthURI, "", "")
t.Logf("Origin: %s", originalAuthURI)
t.Logf("Expect: %s", originalAuthURI)
t.Logf("Result: %s", newUri)
if newUri != originalAuthURI {
t.Fail()
}
resetNewUri()

t.Log("\nuri with prefix and no auth, and auth supplied in opt.User/Password")
newUri = buildURI(originalPrefixBareURI, newUser, newPass)
t.Logf("Origin: %s", originalPrefixBareURI)
t.Logf("Expect: %s", changedPrefixAuthURI)
t.Logf("Result: %s", newUri)
if newUri != changedPrefixAuthURI {
t.Fail()
}
resetNewUri()

t.Log("\nuri with prefix and no auth, no auth supplied in opt.User/Password")
newUri = buildURI(originalPrefixBareURI, "", "")
t.Logf("Origin: %s", originalPrefixBareURI)
t.Logf("Expect: %s", originalPrefixBareURI)
t.Logf("Result: %s", newUri)
if newUri != originalPrefixBareURI {
t.Fail()
}
resetNewUri()

t.Log("\nuri with no prefix and no auth, and auth supplied in opt.User/Password")
newUri = buildURI(originalBareURI, newUser, newPass)
t.Logf("Origin: %s", originalBareURI)
t.Logf("Expect: %s", changedPrefixAuthURI)
t.Logf("Result: %s", newUri)
if newUri != changedPrefixAuthURI {
t.Fail()
}
resetNewUri()

t.Log("\nuri with no prefix and no auth, no auth supplied in opt.User/Password")
newUri = buildURI(originalBareURI, "", "")
t.Logf("Origin: %s", originalBareURI)
t.Logf("Expect: %s", originalBareURI)
t.Logf("Result: %s", newUri)
if newUri != originalBareURI {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if newUri != originalBareURI {
if newUri != originalPrefixBareURI {

This is the expected behavior.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i have reorgnized the test code, 24987e4

could you review it again, thanks

t.Fail()
}
resetNewUri()
}
Loading