【问题标题】:Use Managed Identity to authenticate Azure App Service to SQL Database使用托管标识向 SQL 数据库验证 Azure 应用服务
【发布时间】:2021-06-04 17:19:47
【问题描述】:

我正在尝试将在 Azure 应用服务 Web 应用中运行的 Python Flask 应用连接到 Azure SQL 数据库。 当我使用带有用户名和密码的 SQL 身份验证时,效果很好。

现在我想转而使用 Web Apps 托管标识。 我已经激活了系统分配的托管标识,在 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-database azure-web-app-service


    【解决方案1】:

    我知道这是一篇很老的帖子,但它可能会帮助像我这样正在寻找解决方案的人。

    您可以通过将“Authentication”参数添加为“ActiveDirectoryMsi”来修改连接字符串,无需使用端点和标头。

    (适用于 Azure SQL,对于 Postgress 等其他数据库,您可能需要使用 struct 令牌)

    import pyodbc
    
    
    pyodbc.connect(
            "Driver="
            + driver
            + ";Server="
            + server
            + ";PORT=1433;Database="
            + database
            + ";Authentication=ActiveDirectoryMsi")
    

    我为那些对 Azure MSI 感兴趣的人写了一篇简短的文章: https://hedihargam.medium.com/python-sql-database-access-with-managed-identity-from-azure-web-app-functions-14566e5a0f1a

    【讨论】:

      【解决方案2】:

      如果你想在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

        一个。将您的 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

      【讨论】:

      • 感谢您的回答。这是否意味着我必须直接使用 pyodbc,或者您知道使用 SqlAlchemy 的方法吗?
      • @Ben 关于这个问题,请参考stackoverflow.com/questions/57193301/…
      • @JimXu,你能回答这个问题吗stackoverflow.com/questions/64261711/…,这也是一个赏金问题。
      • 如何传递注册应用的客户端 ID 和客户端密码?我认为这是部分解决方案
      • @abhijat_saxena 如果你使用 Azure msi,我们不需要传递客户端 ID 和客户端密码。
      猜你喜欢
      • 2020-01-08
      • 2019-10-26
      • 2019-01-24
      • 1970-01-01
      • 2019-09-08
      • 2020-08-30
      • 1970-01-01
      • 2023-01-18
      • 1970-01-01
      相关资源
      最近更新 更多