add user to mongodb via python - python

I want to be able to add users to MongoDB so that we can automate MongoDB installs with authentication already baked in. I can successfully add users using pymongo that are read only or are dbOwner by doing this:
from pymongo import MongoClient
client = MongoClient('localhost:27017')
client.admin.authenticate('siteRootAdmin', 'Test123')
client.testdb.add_user('newTestUser', 'Test123', True)
but when I do this following code block to specify roles, it fails:
from pymongo import MongoClient
client = MongoClient('localhost:27017')
client.admin.authenticate('siteRootAdmin', 'Test123')
client.testdb.add_user('newTestUser', 'Test123', False, 'readWrite')
with the error:
line 10, in <module>
client.admin.add_user('newTestUser', 'Test123', False, 'readWrite')
TypeError: add_user() takes at most 4 arguments (5 given)
In the docs it implies that you are able to have optional fields for the user document such as other roles. Has anyone been able to set these correctly? Namely, I want to have readWrite service accounts that can add data to collections but don't have full dbOwner privileges.

Here is the workaround:
client.testdb.add_user('newTestUser', 'Test123', roles=[{'role':'readWrite','db':'testdb'}])
Note: as you're going to set "roles", should leave the 3rd argument (read_only) empty.

Starting from version 3 add_user is deprecated and will be removed in later versions. It cause following warning when called:
DeprecationWarning: add_user is deprecated and will be removed in PyMongo 4.0. Use db.command with createUser or updateUser instead
Above code might be rewritten to
client.testdb.command(
'createUser', 'newTestUser',
pwd='Test123',
roles=[{'role': 'readWrite', 'db': 'testdb'}]
)

Related

PyMongo's insert_one() method not working using PyCharm IDE

I'm trying to use mongodb but for some reason i cant put data into a collection.
Here's my code:
import pymongo
from pymongo import MongoClient
mongo_url = "mongodb+srv://<User>:<Password>#cluster0.yozx6.mongodb.net/<dbname>?retryWrites=true&w=majority"
cluster = MongoClient(mongo_url)
db = cluster["TestDatabse"]
collection = db["TestCollection"]
post = {"number": 7}
collection.insert_one(post)
for some reason the data the collection.insert_one line isn't working and it isn't giving an error message either. The program seems to get stuck on it. Can somebody please tell me what I'm doing wrong and how I can fix it.
There are different things to verify for you.
Version compatibility:
First of all insertOne was introduced inmongoDB 3.2, so make sure that you are connecting to a newer pymongo version, and also that the version of pymongo is compatible with your version
Network connection:
Make sure you have a stable connection to your DB if it is remote.
Then use:
result = cluster.admin.command("ismaster")
to check if the db is accesible, if this throws a ConnectionError there is a problem with the connection.
User permissions
Check if the user and password you are using has permissions to insert documents to the given collection.
On the mongo shell:
db.getRoles(
{
rolesInfo: 1,
showPrivileges:true,
showBuiltinRoles: true
}
)
should show:
roles: [
{
role: "readWrite",
db: "TestDatabse"
}
]
for the user User.
Result of insert
Check the result. insert_one returns inserted_id and acknowledged.
res = collection.insert_one(post)
res.acknowledged # should be True
res.inserted_id
Logs
Check your logs, you can find the log path for your server by running:
cat /etc/mongod.conf | grep log

Configuring sqlalchemy engine with user containing ":"

I am trying to configure an engine in sqlalchemy to connect with temporary credentials from an AWS IAM role using get_cluster_credentials api.
When I do so this is the user I get 'IAM:user_rw'. Problem comes when I configure the engine string as
engine_string = "postgresql+pygresql://{user}:{password}#{endpoint}:{port}/{dbname}".format(
user=cluster_creds['DbUser'],
password=cluster_creds['DbPassword'],
endpoint='big endpointstring',
port=8192,
dbname='small dbname')
I create the engine without errors but when running any query I get: FATAL: password authentication failed for user "IAM"
Tested the user and pass in DataGrip it works so it seems evident sqlalchemy is getting the user just as "IAM" instead of 'IAM:user_rw'.
Do you know how can I force sqlalchemy to get the correct user?
I managed to solve the issue using urllib parse_quote in a similar fashion to what Gord is pointing. Final code
from urllib.parse import quote_plus
engine_string = "postgresql+pygresql://%s:%s#%s:%d/%s" % (
quote_plus(user),
quote_plus(passw),
endpoint,
port,
dbname,
)

MongoDB Atlas authentication failed on Python

I have deployed this Python app on Heroku and i want it to connect to a MongoDB Atlas cluster. I used my string to connect to the cluster, but for some reason i keep getting raise OperationFailure(msg % errmsg, code, response)
pymongo.errors.OperationFailure: bad auth Authentication failed. I checked twice and both the user and the password are correct. Any idea on why this is happening?
from pymongo import MongoClient
import time
import random
import time
import datetime
client = MongoClient('mongodb+srv://USER:<MYPASSWORD>#test-2liju.mongodb.net/test?retryWrites=true')
db = client.one
mycol = client["tst"]
while True:
test = int(random.randrange(-99999990,90000000,1))
dic = {"num": test}
result = db.tst.insert_one(dic)
print(test)
time.sleep(5)
Stupid error, i had to type MYPASSWORD instead of <MYPASSWORD>, without the <>
Don't use any special char in password, like '+' or '='.
I use OpenSSL to generate a password like u4wY9AOwnOLMY+h9EQ==. Came across bad auth Authentication failed.
After using MongoDB Compass it told me don't use special char, so I remove those and use like 'u4wY9AOwnOLMYh9EQ'.
Then it works.
check the compatibility of the version of the Python driver you choose from the Mongodb Atlas Connections. versions above 3.4 are not supported by mongoengine flask

Blob.generate_signed_url() failing to AttributeError

So I'm trying to produce temporary globally readable URLs for my Google Cloud Storage objects using the google-cloud-storage Python library (https://googlecloudplatform.github.io/google-cloud-python/latest/storage/blobs.html) - more specifically the Blob.generate_signed_url() method. I doing this from within a Compute Engine instance in a command line Python script. And I keep getting the following error:
AttributeError: you need a private key to sign credentials.the credentials you are currently using <class 'oauth2cl
ient.service_account.ServiceAccountCredentials'> just contains a token. see https://google-cloud-python.readthedocs
.io/en/latest/core/auth.html?highlight=authentication#setting-up-a-service-account for more details.
I am aware that there are issues with doing this from within GCE (https://github.com/GoogleCloudPlatform/google-auth-library-python/issues/50) but I have created a new Service Account credentials following the instructions here: https://cloud.google.com/storage/docs/access-control/create-signed-urls-program and my key.json file most certainly includes a private key. Still I am seeing that error.
This is my code:
keyfile = "/path/to/my/key.json"
credentials = ServiceAccountCredentials.from_json_keyfile_name(keyfile)
expiration = timedelta(3) # valid for 3 days
url = blob.generate_signed_url(expiration, method="GET",
credentials=credentials)
I've read through the issue tracker here https://github.com/GoogleCloudPlatform/google-cloud-python/issues?page=2&q=is%3Aissue+is%3Aopen and nothing related jumps out so I am assuming this should work. Cannot see what's going wrong here.
I was having the same issue. Ended up fixing it by starting the storage client directly from the service account json.
storage_client = storage.Client.from_service_account_json('path_to_service_account_key.json')
I know I'm late to the party but hopefully this helps!
Currently, it's not possible to use blob.generate_signed_url without explicitly referencing credentials. (Source: Google-Cloud-Python documentation) However, you can do a workaround, as seen here, which consists of:
signing_credentials = compute_engine.IDTokenCredentials(
auth_request,
"",
service_account_email=credentials.service_account_email
)
signed_url = signed_blob_path.generate_signed_url(
expires_at_ms,
credentials=signing_credentials,
version="v4"
)
A much complete snippet for those asking where other elements come from. cc #AlbertoVitoriano
from google.auth.transport import requests
from google.auth import default, compute_engine
credentials, _ = default()
# then within your abstraction
auth_request = requests.Request()
credentials.refresh(auth_request)
signing_credentials = compute_engine.IDTokenCredentials(
auth_request,
"",
service_account_email=credentials.service_account_email
)
signed_url = signed_blob_path.generate_signed_url(
expires_at_ms,
credentials=signing_credentials,
version="v4"
)

Mongodb authentication issue

I am new to mongodb and I am trying to connect it remotely (from my local system to live db) and it is connected successfully. I have admin users in admin table and want that without authentication no one can access my database. But when I try to connect Mongodb remotely via the below mention code , even without authentication i can access any db :
from pymongo import MongoClient, Connection
c = MongoClient('myip',27017)
a = c.mydb.testData.find()
In my config file , the parameter auth is set to True , auth = True . But still no authentication is needed to access my db . Please can anyone let me know what I am missing here.
Based on your description I would guess you haven't actually enabled authentication. In order to enable authentication you must start the Mongo server with certain settings. You can find more information below:
http://docs.mongodb.org/manual/tutorial/enable-authentication/
Basically you need to run with --auth in order to enable authentication.

Categories