I have a simple Python app that is deployed as an Azure Web App using Docker. The app itself is running, but can't connect with an Azure SQL Database that is configured to only allow authentication through Managed Identity.
Setup
Both myself and the app's Managed Identity have been added to a security group (let's call it my-group
). I created the SQL Server hosting the database using az sql server create ... --external-admin-name my-group
. After doing so, I also ran these queries:
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];
The following code, which is also part of my app, can run locally without Docker, provided I first login using az login
. (When using Docker, the app also can't connect to the database, but everything else is working just fine.)
from azure.identity import DefaultAzureCredentialdef 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)) + exptokencredential = DefaultAzureCredential()pyodbc.connect(AZURE_SQL_CONNECTION_STRING, attrs_before = {1256: create_token_struct(credential.get_token('https://database.windows.net/'))})
The connection string looks like this: 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
The error
When running in Azure, the app returns an error the moment it runs that code. At first it just gave a Login timeout expired
error, but after adding two environment variables (AZURE_CLIENT_ID
and AZURE_TENANT_ID
) to my Azure Web App, I now get the following error:
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: NoneMessage: 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.
The values of the environment variables are obtained by running az webapp identity show
; the AZURE_CLIENT_ID
is set to the output's principalId
and the AZURE_TENANT_ID
is set to the tenantId
. I have also tried other values, such as the app's Application ID
and the security group's Object Id
.
What am I missing here? I can access the database locally, so it seems that, somehow, the Docker container doesn't "receive" the system-assigned managed identity of the Azure Web App.
Edit
Here is my Dockerfile
FROM python:3.10COPY requirements.txt requirements.txtRUN pip install -r requirements.txt# For pyodbcRUN apt-get update && apt-get -y install unixodbc-devRUN 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 CLIRUN sh -c "curl -sL https://aka.ms/InstallAzureCLIDeb | bash"WORKDIR /appCOPY . /appEXPOSE 8501