ODBC connection to Azure using ActiveDirectoryInteractive - python

I am connecting to an Azure SQL database using pyodcb. We have multi-factor authentication enabled, so I am using ActiveDirectoryInteractive authentication. We also use single sign-on for Windows.
My code is as follows:
import pyodbc
driver = '{ODBC Driver 17 for SQL Server}'
server = 'xxxxxxxxxxxxx.database.windows.net'
database = 'xxxxxxxxxxxxx'
authentication = 'ActiveDirectoryInteractive'
username = 'xxxxxxxxxxxxx'
conn = pyodbc.connect(
'DRIVER=' + driver + ';' +
'SERVER=' + server + ';' +
'DATABASE=' + database + ';' +
'UID=' + username + ';' +
'AUTHENTICATION=' + authentication + ';')
cursor = conn.cursor()
When I run the script I get pop-ups to submit my password and MFA details. But the connection works whether I fill in these details or just close the prompts - suggesting that single sign-on is working successfully. So why am I getting the password and MFA pop-ups - and how can I suppress them?

I'm not sure if this will disable it in Office 365, but if you want to disable MFA for users in Azure ad, I think the easiest way is to disable it directly in the portal.

Related

Login to Azure SQL with JWT token in python - [SQL Server]Login failed for user '<token-identified principal>

I try to connect to Azure SQL using SQLAlchemy in python, authenticating with JWT generated for App registration. Despite checking almost any combination of parameters and granting all potentially meaningful permissions, I still get following error:
[28000] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Login failed for user ''. (18456)
I did the following:
Created App registration 'test-app'.
Executed on the db:
CREATE USER [test-app] FROM EXTERNAL PROVIDER;
EXEC sp_addrolemember N'db_datareader', N'test-app';
GRANT SELECT ON test_vw to [test-app];
Added 'test-app' to Contributor and Reader roles for the SQL Server.
Whitelisted IP in the portal - I'm able to log in through SSMS and 'AAD Universal with MFA' using personal account.
Generated token with (tenant ID matches the one used by the organization):
POST https://login.microsoftonline.com/9ff8761-1be4-4729-b88df-e421e19d92f/oauth2/v2.0/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
client_id=[client_id]
client_secret=[client_secret]
scope=https://database.windows.net/.default
grant_type=client_credentials
Used generated JWT token in following python code:
from sqlalchemy import create_engine
import urllib
import struct
server = "test-server.database.windows.net"
database = "test-db"
driver = "{ODBC Driver 17 for SQL Server}"
jwt_token = "<jwt_token>"
SQL_COPT_SS_ACCESS_TOKEN = 1256
exptoken = b""
for i in bytes(jwt_token, "UTF-8"):
exptoken += bytes({i})
exptoken += bytes(1)
tokenstruct = struct.pack("=i", len(exptoken)) + exptoken
params = urllib.parse.quote_plus(
f"Driver={driver};Server={server};Database={database};Encrypt=yes"
)
conn_str = f"mssql+pyodbc:///?odbc_connect={params}"
engine_azure = create_engine(
conn_str,
connect_args={"attrs_before": {SQL_COPT_SS_ACCESS_TOKEN: tokenstruct}},
echo=True,
)
with engine_azure.connect() as con:
rs = con.execute("SELECT TOP 100 * FROM test_vw")
for row in rs:
print(row)
Any idea what I've missed?
I registered an app and copied ClientID, TenantId, generated client secret and copied ClientSecret value.I created azure SQL database and copied servername, databasename in azure portal.
I tried to connect azure SQL database by using token by replacing ClientID, TenantId, ClientSecret:
I installed SQLALchemy and adal packages using
pip install sqlalchemy
pip install adal
Connecting to Azure SQL database using below code:
from sqlalchemy import create_engine
import adal
server = '<servername>'
database = '<databasename>'
client_id = '<ClientId>'
tenant_id = '<TenantId>'
authority_host_uri = 'https://login.microsoftonline.com'
authority_uri = authority_host_uri + '/' + tenant_id
resource_uri = 'https://database.windows.net/'
client_secret = 'NbH8Q~x8PsGqD4C~8HUGzLmql_iRS7dxOMv2Bcjj'
context = adal.AuthenticationContext(authority_uri)
token = context.acquire_token_with_client_credentials(resource_uri, client_id, client_secret)
conn_str = (
'Driver={ODBC Driver 17 for SQL Server};'
f'Server={server};'
f'Database={database};'
'Encrypt=yes;'
'TrustServerCertificate=yes;'
f'AccessToken={token["accessToken"]};'
)
engine = create_engine('mssql+pyodbc:///?odbc_connect={}'.format(conn_str))
with engine.connect() as conn:
result = conn.execute('SELECT * FROM your-table')
for row in result:
print(row)
I got below error:
I created new group and added to registered app by following below procedure:
Goto-->Azure Active directory-->Enterprise Applications
Select the app and go to--> Group/Users-->Add User/Group select the user/group and click on assign.
Set that user/group as admin of SQL server by clicking Set admin:
I tried to connect SQL database again:
It worked successfully for me kindly check from your end.

Oracle connect from Databricks

I am trying to connect to Oracle database in an on-premises VM from Databricks.
I tried to connect using CX_Oracle via Python through init-script by following this link. It failed with below errors
Then I tried to connect using Pyspark and it also failed with below error. Also installed OJDBC into the cluster, where I used OJDBC version compatible with Oracle DB version.
URL = "jdbc:oracle:thin:" + User_Name + "/" + Password + "#//" + IP + ":" + Port + "/" + DB_name
DbTable = DataBase_name + "." + Table_Name
empDF = spark.read.format("jdbc").option("url", URL).option("dbtable", DbTable).option("user", User_Name).option("password", Password).option("driver", "oracle.jdbc.driver.OracleDriver").load()
Using the same settings in ADF Lookup activity, using a self hosted IR I am able to establish the connection. Is there anything I am missing in the connection string from Databricks?

Error connecting from Python to Db2 through pyodbc

I installed the Db2 ODBC driver in Windows 10 following these instructions. I extracted the driver folder in C:\tools\db2cli\ and run db2cli install -setup from the bin folder.
This seems to have worked fine, as the ODBC driver was registered in Windows:
But when I try to connect from Jupyter I get this error:
server = 'localhost'
database = 'mydb'
username = 'db2inst1'
password = 'abc123'
driver = 'IBM DB2 ODBC DRIVER - C_tools_db2cli'
conn = pyodbc.connect('DRIVER={' + driver +'};SERVER='
+ server + ';DATABASE=' + database + ';UID='
+ username + ';PWD=' + password + ';PROTOCOL=TCPIP;PORT=50000' )
Error Traceback (most recent call
last) in
4 password = 'abc123'
5 driver = 'IBM DB2 ODBC DRIVER - C_tools_db2cli'
----> 6 conn = pyodbc.connect('DRIVER={' + driver +'};SERVER='
7 + server + ';DATABASE=' + database + ';UID='
8 + username + ';PWD=' + password + ';PROTOCOL=TCPIP;PORT=50000' )
Error: ('HY000', '[HY000] [IBM][CLI Driver] SQL1042C An unexpected
system error occurred. SQLSTATE=58004\r\n (-1042) (SQLDriverConnect);
[HY000] [IBM][CLI Driver] SQL1042C An unexpected system error
occurred. SQLSTATE=58004\r\n (-1042)')
I unsuccessfully tried to find the error codes to find a solution. What should be looked at to fix this problem?
Note: I added C:\tools\db2cli\bin to the PATH but still get the same error.
This issue was caused by a defect in clidriver for some specific configurations on Microsoft Windows.
You can workaround this by ensuring that the PATH does not have any other Db2-products on it (except for clidriver\bin), and then ensuring to add two additional directories to the PATH before launching python. These are the fully qualified pathnames to these directories:
clidriver\bin\icc64
clidriver\bin\amd64.vc12.crt
IBM should at some point deliver a fix for IT34327.
SERVER= is for the already cataloged database
otherwise you must use: HOSTNAME= if you want to specify full DSN.
https://cloud.ibm.com/docs/Db2onCloud?topic=Db2onCloud-con_program&locale=fr

Unable to get the collection names from MongoDB python

I have mongodb running on azure portal. I can connect to it using nosql booster. I have created a DB TestDb and have added 3 collections to it. I am trying to connect to it using python as below:
mongo_url = 'mongodb://' + <username> + ':' + <password> + '#' + <url> + ':' + port + '/' + admin
client = MongoClient(mongo_url)
db = client.get_database('TestDb')
print(db)
print(db.list_collection_names()) # Error at this line
Below is the output of db:
Database(MongoClient(host=['<name>.documents.azure.com:10255'], document_class=dict, tz_aware=False, connect=True), 'TestDb')
but at db.list_collection_names() it shows error <name>.documents.azure.com:10255: timed out.
I have rechecked everything and all looks good to me. But not sure why not able to do above using python. Please help. Thanks
It's worth mentioning you are using Cosmos DB.
Although it's compatible with MongoDB on wire protocol level, it has own specifics.
Try to follow Quick Start snippets for Python from Azure Portal. It should have most accurate connection settings.
My best guess is it requires ssl enabled oclientside:
mongo_url = 'mongodb://' + <username> + ':' + <password> + '#' + <url> + ':' + port + '/' + admin + '?ssl=true'
I was also using a test DB but nothing worked. This develop DB had some dummy configurations so the solution was adding a tlsAllowInvalidCertificates to my url:
url = f"mongodb://{USERNAME}:{PASSWORD}#{HOST}:{PORT}/{DB_NAME}?authSource=admin&ssl=true&tlsAllowInvalidCertificates=true"

Connect to db2 database with Python

I'm working on an app that needs to connect to an ibm db2 database. Using DBeaver I can successfully connect to the database (I provide him the db2cc.jar and db2cc4.jar files).
It looks to me as DBeaver is using my Window's credentials to login, because I didn't need to input any login or password to connect.
Now, I've been trying to connect to the same database using python 3.7 and pypi's latest version of the ibm_db package. I didn't install anything else.
import ibm_db
# ...
connection_string = "DATABASE=" + self.params['schema'] + ";" + \
"HOSTNAME=" + self.params['host'] + ";" + \
"PORT=" + self.params['port'] + ";" + \
"PROTOCOL=TCPIP;" + \
"SECURITYMECHANISM=4;" + \
"UID=" + self.params['user'] + ";" + \
"PWD=" + self.params['password'] + ";"
try:
self.connection = ibm_db.connect(connection_string, "", "")
# ...
Using my Windows credentials in the parameters, I get the following error message:
Connection error
Bad credentials
SQLCODE=-30082
08001
From what I've seen on stack overflow connecting to a db2 database is complicated...
Does someone know how to connect ? Using the windows credentials or otherwise...
Thanks !
Db2 works fine with Python.
You need to be aware of some basics before you start such as:
what operating-system runs the target Db2-database and
what kind of client is being used (java, odbc/cli, .net etc), and
what kind of authentication/encrpytion is in place for the database
(ssl, server based authentication/+/-/encryption etc.).
is the remote database rdbms Apache DERBY or Db2.
Find out these basics before you start. You have to speak with people who run the Db2-server.
Note: in your question you mention (SecurityMechanism=4) com.ibm.db2.jcc.DB2BaseDataSource.USER_ONLY_SECURITY - this is not relevant for non-JAVA clients, it is relevant is the database manager is DERBY .
For python, the ibm_db package is not a java application.
DBeaver is a java application (hence it uses db2jcc.jar or db2jcc4.jar and a licence-file to connect to the remote database).
You can only use your Windows credentials for connecting to a Db2-database when that Db2-database run on Microsoft-Windows, and the credentials work on the hostname running the Db2-server. For any other combinations, the administrator must issue you a userid/password that is relevant for the target hostname.
The ibm_db package needs a Db2-client to be installed. The Db2-client is a separate installable. There are different kinds of Db2-client depending both on which operating-system runs your Db2-server and how much functionality you need to have in your Db2-client. If your remote Db2-server runs on Linux, Unix, Windows or Z/OS then you can use the "IBM Data Server Runtime Client" which you can either download from IBM's passport advantage website, or get from your internal IT folks. If your Db2-server runs on i-Series (AS/400) you should get its drivers from your i-Series administrator. For either Z/OS or i-Series you will additionally need a license file (which costs money) and you should get that from your administrator, unless your company uses a gateway product called Db2-connect in which case you don't need a separate license file on your workstation.
Try the following connection string, If your db2 client and server are on the same host.
Change the 'mydb' and 'DB2' (db2 instance name, you can get it with db2ilist utility) constants according your case.
ibm_db.connect('DATABASE=mydb;Instance=DB2;PROTOCOL=IPC;', '', '')
add ibm_db library and import ibm_db on top in the .py file.
def get_db_connection():
"""
This will help to get db2 connection for query execution
:return: conn
"""
dsn_driver = "{IBM DB2 ODBC DRIVER}"
dsn_database = "BLUDB"
dsn_hostname = "your_hostname"
dsn_port = "50000"
dsn_protocol = "TCPIP"
dsn_uid = "your_userid"
dsn_pwd = "your_pwd"
dsn = (
"DRIVER={0};"
"DATABASE={1};"
"HOSTNAME={2};"
"PORT={3};"
"PROTOCOL={4};"
"UID={5};"
"PWD={6};").format(dsn_driver, dsn_database, dsn_hostname, dsn_port, dsn_protocol, dsn_uid, dsn_pwd)
try:
conn = ibm_db.connect(dsn, "", "")
print("Connected!")
return conn
except Exception:
print("\nERROR: Unable to connect to the \'" + dsn_database + "\' server.")
print("error: ", ibm_db.conn_errormsg())
exit(-1)
function get_db_connection() will return the connection object. On that connection object you can perform operation like:
conn = get_db_connection()
list_results = []
select_query = 'SELECT a.STATUS, a.ID FROM "TABLE_NAME" AS a'
print(select_query)
selectStmt = ibm_db.exec_immediate(conn, select_query)
while ibm_db.fetch_row(selectStmt) != False:
list_results.append(ibm_db.result(selectStmt, 'ID'))
ibm_db.close(conn)

Categories

Resources