I have 3 databases in my MongoDB server. I am using pymongo to do some scripting with Python3.
I want to use the latest versions and practices. Once I open the client and pick the database, the API for pymongo.MongoClient.['mydatabase'].authenticate is deprecated. https://api.mongodb.com/python/current/api/pymongo/database.html
Authentication prior to picking the database (while dialing the client) doesn't seem to flow down toward the database. Not just for pymongo, but also when I use mongo shell. So I have a feeling this is the issue.
script.py
import pymongo
from pymongo import MongoClient
u = getUser() # function which prompts for username
p = getPassword() # getpass.getpass('Password')
uri = formatUri(u, p) # formats 'mongodb://%s:%s@%s'.format(user, password, host)
client = MongoClient(uri)
db = client['mydb']
col = db.mycollection
for doc in col.find():
print(doc)
I get the error that I am not authorized for the database. I know my account works in shell but I have to dial the client first then use the db and then auth.
Here's a mongo shell example:
$ mongo
MongoDB shell version: v3.4.10
Connecting to: mongodb://127.0.0.1:port
MongoDB server version: v3.4.10
> use mydb
switched to mydb
> db.auth("user", "pass")
1
Any idea how I can either auth after picking the database or once I use the db it remembers the context I dialed with?
You seem to be missing some concepts here so I'll basically answer as a "guide" to what you should be doing instead. So "authentication' is not really something you do "after" connection, but rather you need to be "looking in the right place" when you actually attempt to authenticate.
We can start this by essentially following the process outlined in Enable Auth from the core documentation, but specifically altered because you want to be running this "test" under your own user account and local directory.
Revision Steps - Straight from Documentation
So first would would want to pick a local working directory and make a path for the database storage files underneath that. On *nix based systems you can do something like:
Then we want to startup a separate MongoDB instance without any other options. Making sure the port does not conflict with any other running instance:
In a new terminal or command line window, you can then connect to the shell:
You always want at least one account with administrative privileges to at least "create accounts" and alter them in case you get in trouble, so create one:
Now exit the shell and close the existing
mongod
instance running in the other terminal or command prompt and then start it again using--auth
:Specific User - Make sure you follow these
Now you actually want to create a user that will be "used by your application". So these steps are important to ensure you get it right.
Log into a shell using your "adminstrative user":
You can alternately do the
db.auth()
method as shown in the question, but as noted this must be authorised on the"admin"
namespace.The next thing you want to do is create a user with access to
"mydb"
as a namespace with thereadWrite
role. For kicks, we are also going to let this user have thereadAnyDatabase
allowing them to "list" all databases namespaces, if not actually being able to do anything else with them.Just for additional output, let's look at the current created users:
See how these have expanded in naming, and particularly the values assigned to the various
"db"
keys on each user. This should give you a little more insight into how MongoDB looks this up and why.Python Connection
Finally we just want to connect from python. So presuming you have python and pymongo installed already, then it's just a simple listing to verify:
Which shows the document created and listed without problem:
Note that we don't actually need to make any mention of
"admin"
here, because this is the default where the driver "expects the accounts to be" and where you really "should" be doing it.But I did it the wrong way
So let's say you originally got all confused and created the user under
"mydb"
instead:If you go look in
"admin"
that user is not there. But if you look on"mydb"
:So you can see where the actual user data is now kept and how it has been recorded.
The simple case here is you "must" tell MongoDB where to obtain the authentication from for this user:
See how we add
"mydb"
on to the connection string. This is how it's done.This is actually "in progress" to be made consistent with ALL drivers in how connections are made and where authentication happens as well as where you select the database. But there are basic rules:
If no other database namespace is provided with connection details for authentication credentials, then
"admin"
is taken to be the default.Where there is a database namespace provided on the connection string, this will be used for authentication and this is the actual intent of the database namespace on the connection string.
Though other drivers "presently" differ in the role of the database namespace on the connection string, the usage is being changed to be consistent with all drivers that "using" a database namespace is in fact an API call, rather than being assigned from the connection string.
So where you need to authenticate depends on "where you created the user". But you should really be noting that
"admin"
is the place where you "should" be doing this instead of anywhere else.