-
Type: Bug
-
Resolution: Duplicate
-
Priority: Major - P3
-
None
-
Affects Version/s: None
-
Component/s: Authentication
-
None
I'm working on a project that automates MongoDB deployments and then attempts to connect to them to check their status using theĀ replSetGetStatus command. In this particular case the code running in a separate goroutine is:
- Creating a MongoDB Sharded Cluster with MONGODB-SCRAM-SHA-256 authentication
- Creating a user "XXX" with password "YYY"
- Assigning that user the clusterMonitor role
The goroutine that concerns me is the code below, and results in two very strange symptoms:
- The connection status command returns results showing no users nor roles for the current connection, even though they've been provided in the clientOptions:
{"authInfo":{"authenticatedUserRoles":[],"authenticatedUsers":[]},"ok":1}
- The call to replSetGetStatus fails with the error:
Failure on replSetGetStatus command: Err: not authorized on admin to execute command { replSetGetStatus: 1 }
The code (taken out of context)
package main import "fmt" import "encoding/json" import "time" import "context" import "go.mongodb.org/mongo-driver/bson" import "go.mongodb.org/mongo-driver/mongo" import "go.mongodb.org/mongo-driver/mongo/options" import "go.mongodb.org/mongo-driver/mongo/readpref" func main() { credential := options.Credential{ AuthMechanism: "", AuthSource: "admin", Username: "XXX", Password: "YYY", PasswordSet: true, AuthMechanismProperties: nil, } clientOptions := options.ClientOptions{} clientOptions.SetAuth(credential) clientOptions.SetReadPreference(readpref.Nearest()) clientOptions.ApplyURI("mongodb://localhost:28100/?connect=direct") clientOptions.SetConnectTimeout(40 * time.Second) clientOptions.SetServerSelectionTimeout(40 * time.Second) clientOptions.SetSocketTimeout(40 * time.Second) marshalledJson, err := json.Marshal(clientOptions) if err != nil { fmt.Printf("Couldn't serialize clientOptions\n") } else { fmt.Printf("clientOptions: %s\n", string(marshalledJson)) } // time.Sleep(30 * time.Second) client, err := mongo.NewClient(&clientOptions) if err != nil { fmt.Printf("Failure creating new client") return } err = client.Connect(context.TODO()) if err != nil { fmt.Printf("Failure dialing host. Err: `%v`", err) return } admin := client.Database("admin") var connectionStatus bson.M if err := admin.RunCommand(context.Background(), bson.D{{"connectionStatus", 1}}).Decode(&connectionStatus); err != nil { fmt.Printf("Failed to get connectionStatus\n") } marshalledClient, err := json.Marshal(connectionStatus) if err != nil { fmt.Printf("Couldn't serialize the connectionStatus\n") } else { fmt.Printf("After creation Client has connectionStatus %s\n", string(marshalledClient)) } var replSetGetStatus bson.Raw if err := admin.RunCommand(context.Background(), bson.D{{"replSetGetStatus", 1}}).Decode(&replSetGetStatus); err != nil { fmt.Printf("Failure on replSetGetStatus command: Err: %v", err) return } }
The above code succeeds if I uncomment the sleep, which leads me to believe I'm catching an intermediary state in MongoDB that is unhandled.
My major concern here is that the go driver doesn't let me know that authentication has failed at any point, the only thing it does tell me is that I'm not authorized to execute the command I'm trying to execute, and that my connection has no users nor roles associated with it.
Additionally, I've confirmed behavior is not what I'm currently getting if:
- The user I try to authenticate as does not exist but auth has not been enabled for the cluster
- The user I try to authenticate as does not exist but auth has been enabled for the cluster
- The user exists but has not been assigned roles
- The user and roles exist (everything succeeds)
Because of this, I've worked around this issue by checking connectionStatus for a lack of users/roles and using that to decide whether my connection has been successful. But, given that I've provided authentication credentials I'd expect either a different kind of failure from the runCommand command or for connect to fail altogether.
I'm not sure how to help reproduce this issue further but if anyone on the team wants me to reproduce it for them I can consistently do so. I'm also happy to use a modified version of the go driver to get finer grained debugging output.
- duplicates
-
GODRIVER-1090 Authentication fails against Hidden Secondary
- Closed