使用托管标识向SQL数据库验证Azure应用程序服务

问题描述

我正在尝试将在Azure应用服务Web App中运行的Python Flask应用连接到Azure SQL数据库。 当我将SQL身份验证与用户名和密码一起使用时,工作正常。

现在,我想转到使用Web应用程序托管标识。 我已经激活了系统分配的托管标识,在SQL中为其创建了一个用户,并将其添加到db_datareader角色。

我正在使用如下所示的连接字符串连接SqlAlChemy

params = urllib.parse.quote_plus(os.environ['SQL_CONNECTION_STRING'])
conn_str = 'mssql+pyodbc:///?odbc_connect={}'.format(params)
engine_azure = db.create_engine(conn_str,echo=True)

连接字符串存储为应用程序设置,其值为

"Driver={ODBC Driver 17 for SQL Server};Server=tcp:<server>.database.windows.net,1433;Database=<database>;Authentication=ActiveDirectoryMsi;"

我以为这就是我需要做的全部工作,但现在我的应用程序无法启动。 日志在连接到数据库时报告超时。

如何修复此问题?


解决方案

如果您想在Python应用中连接Azure SQL数据库和Azure MSI,我们可以使用SDKpyodbc来实现。

例如

  1. Enable system-assigned identity for your Azure app service

  2. Add the MSi as contained database users in your database

    a.将您的SQL数据库与Azure SQL AD管理员连接(我使用SSMS来实现)

    B.在数据库中运行以下脚本

    CREATE USER <your app service name> FROM EXTERNAL PROVIDER;
    ALTER ROLE db_datareader ADD MEMBER <your app service name>
    ALTER ROLE db_datawriter ADD MEMBER <your app service name>
    ALTER ROLE db_ddladmin ADD MEMBER <your app service name>
    
  3. 编码
import os
import pyodbc
import requests 
import struct

#get access token
identity_endpoint = os.environ["IDENTITY_ENDPOINT"]
identity_header = os.environ["IDENTITY_HEADER"]
resource_uri="https://database.windows.net/"
token_auth_uri = f"{identity_endpoint}?resource={resource_uri}&api-version=2019-08-01"
head_msi = {'X-IDENTITY-HEADER':identity_header}
resp = requests.get(token_auth_uri, headers=head_msi)
access_token = resp.json()['access_token']


accessToken = bytes(access_token, 'utf-8');
exptoken = b"";
for i in accessToken:
        exptoken += bytes({i});
        exptoken += bytes(1);
tokenstruct = struct.pack("=i", len(exptoken)) + exptoken;

conn = pyodbc.connect("Driver={ODBC Driver 17 for SQL Server};Server=tcp:andyserver.database.windows.net,1433;Database=database2", attrs_before = { 1256:bytearray(tokenstruct) });

cursor = conn.cursor()
cursor.execute("select @@version")
row = cursor.fetchall()

有关更多详细信息,请参阅

https://github.com/AzureAD/azure-activedirectory-library-for-python/wiki/Connect-to-Azure-SQL-Database

https://docs.microsoft.com/en-us/azure/app-service/overview-managed-identity

https://docs.microsoft.com/en-us/azure/sql-database/sql-database-aad-authentication-configure

相关文章