Skip to content

Commit 9571d21

Browse files
add user and password to uri if the uri does not contain user password (#560)
* add user and password to uri if the uri does not contain user password * improve compatibility * extract whole `buildURI` logic and write a test * add description for MONGODB_USER and MONGODB_PASSWORD in README.md * fix for lint check * make duplications test code simplified * change properties order to make read easier * add back mongodb:// append logic * clean duplicate mongodb:// append logic * try to fix lint * move third party dependency below to internal dependency
1 parent 4aca88d commit 9571d21

File tree

3 files changed

+107
-6
lines changed

3 files changed

+107
-6
lines changed

README.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,25 @@ Connecting user should have sufficient rights to query needed stats:
7171
More info about roles in MongoDB [documentation](https://docs.mongodb.com/manual/reference/built-in-roles/#mongodb-authrole-clusterMonitor).
7272

7373
#### Example
74-
```
74+
```sh
7575
mongodb_exporter_linux_amd64/mongodb_exporter --mongodb.uri=mongodb://127.0.0.1:17001
7676
```
7777

78+
#### MongoDB Authentication
79+
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=`
80+
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
81+
```sh
82+
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
83+
# or
84+
export MONGODB_USER=XXX
85+
export MONGODB_PASSWORD=YYY
86+
mongodb_exporter_linux_amd64/mongodb_exporter --mongodb.uri=mongodb://127.0.0.1:17001 --mongodb.collstats-colls=db1.c1,db2.c2
87+
```
88+
7889
#### Enabling collstats metrics gathering
7990
`--mongodb.collstats-colls` receives a list of databases and collections to monitor using collstats.
8091
Usage example: `--mongodb.collstats-colls=database1.collection1,database2.collection2`
81-
```
92+
```sh
8293
mongodb_exporter_linux_amd64/mongodb_exporter --mongodb.uri=mongodb://127.0.0.1:17001 --mongodb.collstats-colls=db1.c1,db2.c2
8394
```
8495
#### Enabling compatibility mode.

main.go

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ var (
3434

3535
// GlobalFlags has command line flags to configure the exporter.
3636
type GlobalFlags struct {
37+
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"`
38+
Password string `name:"mongodb.password" help:"monitor user password" env:"MONGODB_PASSWORD" placeholder:"monitorPassword"`
3739
CollStatsNamespaces string `name:"mongodb.collstats-colls" help:"List of comma separared databases.collections to get $collStats" placeholder:"db1,db2.col2"`
3840
IndexStatsCollections string `name:"mongodb.indexstats-colls" help:"List of comma separared databases.collections to get $indexStats" placeholder:"db1.col1,db2.col2"`
3941
URI string `name:"mongodb.uri" help:"MongoDB connection URI" env:"MONGODB_URI" placeholder:"mongodb://user:[email protected]:27017/admin?ssl=true"`
@@ -89,6 +91,21 @@ func main() {
8991
e.Run()
9092
}
9193

94+
func buildURI(uri string, user string, password string) string {
95+
// IF user@pass not contained in uri AND custom user and pass supplied in arguments
96+
// DO concat a new uri with user and pass arguments value
97+
if !strings.Contains(uri, "@") && user != "" && password != "" {
98+
// trim mongodb:// prefix to handle user and pass logic
99+
uri = strings.TrimPrefix(uri, "mongodb://")
100+
// add user and pass to the uri
101+
uri = fmt.Sprintf("%s:%s@%s", user, password, uri)
102+
}
103+
if !strings.HasPrefix(uri, "mongodb") {
104+
uri = "mongodb://" + uri
105+
}
106+
return uri
107+
}
108+
92109
func buildExporter(opts GlobalFlags) *exporter.Exporter {
93110
log := logrus.New()
94111

@@ -103,10 +120,7 @@ func buildExporter(opts GlobalFlags) *exporter.Exporter {
103120

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

106-
if !strings.HasPrefix(opts.URI, "mongodb") {
107-
log.Debugf("Prepending mongodb:// to the URI")
108-
opts.URI = "mongodb://" + opts.URI
109-
}
123+
opts.URI = buildURI(opts.URI, opts.User, opts.Password)
110124

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

main_test.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ package main
1717

1818
import (
1919
"testing"
20+
21+
"github.com/stretchr/testify/assert"
2022
)
2123

2224
func TestBuildExporter(t *testing.T) {
@@ -37,3 +39,77 @@ func TestBuildExporter(t *testing.T) {
3739

3840
buildExporter(opts)
3941
}
42+
43+
func TestBuildURI(t *testing.T) {
44+
tests := []struct {
45+
situation string
46+
origin string
47+
newUser string
48+
newPassword string
49+
expect string
50+
}{
51+
{
52+
situation: "uri with prefix and auth, and auth supplied in opt.User/Password",
53+
origin: "mongodb://usr:[email protected]",
54+
newUser: "xxx",
55+
newPassword: "yyy",
56+
expect: "mongodb://usr:[email protected]",
57+
},
58+
{
59+
situation: "uri with prefix and auth, no auth supplied in opt.User/Password",
60+
origin: "mongodb://usr:[email protected]",
61+
newUser: "",
62+
newPassword: "",
63+
expect: "mongodb://usr:[email protected]",
64+
},
65+
{
66+
situation: "uri with no prefix and auth, and auth supplied in opt.User/Password",
67+
origin: "usr:[email protected]",
68+
newUser: "xxx",
69+
newPassword: "yyy",
70+
expect: "mongodb://usr:[email protected]",
71+
},
72+
{
73+
situation: "uri with no prefix and auth, no auth supplied in opt.User/Password",
74+
origin: "usr:[email protected]",
75+
newUser: "",
76+
newPassword: "",
77+
expect: "mongodb://usr:[email protected]",
78+
},
79+
{
80+
situation: "uri with prefix and no auth, and auth supplied in opt.User/Password",
81+
origin: "mongodb://127.0.0.1",
82+
newUser: "xxx",
83+
newPassword: "yyy",
84+
expect: "mongodb://xxx:[email protected]",
85+
},
86+
{
87+
situation: "uri with prefix and no auth, no auth supplied in opt.User/Password",
88+
origin: "mongodb://127.0.0.1",
89+
newUser: "",
90+
newPassword: "",
91+
expect: "mongodb://127.0.0.1",
92+
},
93+
{
94+
situation: "uri with no prefix and no auth, and auth supplied in opt.User/Password",
95+
origin: "127.0.0.1",
96+
newUser: "xxx",
97+
newPassword: "yyy",
98+
expect: "mongodb://xxx:[email protected]",
99+
},
100+
{
101+
situation: "uri with no prefix and no auth, no auth supplied in opt.User/Password",
102+
origin: "127.0.0.1",
103+
newUser: "",
104+
newPassword: "",
105+
expect: "mongodb://127.0.0.1",
106+
},
107+
}
108+
for _, tc := range tests {
109+
newUri := buildURI(tc.origin, tc.newUser, tc.newPassword)
110+
// t.Logf("Origin: %s", tc.origin)
111+
// t.Logf("Expect: %s", tc.expect)
112+
// t.Logf("Result: %s", newUri)
113+
assert.Equal(t, newUri, tc.expect)
114+
}
115+
}

0 commit comments

Comments
 (0)