Azure Web App 在使用 Docker 运行时无法使用托管身份

问题描述 投票:0回答:1

编辑

请勿在 Web 应用程序中设置

AZURE_CLIENT_ID
AZURE_TENANT_ID
环境变量。另外,使用
DefaultAzureCredential
时,请执行以下操作:
DefaultAzureCredential(exclude_environment_credential = False)

设置

我有一个简单的 Python 应用程序,它使用 Docker 部署为 Azure Web 应用程序。应用程序本身正在运行,但无法与配置为仅允许通过托管标识进行身份验证的 Azure SQL 数据库连接。

我自己和应用程序的托管身份都已添加到安全组(我们称之为

my-group
)。我使用
az sql server create ... --external-admin-name my-group
创建了托管数据库的 SQL Server。这样做之后,我还运行了这些查询:

CREATE USER [my-group] FROM EXTERNAL PROVIDER;

ALTER ROLE db_datareader ADD MEMBER [my-group];
ALTER ROLE db_datawriter ADD MEMBER [my-group];
ALTER ROLE db_ddladmin   ADD MEMBER [my-group];

以下代码也是我的应用程序的一部分,可以在没有 Docker 的情况下在本地运行,前提是我首先使用

az login
登录。 (使用 Docker 时,应用程序也无法连接到数据库,但其他一切都工作正常。)

from azure.identity import DefaultAzureCredential


def create_token_struct(databaseToken):
    
    exptoken = b''
    
    for i in bytes(databaseToken[0], "UTF-8"):
        exptoken += bytes({i})
        exptoken += bytes(1)
    
    return struct.pack("=i", len(exptoken)) + exptoken


credential = DefaultAzureCredential()

pyodbc.connect(AZURE_SQL_CONNECTION_STRING, attrs_before = {1256: create_token_struct(credential.get_token('https://database.windows.net/'))})

连接字符串如下所示:

Driver={ODBC Driver 18 for SQL Server};Server=tcp:my-server-name.database.windows.net,1433;Database=my_database_name;Encrypt=yes;TrustServerCertificate=no;Connection Timeout=30

错误

在 Azure 中运行时,应用程序在运行该代码时会返回错误。起初它只是给出了

Login timeout expired
错误,但在向我的 Azure Web 应用程序添加两个环境变量(
AZURE_CLIENT_ID
AZURE_TENANT_ID
)后,我现在收到以下错误:

azure.core.exceptions.ClientAuthenticationError: DefaultAzureCredential failed to retrieve a token from the included credentials.
Attempted credentials:
    EnvironmentCredential: EnvironmentCredential authentication unavailable. Environment variables are not fully configured.
Visit https://aka.ms/azsdk/python/identity/environmentcredential/troubleshoot to troubleshoot this issue.
    ManagedIdentityCredential: (None) No User Assigned or Delegated Managed Identity found for specified ClientId/ResourceId/PrincipalId.
Code: None
Message: No User Assigned or Delegated Managed Identity found for specified ClientId/ResourceId/PrincipalId.
To mitigate this issue, please refer to the troubleshooting guidelines here at https://aka.ms/azsdk/python/identity/defaultazurecredential/troubleshoot.

环境变量的值通过运行

az webapp identity show
获取;
AZURE_CLIENT_ID
设置为输出的
principalId
,并且
AZURE_TENANT_ID
设置为
tenantId
。我还尝试了其他值,例如应用程序的
Application ID
和安全组的
Object Id

我在这里缺少什么?我可以在本地访问数据库,因此,不知何故,Docker 容器似乎没有“接收”系统分配的 Azure Web App 托管标识。

编辑

这是我的 Dockerfile

FROM python:3.10


COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt


# For pyodbc
RUN apt-get update && apt-get -y install unixodbc-dev

RUN sh -c "curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -" \
    && apt-get update \
    && sh -c "curl https://packages.microsoft.com/config/ubuntu/20.04/prod.list > /etc/apt/sources.list.d/mssql-release.list" \
    && apt-get update \
    && ACCEPT_EULA=Y apt-get install -y msodbcsql18 \
    && ACCEPT_EULA=Y apt-get install -y mssql-tools18


# Azure CLI
RUN sh -c "curl -sL https://aka.ms/InstallAzureCLIDeb | bash"


WORKDIR /app
COPY . /app
EXPOSE 8501
azure docker azure-managed-identity
1个回答
0
投票

这对我有用 我创建了一个简单的 Flask 应用程序来从表中获取数据

Dockerfile
:

FROM python

RUN sh -c "curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -" \
    && apt-get update \
    && sh -c "curl https://packages.microsoft.com/config/ubuntu/20.04/prod.list > /etc/apt/sources.list.d/mssql-release.list" \
    && apt-get update \
    && ACCEPT_EULA=Y apt-get install -y msodbcsql18 \
    && ACCEPT_EULA=Y apt-get install -y mssql-tools18

RUN pip install gunicorn

WORKDIR /app

COPY . .

RUN pip install -r requirements.txt

EXPOSE 5000

ENTRYPOINT [ "gunicorn", "app:app"]

app.py
:

from flask import Flask, render_template_string
import azure.identity as ad
import pyodbc
import struct
import json

app = Flask(__name__)

@app.route('/')

def hello():
    message = "Greetings! Wecome to Flask App"

    try:
        cred = ad.DefaultAzureCredential()
        Connectionstring = "Driver={ODBC Driver 18 for SQL Server};Server=tcp:mi-in-docker-server.database.windows.net,1433;Database=manageidentyindocker;Encrypt=yes;TrustServerCertificate=no;Connection Timeout=30"
        with pyodbc.connect(Connectionstring,attrs_before = {1256: create_token_struct(cred.get_token('https://database.windows.net/'))}) as conn:
            with conn.cursor() as cursor:
                cursor.execute("Select * from Users;")
                data= []
                data = cursor.fetchall()  # Fetch the result

                return str(data)
                
    except pyodbc.Error as e:
        return(f"SQL query failed: {e}")
    
def create_token_struct(databaseToken):
    
    exptoken = b''
    
    for i in bytes(databaseToken[0], "UTF-8"):
        exptoken += bytes({i})
        exptoken += bytes(1)
    
    return struct.pack("=i", len(exptoken)) + exptoken

app.run(host='0.0.0.0', port=5000)

INPUT

为网络应用程序的系统分配身份分配角色:

注意: 您可以在 Azure 中使用 Microsoft Entra 身份验证登录时分配角色。

DECLARE @USERNAME nvarchar(128)

SET @USERNAME = 'my-system-assign-identity-name'

BEGIN
    EXECUTE('CREATE USER "' + @USERNAME + '" FROM EXTERNAL PROVIDER');
    EXECUTE('ALTER ROLE db_datareader ADD MEMBER "' + @USERNAME + '"');
    EXECUTE('ALTER ROLE db_datawriter ADD MEMBER "' + @USERNAME + '"');
    EXECUTE('ALTER ROLE db_ddladmin ADD MEMBER "' + @USERNAME + '"')
END

创建表格

Users

OUTPUT

有关参考,请查看此问答帖子

© www.soinside.com 2019 - 2024. All rights reserved.