Connect mongodb from Python in authorized mode - python

I've created a user for my database in mongodb. I've tested with mongo shell to make sure that the user has proper privileges to access the database.
Now I want to use my Python program to access the database, and I use PyMongo. If I run mongod in unauthorized mode (without option --auth), the Python client works fine. However, when I use --auth option, the Python client doesn't work any more. In fact, it reports unauthorized error, which is easy to understand because I didn't change anything in the code. Here is the code to connect my test database:
from pymongo import MongoClient
client = MongoClient()
db = client.test
cursor = db.restaurants.find()
for document in cursor:
print(document)
My question is how can I change the Python code to use username/password created previously? I've looked at the client documentation but there is not information for it.

client = MongoClient("mongodb://username:password#server/dbname")
This is the normal format for telling the client where and how to connect. The way you are using (with no parameters at all) defaults to a local mongo install, on the default port, with no authentication.

Besides Danielle's answer you can also use authenticate method for that. Your code would look like this:
from pymongo
import MongoClient
client = MongoClient()
db = client.test
db.authenticate('user', 'password', mechanism=<either 'SCRAM-SHA-1' or 'MONGODB-CR', being 'MONGODB-CR' the default authentication mechanism Before MongoDB 3.0>)
cursor = db.restaurants.find()
for document in cursor:
print(document)

Related

SQL Login Failed [2800] with Windows Authentication Only when Using pyodbc, and Only for Certain Databases

Thank you for taking the time to look at my question!
I have a class ODBCSources which returns a SQLAlchemy/pyodbc engine for use with pretty much anything you could want it for. While logged in as a user with database editing permissions and using windows authentication, the code works for some databases on myserver.mycompany.local but not one database in particular. The problem database was created a week or so ago vs years ago for the ones that I can connect to with pyodbc. As the same user, I am able to log into the all of the databases using windows authentication + SSMS, Azure Data Studio, and/or DataGrip.
My code works for other databases on the same server, so I don't think the issue is with my connection string (But, the connection string must have a database name component, not an ODBC name component -- See my answer below). Additionally, the MS ODBC Data Source Administrator gives the feel good 'TESTS COMPLETED SUCCESSFULLY!' message when I test the connection corresponding to the problem database.
Is there a SQL-Server setting that I need to enable to allow python connections to the problem database? (No -- See my answer below)
import getpass
import pyodbc
from sqlalchemy import create_engine
class ODBCSources():
"""
A class to return sql alchemy engine for use in something like `pd.to_sql`
"""
def __init__(self, login = False):
self.sources = pyodbc.dataSources().keys()
self.login = login
self.user = ""
self.pwd = ""
def make_engine(self, odbc_source, driver = 'ODBC Driver 17 for SQL Server'):
if odbc_source not in self.sources:
raise ValueError(f'{odbc_source} is not available.\nAvailable Sources: {self.sources}')
else:
if self.login:
# This just gets the currently logged in user. Not really much more flexible
# than windows auth, but I'm not concerned with this
user = getpass.getuser()
pwd = getpass.getpass()
engine = create_engine(f'mssql+pyodbc://{user}:{pwd}#myserver.mycompany.local/{odbc_source}?driver={driver}', echo = False)
else:
user = self.user
pwd = self.pwd
engine = create_engine(f'mssql+pyodbc://{user}:{pwd}#myserver.mycompany.local/{odbc_source}?driver={driver}', echo = False)
return engine
I resolved the issue by creating a new ODBC datasource having a the same name as my database . . . which was really not necessary at all, but led me to the root cause root cause of my issue: my connection string is suitable for connection via database names, not ODBC names.
It so happened that in the past I created all of my ODBC connections with the same name as their corresponding database, so I was able to get by thinking that my connection string in create_engine had an ODBC component (it does not), because I was actually entering correct database names.

PyMongo authentication with docker

I'm having some problems to authenticate a newly created user in MongoDB. My setup is the MongoDB 4.4.2 in a container and python 3.8.
I have created a user as follows:
from pymongo import MongoClient
host = "mongodb://root_user:root_password#172.20.0.3:27017"
DB_NAME = "test"
client = MongoClient(host)
test_db = client[DB_NAME]
test_db.command("createUser", "TestUser", pwd="TestPwd", roles=["readWrite"])
So far, so good: I simply added the TestUser to the database test, and so I see when I query the collection client.system.users.find({'user': 'TestUser'}), I get the test user with db: test.
Now if I want to test this user connection with
host = "mongodb://TestUser:testPwd#172.20.0.3:27017"
it shows an authentication failure: pymongo.errors.OperationFailure: Authentication failed.
I can connect via the shell inside the container but not via pymongo and I tried already to connect specifying the authentication method, the authentication database and neither worked so far.
Any hints would be much appreciated!
Two issues.
As the commenter notes, you are creating the user in the test database; by default MongoDB will look for credentials in the admin database if authSource is not specified. Therefore you will need to append /<optional database name>?authSource=test to your connection string.
You create your account with password TestPwd, but on the connection string you have testPwd; so this won't authenticate.
So, assuming your password is definitely TestPwd, your connection string should be:
mongodb://TestUser:TestPwd#172.20.0.3:27017/test?authSource=test

How to pass variable values for oracle connection in python

Im able to connect to Oracle Db successfully when i hardcode the Db details like " connection = cx_Oracle.connect("uname/pass#192.168.xxx.yyy:port/db")" but how to pass the variable values to connect to the db?
I tried some like this.
connection = cx_Oracle.connect("{}/{}#{}:{}/{}".format(uname,password,IP,port,db))
which is not working as expected so please share some thought on this to make it work.
def knowcobrand(request):
value_type = request.POST.get('CobranSelection')
cobrand_value = request.POST.get('cobrand')
env = request.POST.get('NewEnvName')
print(value_type)
print(cobrand_value)
print(env)
# feed = Environments.objects.get(Q(Env_name__icontains=env))
# print(feed.user_name)
connection = cx_Oracle.connect("app/app#192.168.xxx.yy:port/db")
I want to use the variable's value of value_type and env for Db connection
EDIT: You should probably run through the Django tutorial, it will explain the basics of Django and using the ORM
You should configure your database connection in your settings
There is a specific example for oracle
You can now use the Django ORM (after running migrations)
If you want a raw cursor for the database you can still use Django for this like so
from django.db import connection
with connection.cursor() as c:
c.execute(...)

How to login to mongodb(through pymongo) remotely and get output of db.serverStatus()

How to connect to a mongodb host remotely by specifying Username, Password, Hostname and also how to get db.serverStatus() output through pymongo ???
"I have commented the bind_ip in **mongod.conf* file, so that it allows remote connection"
import pymongo
from pymongo import MongoClient
connection=MongoClient(???)
Following is a sample code:
import pymongo
MONGO_HOST = ''
MONGO_PORT = <PORT>
MONGO_DB=''
MONGO_USER=''
MONGO_PASS=''
def get_mongo_db():
con=pymongo.Connection(MONGO_HOST,MONGO_PORT)
db=con[MONGO_DB]
try:
db.authenticate(MONGO_USER,MONGO_PASS)
except:
return None
return db
Attention, if your mongo doesn't open auth (--auth), you needn't to auth, but it's recommended to open auth for security.
then, you can use db for more ops, as you said, db.serverStatus() (I haven't tried, maybe a little different)

Connecting to MongoHQ from heroku console (heroku run python)

I'm getting a 'need to login' error when trying to interact with my MongoHQ database through python console on heroku:
...
File "/app/.heroku/venv/lib/python2.7/site-packages/pymongo/helpers.py", line 128, in _check_command_response
raise OperationFailure(msg % response["errmsg"])
pymongo.errors.OperationFailure: command SON([('listDatabases', 1)]) failed: need to login
My applicable code
app/init.py:
from mongoengine import connect
import settings
db = connect(settings.DB, host=settings.DB_HOST, port=settings.DB_PORT, username=settings.DB_USER, password=settings.DB_PASS)
app/settings.py:
if 'MONGOHQ_URL' in os.environ:
url = urlparse(os.environ['MONGOHQ_URL'])
DB = url.path[1:]
DB_HOST = url.hostname
DB_PORT = url.port
DB_USER = url.username
DB_PASS = url.password
os.environ['MONGOHQ_URL'] looks like:
'mongodb://[username]:[password]#[host]:[port]/[db-name]'
This code works (connects and can read and write to mongodb) both locally and from the heroku web server.
According to the docs (http://www.mongodb.org/display/DOCS/Connections), it should at make a 'login' attempt on connection to the server as long as the username and password params are passed to Connection or parseable from the URI. I couldn't think of a way to see if the login attempt was being made and failing silently.
I've tried bypassing mongoengine and using pymongo.Connection and got the same result. I tried all of the several patterns of using the Connection method. I created a new database user, different from the one mongoHQ creates for heroku's production access -> same same.
It's a flask app, but I don't think any app code is being touched.
Update
I found a solution, but it will cause some headaches. I can manually connect to the database by
conn = connect(settings.DB, host=settings.DB_HOST, port=settings.DB_PORT, username=settings.DB_USER, password=settings.DB_PASS)
db = conn[settings.DB]
db.authenticate(settings.DB_USER, settings.DB_PASS)
Update #2
Mongolab just worked out of the box.
Please use the URI method for connecting and pass the information to via the host kwarg eg:
connect("testdb_uri", host='mongodb://username:password#localhost/mongoenginetest')
MongoHQ add-on uses password hashes not actual passwords and that's perhaps the error.
You should change the environment variable MONGOHQ_URL to a real password with the following command:
heroku config:set MONGOHQ_URL=mongodb://...
Once set, you may restart your applications (heroku apps) so the change gets picked up. If you're in the directory of the failing application, config:seting the config var will restart the application.

Categories

Resources