Connect to Azure SQL database in SQL Alchemy using Entra ID tokens

Mary-Kate Olsen
Release: 2024-11-03 18:46:30
Original
926 people have browsed it

Connect to Azure SQL database in SQL Alchemy using Entra ID tokens

We have a web application at work that needs to connect to our Azure SQL database for the duration of the request. To make querying the database easier, we use SQL Alchemy and pyodbc.

We have a few goals we want to achieve:

  • Every request gets its own session. We want to open a new session when the request starts and close it once it is done.
  • We want to connect to the database using the managed identity of the web service (Azure Function App or Azure Web App).
  • We want to delegate the handling of the session and connection as much as we can.

Session lifetime management

First, to make sure we open a new session for every request, we can wrap the request functions into decorators that make sure a new session is created and subsequently destroyed.

To make sure our session is easily accessible from all over the application without having to hand it over in every function call, we use a singleton pattern. However, since we run multiple threads to handle multiple requests at the same time, we have to make sure that there are no race conditions with respect to the session objects.

SQL Alchemy has a great utility to make this easier: the scoped session.

To use this, we wrap our connection factory into a scoped_session() call:

from urllib.parse import quote_plus
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, scoped_session

connection_string = "..."
engine = create_engine("mssql+pyodbc:///?odbc_connect={}".format(quote_plus(connection_string))
session_factory = sessionmaker(bind=engine)
Session = scoped_session(session_factory)
Copy after login
Copy after login

Now, whenever we want to use the session, we just call Session() and SQL Alchemy makes sure we reuse the existing session object. If we are done, we can call Session.remove() to close the session. There is no way for SQL Alchemy to tell if the thread is done so we have to do this ourselves.

Connect via Entra ID tokens using managed identity

There are some posts that describe how to setup the connection to Azure SQL databases using access tokens, but the best resource for this is the SQL Alchemy docs themselves.

Let's go over the details together. First, we need a connection string. Since we want to rely on managed identity (or the Azure CLI for local development), we do not put any credentials into the connection string:

Driver={ODBC Driver 18 for SQL Server};Database=YOUR_DB;Server=tcp:you.database.windows.net,1433;Encrypt=yes;TrustServerCertificate=no;Connection Timeout=30

Our general plan is:

  • Add an event handler that fires whenever we connect to the database.
  • Retrieve an access token whenever we connect to the database.
  • Adjust the connection arguments so that we put the (fresh!) access token into the connection string.

Now, let's take a look at the code:

from urllib.parse import quote_plus
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, scoped_session

connection_string = "..."
engine = create_engine("mssql+pyodbc:///?odbc_connect={}".format(quote_plus(connection_string))
session_factory = sessionmaker(bind=engine)
Session = scoped_session(session_factory)
Copy after login
Copy after login

Summary

With this, we achieved our goals. With the scoped_session() we do not need to open a new session every time a request comes in (this will be handled for us) but we should close the session at the end so that we do not have too many dangling sessions.

We also connect to the SQL database using our own identity (for local dev) or the managed identity of the web service. We modify the connection string each time a new connection is created.

Acknowledgements

A big thank you to David for helping me figure out the concept of scoped sessions.

The above is the detailed content of Connect to Azure SQL database in SQL Alchemy using Entra ID tokens. For more information, please follow other related articles on the PHP Chinese website!

source:dev.to
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template