2

I have this user in MongoDB

{ 
"_id" : "xxx", 
"userId" : UUID("xxx"), 
"user" : "user", 
"db" : "db", 
"roles" : [
    {
        "role" : "dbOwner", 
        "db" : "db"
    }, 
    {
        "role" : "readWrite", 
        "db" : "db"
    }
], 
"mechanisms" : [
    "SCRAM-SHA-1", 
    "SCRAM-SHA-256"
]
}

and this is my connection string

Connection_string= 'mongodb://user:password@cluster:111111/db?ssl=false&connectTimeoutMS=10000&authSource=db&authMechanism=SCRAM-SHA-1'

When I am using this connection string in the Studio 3T, I have no issues querying data. However, when I try to use it in pymongo I am getting an error. This is my code

from pymongo import MongoClient

client = MongoClient(Connection_string)
db=client.db
collection = db.collection_name
coursor= collection.find({})

for r in coursor:
    print (r)

And this is an error message

OperationFailure: not authorized on db to execute command { find: "collection_name", filter: {}, lsid: { id: UUID("xx") }, $clusterTime: { clusterTime: Timestamp(1654866078, 1), signature: { hash: BinData(0, xx), keyId: xx} }, $db: "db" }, full error: {'operationTime': Timestamp(1654866078, 1), 'ok': 0.0, 'errmsg': 'not authorized on db to execute command { find: "collection_name", filter: {}, lsid: { id: UUID("xx") }, $clusterTime: { clusterTime: Timestamp(1654866078, 1), signature: { hash: BinData(0, xx), keyId: xx} }, $db: "db" }', 'code': 13, 'codeName': 'Unauthorized', '$clusterTime': {'clusterTime': Timestamp(1654866078, 1), 'signature': {'hash': b'xxxx', 'keyId': xx}}}

I was checking some threads regarding this issue in StackOverflow, however, non of them suit my situation. I want to query only the DB in which the user I am using is created

jedrek
  • 41
  • 1
  • 1
  • 10
  • User is created in database `db`, however you gave `authSource=OSCAR`. See https://stackoverflow.com/questions/63754742/authentication-failure-while-trying-to-save-to-mongodb/63755470#63755470 – Wernfried Domscheit Jun 10 '22 at 14:32
  • Does this answer your question? [Authentication failure while trying to save to mongodb](https://stackoverflow.com/questions/63754742/authentication-failure-while-trying-to-save-to-mongodb) – Wernfried Domscheit Jun 10 '22 at 14:32
  • @WernfriedDomscheit: thanks for the answer. I have changed authSource to db, however it is still giving the same error – jedrek Jun 11 '22 at 11:44
  • Maybe database name `db` is not so smart, because `db` it is a pre-defined object in MongoDB. Usually you can skip `authMechanism=...`. Does it work, when you run the same command from mongo shell? – Wernfried Domscheit Jun 11 '22 at 12:05
  • @WernfriedDomscheit I am not using `db` as a name in real case, it is just the name I created to show in this example to make sure I will not reveal any sensitive information. In real case scenarion I am using different namefor database and it is consistent between the database in which user is created, databases defined for roles, and in the connection string. I have used the same connection string and commands in studio 3t and everything was working correctly. I will check if omiting `authMechanism=..` works on Monday, as I don't have access to environment right now. – jedrek Jun 11 '22 at 12:25
  • You write "databases defined for roles". Where did you create the roles? Typically roles and users are created in `admin` database (actually I don't know any reason why they should be created anywhere else). `dbOwner` and `readWrite` are [Built-In Roles](https://www.mongodb.com/docs/v5.0/reference/built-in-roles/), you don't need to create them. – Wernfried Domscheit Jun 11 '22 at 13:52
  • Does the password has any characters you need to escape? See [Standard Connection String Format](https://www.mongodb.com/docs/v5.0/reference/connection-string/#examples) – Wernfried Domscheit Jun 11 '22 at 13:56
  • @WernfriedDomscheit I am not an admin of this server, I have only got access to this one user. I meant that, when I find information about this user in server, these roles and db are within the same bracket, so I assumed they are connected `{"role" : "dbOwner", "db" : "db"}` I assume these roles where not created, but are Built-in roles. I have no characters I need to escape in password. – jedrek Jun 11 '22 at 15:05
  • 1
    Just a note, role `dbOwner` includes `readWrite`, i.e. `readWrite` is redundant. – Wernfried Domscheit Jun 11 '22 at 19:07
  • @WernfriedDomscheit I have removed `authMechanism=..` from the connection string. I have also tried Connection_string= `mongodb://user:password@cluster:111111/db` to make sure there are no unnecessary characters. When I run this `db.collection_name.find({})` In Mongo shell everything works fine. My mongodb is on-premise, maybe this information helps. DO you have any other ideas why it is not working for Python? – jedrek Jun 13 '22 at 05:28
  • Does it work from mongo shell? – Wernfried Domscheit Jun 13 '22 at 05:58
  • @WernfriedDomscheit Yes, I have used the connection string `mongodb://user:password@cluster:111111/db` and `db.collection_name.find({})` command in Mongosh. It works there – jedrek Jun 13 '22 at 07:23
  • @WernfriedDomscheit do you have any ideas what more could I do? – jedrek Jun 14 '22 at 06:20
  • Apart from any typo - not really. Maybe ask for [listCollections](https://www.mongodb.com/docs/v5.0/reference/privilege-actions/#mongodb-authaction-listCollections), [listDatabases](https://www.mongodb.com/docs/v5.0/reference/privilege-actions/#mongodb-authaction-listDatabases) or [clusterMonitor](https://www.mongodb.com/docs/v5.0/reference/built-in-roles/#mongodb-authrole-clusterMonitor) – Wernfried Domscheit Jun 14 '22 at 06:50

1 Answers1

0

I have found an answer. I don't really know what is a difference, but in my case I had to create a function to get cursor.

def get_database():

    from pymongo import MongoClient
    import pymongo

    # Provide the mongodb url to connect python to mongodb using pymongo
    CONNECTION_STRING = "mongodb://user:password@cluster:111111/db?ssl=true&connectTimeoutMS=10000&authSource=db&authMechanism=SCRAM-SHA-1"

    # Create a connection using MongoClient. 
    from pymongo import MongoClient
    client = MongoClient(CONNECTION_STRING)

    # Create the database
    return client['db']

and afterwads use this funcion to create cursor

dbname = get_database()

collection_name = dbname["collection_name"]

item_details = collection_name.find(condition)
for item in item_details:
    print(item)

Using this method everything works fine.

jedrek
  • 41
  • 1
  • 1
  • 10