Skip to content

Commit 8c69fa4

Browse files
authored
PMM-9320: fix auth creds (#497)
1 parent 7b4692b commit 8c69fa4

File tree

3 files changed

+113
-2
lines changed

3 files changed

+113
-2
lines changed

exporter/dsn_fix/dsn_fix.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// mongodb_exporter
2+
// Copyright (C) 2017 Percona LLC
3+
//
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Affero General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Affero General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Affero General Public License
15+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
17+
package dsn_fix
18+
19+
import (
20+
"net/url"
21+
22+
"github.com/pkg/errors"
23+
"go.mongodb.org/mongo-driver/mongo/options"
24+
)
25+
26+
// ClientOptionsForDSN applies URI to Client.
27+
func ClientOptionsForDSN(dsn string) (*options.ClientOptions, error) {
28+
clientOptions := options.Client().ApplyURI(dsn)
29+
30+
// Workaround for PMM-9320
31+
// if username or password is set, need to replace it with correctly parsed credentials.
32+
parsedDsn, err := url.Parse(dsn)
33+
if err != nil {
34+
return nil, errors.Wrap(err, "cannot parse DSN")
35+
}
36+
username := parsedDsn.User.Username()
37+
password, _ := parsedDsn.User.Password()
38+
if username != "" || password != "" {
39+
clientOptions = clientOptions.SetAuth(options.Credential{Username: username, Password: password})
40+
}
41+
42+
return clientOptions, nil
43+
}

exporter/dsn_fix/dsn_fix_test.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// mongodb_exporter
2+
// Copyright (C) 2017 Percona LLC
3+
//
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Affero General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Affero General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Affero General Public License
15+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
17+
package dsn_fix
18+
19+
import (
20+
"net/url"
21+
"testing"
22+
23+
"github.com/stretchr/testify/assert"
24+
)
25+
26+
func TestClientOptionsForDSN(t *testing.T) {
27+
tests := []struct {
28+
name string
29+
dsn string
30+
expectedUser string
31+
expectedPassword string
32+
}{
33+
{
34+
name: "Escape username",
35+
dsn: (&url.URL{
36+
Scheme: "mongo",
37+
Host: "localhost",
38+
Path: "/db",
39+
User: url.UserPassword("user+", "pass"),
40+
}).String(),
41+
expectedUser: "user+",
42+
expectedPassword: "pass",
43+
},
44+
{
45+
name: "Escape password",
46+
dsn: (&url.URL{
47+
Scheme: "mongo",
48+
Host: "localhost",
49+
Path: "/db",
50+
User: url.UserPassword("user", "pass+"),
51+
}).String(),
52+
expectedUser: "user",
53+
expectedPassword: "pass+",
54+
},
55+
}
56+
for _, tt := range tests {
57+
t.Run(tt.name, func(t *testing.T) {
58+
got, err := ClientOptionsForDSN(tt.dsn)
59+
assert.Nil(t, err)
60+
assert.Equal(t, got.Auth.Username, tt.expectedUser)
61+
assert.Equal(t, got.Auth.Password, tt.expectedPassword)
62+
})
63+
}
64+
}

exporter/exporter.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ import (
3333
"github.com/prometheus/exporter-toolkit/web"
3434
"github.com/sirupsen/logrus"
3535
"go.mongodb.org/mongo-driver/mongo"
36-
"go.mongodb.org/mongo-driver/mongo/options"
36+
37+
"github.com/percona/mongodb_exporter/exporter/dsn_fix"
3738
)
3839

3940
// Exporter holds Exporter methods and attributes.
@@ -338,7 +339,10 @@ func (e *Exporter) Run() {
338339
}
339340

340341
func connect(ctx context.Context, dsn string, directConnect bool) (*mongo.Client, error) {
341-
clientOpts := options.Client().ApplyURI(dsn)
342+
clientOpts, err := dsn_fix.ClientOptionsForDSN(dsn)
343+
if err != nil {
344+
return nil, fmt.Errorf("invalid dsn: %w", err)
345+
}
342346
clientOpts.SetDirect(directConnect)
343347
clientOpts.SetAppName("mongodb_exporter")
344348

0 commit comments

Comments
 (0)