使用使用者指派的受控識別,建立 Django Web 應用程式並將其部署至 Azure
在本教學課程中,您會將 Django Web 應用程式部署至 Azure App 服務。 Web 應用程式會使用使用者指派的受控識別(無密碼連線)搭配 Azure 角色型訪問控制來存取 Azure 儲存體 和 適用於 PostgreSQL 的 Azure 資料庫 - 彈性伺服器資源。 此程式代碼會使用適用於 Python 的 Azure 身分識別用戶端連結庫的 DefaultAzureCredential 類別。 類別 DefaultAzureCredential
會自動偵測 App Service 的受控識別是否存在,並用它來存取其他 Azure 資源。
在本教學課程中,您會建立使用者指派的受控識別,並將其指派給 App Service,以便存取資料庫和記憶體帳戶資源。 如需使用系統指派受控識別的範例,請參閱 使用系統指派的受控識別建立和部署 Flask Python Web 應用程式至 Azure。 建議使用使用者指派的受控識別,因為它們可供多個資源使用,而且其生命週期會與與其相關聯的資源生命周期分離。 如需使用受控識別之最佳做法的詳細資訊,請參閱 受控識別最佳做法建議。
本教學課程說明如何部署 Python Web 應用程式,並使用 Azure CLI 建立 Azure 資源。 本教學課程中的命令會撰寫成在Bash殼層中執行。 您可以在任何已安裝 CLI 的 Bash 環境中執行教學課程命令,例如本機環境或 Azure Cloud Shell。 透過一些修改 -- 例如,設定和使用環境變數 -- 您可以在 Windows 命令殼層等其他環境中執行這些命令。
取得範例應用程式
使用範例 Django 範例應用程式來遵循本教學課程。 下載或複製範例應用程式到您的開發環境。
複製範例。
git clone https://github.com/Azure-Samples/msdocs-django-web-app-managed-identity.git
瀏覽至應用程式資料夾。
cd msdocs-django-web-app-managed-identity
檢查驗證碼
範例 Web 應用程式必須向兩個不同的資料存放區進行驗證:
- Azure Blob 記憶體伺服器會儲存並擷取檢閱者提交的相片。
- 適用於 PostgreSQL 的 Azure 資料庫 - 彈性伺服器資料庫,其儲存餐廳與評論。
它會使用 DefaultAzureCredential 向這兩個數據存放區進行驗證。 使用 DefaultAzureCredential
時,應用程式可以設定為在不同的服務主體身分識別下執行,視其執行環境而定,而不需變更程序代碼。 例如,在本機開發環境中,應用程式可以在登入 Azure CLI 的開發人員身分識別下執行,而在 Azure 中,如本教學課程所示,它可以在使用者指派的受控識別下執行。
不論是哪一種情況,應用程式執行的安全性主體都必須在應用程式所使用的每個 Azure 資源上具有角色,才能在應用程式所需的資源上執行動作。 在本教學課程中,您會使用 Azure CLI 命令來建立使用者指派的受控識別,並將它指派給 Azure 中的應用程式。 然後,在 Azure 記憶體帳戶和 適用於 PostgreSQL 的 Azure 資料庫 伺服器上手動指派該身分識別適當的角色。 最後,您會在 Azure 中設定 AZURE_CLIENT_ID
應用程式的環境變數,以 DefaultAzureCredential
設定為使用受控識別。
在應用程式及其運行時間環境中設定使用者指派的受控識別,並在數據存放區上指派適當的角色之後,您可以使用 DefaultAzureCredential
來向所需的 Azure 資源進行驗證。
下列程式代碼可用來建立 Blob 記憶體用戶端,以在中 ./restaurant_review/views.py
上傳相片。 的實例 DefaultAzureCredential
會提供給用戶端,用來取得存取令牌,以對 Azure 記憶體執行作業。
from azure.identity import DefaultAzureCredential
from azure.storage.blob import BlobServiceClient
azure_credential = DefaultAzureCredential()
blob_service_client = BlobServiceClient(
account_url=account_url,
credential=azure_credential)
的DefaultAzureCredential
實例也可用來取得 中 ./azureproject/get_conn.py
適用於 PostgreSQL 的 Azure 資料庫的存取令牌。 在此情況下,令牌會直接透過在認證實例上呼叫 get_token ,並傳遞適當的 scope
值來取得令牌。 令牌接著會用來在PostgreSQL連線 URI 中設定密碼。
azure_credential = DefaultAzureCredential()
token = azure_credential.get_token("https://ossrdbms-aad.database.windows.net")
conf.settings.DATABASES['default']['PASSWORD'] = token.token
若要深入瞭解如何使用 Azure 服務驗證您的應用程式,請參閱 使用適用於 Python 的 Azure SDK 向 Azure 服務驗證 Python 應用程式。 若要深入瞭解 DefaultAzureCredential
,包括如何針對您的環境自定義認證鏈結,請參閱 DefaultAzureCredential 概觀。
建立 Azure PostgreSQL 彈性伺服器
設定教學課程所需的環境變數。
LOCATION="eastus" RAND_ID=$RANDOM RESOURCE_GROUP_NAME="msdocs-mi-web-app" APP_SERVICE_NAME="msdocs-mi-web-$RAND_ID" DB_SERVER_NAME="msdocs-mi-postgres-$RAND_ID" ADMIN_USER="demoadmin" ADMIN_PW="ChAnG33#ThsPssWD$RAND_ID" UA_NAME="UAManagedIdentityPythonTest$RAND_ID"
重要
ADMIN_PW
必須包含下列三個類別的8到128個字元:英文大寫字母、英文小寫字母、數位和非虛構字元。 建立使用者名稱或密碼時不會使用$
字元。 您稍後會使用這些值建立環境變數,其中$
字元在用來執行 Python 應用程式的 Linux 容器中具有特殊意義。使用 az group create 命令來建立資源群組。
az group create --location $LOCATION --name $RESOURCE_GROUP_NAME
使用 az postgres flexible-server create 命令建立 PostgreSQL 彈性伺服器。 (這個和後續的命令會使用BashShell('\' 的行接續字元)。 變更其他殼層的行接續字元。
az postgres flexible-server create \ --resource-group $RESOURCE_GROUP_NAME \ --name $DB_SERVER_NAME \ --location $LOCATION \ --admin-user $ADMIN_USER \ --admin-password $ADMIN_PW \ --sku-name Standard_D2ds_v4 \ --active-directory-auth Enabled \ --public-access 0.0.0.0
sku-name 是定價層和計算組態的名稱。 如需詳細資訊,請參閱適用於 PostgreSQL 的 Azure 資料庫定價。 若要列出可用的 SKU, 請使用
az postgres flexible-server list-skus --location $LOCATION
。使用 az postgres flexible-server ad-admin create 命令,將 Azure 帳戶新增為伺服器的 Microsoft Entra 管理員。
ACCOUNT_EMAIL=$(az ad signed-in-user show --query userPrincipalName --output tsv) ACCOUNT_ID=$(az ad signed-in-user show --query id --output tsv) echo $ACCOUNT_EMAIL, $ACCOUNT_ID az postgres flexible-server ad-admin create \ --resource-group $RESOURCE_GROUP_NAME \ --server-name $DB_SERVER_NAME \ --display-name $ACCOUNT_EMAIL \ --object-id $ACCOUNT_ID \ --type User
使用 az postgres flexible-server firewall-rule create 命令,在您的伺服器上設定防火牆規則。 此規則可讓您的本機環境存取權連線到伺服器。 (如果您使用 Azure Cloud Shell,您可以略過此步驟。
IP_ADDRESS=<your IP> az postgres flexible-server firewall-rule create \ --resource-group $RESOURCE_GROUP_NAME \ --name $DB_SERVER_NAME \ --rule-name AllowMyIP \ --start-ip-address $IP_ADDRESS \ --end-ip-address $IP_ADDRESS
使用任何顯示IP位址的工具或網站,以取代
<your IP>
命令。 例如,您可以使用 「我的IP位址」 網站。使用 az postgres flexible-server execute 命令建立名為
restaurant
的資料庫。az postgres flexible-server execute \ --name $DB_SERVER_NAME \ --admin-user $ADMIN_USER \ --admin-password $ADMIN_PW \ --database-name postgres \ --querytext 'create database restaurant;'
建立 Azure App 服務並部署程序代碼
在範例應用程式的根資料夾中執行這些命令,以建立App Service並將程式代碼部署至其中。
使用 az webapp up 命令建立 App Service。
az webapp up \ --resource-group $RESOURCE_GROUP_NAME \ --location $LOCATION \ --name $APP_SERVICE_NAME \ --runtime PYTHON:3.9 \ --sku B1
SKU 會定義 App Service 方案的大小(CPU、記憶體)和成本。 B1 (基本) 服務方案會在您的 Azure 訂用帳戶中產生少量成本。 如需 App Service 方案的完整清單,請檢視 App Service 定價頁面。
將 App Service 設定為搭配 az webapp config set 命令使用範例存放庫中的 start.sh。
az webapp config set \ --resource-group $RESOURCE_GROUP_NAME \ --name $APP_SERVICE_NAME \ --startup-file "start.sh"
建立儲存體帳戶和容器
範例應用程式會將檢閱者提交的相片儲存為 Azure 儲存體 中的 Blob。
當使用者提交相片時,範例應用程式會使用受控識別將映像寫入容器,並
DefaultAzureCredential
存取記憶體帳戶。當用戶檢視餐廳的評論時,應用程式會針對每個與該評論相關聯的檢閱,傳回 Blob 記憶體中相片的連結。 若要讓瀏覽器顯示相片,它必須能夠在記憶體帳戶中存取它。 Blob 數據必須可供透過匿名(未經驗證)存取公開讀取。
在本節中,您會建立記憶體帳戶和容器,以允許對容器中的 Blob 進行公用讀取存取。 在稍後的章節中,您會建立使用者指派的受控識別,並將其設定為將 Blob 寫入記憶體帳戶。
使用 az storage create 命令來建立記憶體帳戶。
STORAGE_ACCOUNT_NAME="msdocsstorage$RAND_ID" az storage account create \ --name $STORAGE_ACCOUNT_NAME \ --resource-group $RESOURCE_GROUP_NAME \ --location $LOCATION \ --sku Standard_LRS \ --allow-blob-public-access true
使用 az storage container create 命令,在記憶體帳戶中建立名為 photos 的容器。
az storage container create \ --account-name $STORAGE_ACCOUNT_NAME \ --name photos \ --public-access blob \ --auth-mode login
注意
例如,如果命令失敗,如果您收到錯誤,指出記憶體帳戶的網路規則可能會封鎖要求,請輸入下列命令,以確定您的 Azure 使用者帳戶已獲指派具有建立容器許可權的 Azure 角色。
az role assignment create --role "Storage Blob Data Contributor" --assignee $ACCOUNT_EMAIL --scope "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP_NAME/providers/Microsoft.Storage/storageAccounts/$STORAGE_ACCOUNT_NAME"
如需詳細資訊,請參閱 快速入門:使用 Azure CLI 建立、下載及列出 Blob。 請注意,數個 Azure 角色可讓您在記憶體帳戶中建立容器,包括「擁有者」、「參與者」、「記憶體 Blob 數據擁有者」和「記憶體 Blob 數據參與者」。
建立使用者指派的受控識別
建立使用者指派的受控識別,並將它指派給App Service。 受控識別可用來存取資料庫和記憶體帳戶。
使用 az identity create 命令來建立使用者指派的受控識別,並將用戶端標識碼輸出至變數以供稍後使用。
UA_CLIENT_ID=$(az identity create --name $UA_NAME --resource-group $RESOURCE_GROUP_NAME --query clientId --output tsv) echo $UA_CLIENT_ID
使用 az account show 命令來取得您的訂用帳戶標識碼,並將它輸出至可用來建構受控識別的資源識別符的變數。
SUBSCRIPTION_ID=$(az account show --query id --output tsv) RESOURCE_ID="/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP_NAME/providers/Microsoft.ManagedIdentity/userAssignedIdentities/$UA_NAME" echo $RESOURCE_ID
使用 az webapp identity assign 命令將受控識別指派給 App Service。
export MSYS_NO_PATHCONV=1 az webapp identity assign \ --resource-group $RESOURCE_GROUP_NAME \ --name $APP_SERVICE_NAME \ --identities $RESOURCE_ID
使用 az webapp config appsettings set 命令建立 App Service 應用程式設定,其中包含受控識別的用戶端識別碼和其他組態資訊。
az webapp config appsettings set \ --resource-group $RESOURCE_GROUP_NAME \ --name $APP_SERVICE_NAME \ --settings AZURE_CLIENT_ID=$UA_CLIENT_ID \ STORAGE_ACCOUNT_NAME=$STORAGE_ACCOUNT_NAME \ STORAGE_CONTAINER_NAME=photos \ DBHOST=$DB_SERVER_NAME \ DBNAME=restaurant \ DBUSER=$UA_NAME
範例應用程式會使用環境變數(應用程式設定)來定義資料庫和記憶體帳戶的連線資訊,但這些變數不包含密碼。 而是使用 DefaultAzureCredential
進行無密碼驗證。
範例應用程式程式代碼會 DefaultAzureCredential
使用 類別建構函式,而不需將使用者指派的受控識別用戶端標識元傳遞至建構函式。 在此案例中,後援是檢查您設定為應用程式設定的 AZURE_CLIENT_ID
環境變數。
AZURE_CLIENT_ID
如果環境變數不存在,則會在設定系統指派的受控識別時使用。 如需詳細資訊,請參閱 DefaultAzureCredential 簡介。
建立受控識別的角色
在本節中,您會為受控識別建立角色指派,以啟用記憶體帳戶和資料庫的存取權。
使用 az role assignment create 命令建立受控識別的角色指派,以啟用記憶體帳戶的存取權。
export MSYS_NO_PATHCONV=1 az role assignment create \ --assignee $UA_CLIENT_ID \ --role "Storage Blob Data Contributor" \ --scope "/subscriptions/$SUBSCRIPTION_ID/resourcegroups/$RESOURCE_GROUP_NAME"
命令會指定資源群組的角色指派範圍。 如需詳細資訊,請參閱 瞭解角色指派。
使用 az postgres flexible-server execute 命令連線到 Postgres 資料庫,並執行相同的命令,將角色指派給受控識別。
ACCOUNT_EMAIL_TOKEN=$(az account get-access-token --resource-type oss-rdbms --output tsv --query accessToken) az postgres flexible-server execute \ --name $DB_SERVER_NAME \ --admin-user $ACCOUNT_EMAIL \ --admin-password $ACCOUNT_EMAIL_TOKEN \ --database-name postgres \ --querytext "select * from pgaadauth_create_principal('"$UA_NAME"', false, false);select * from pgaadauth_list_principals(false);"
如果您無法執行命令,請確定您已將用戶帳戶新增為 PosgreSQL 伺服器的 Microsoft Entra 管理員,而且您已允許存取防火牆規則中的 IP 位址。 如需詳細資訊,請參閱建立 Azure PostgreSQL 彈性伺服器一節。
在 Azure 中測試 Python Web 應用程式
範例 Python 應用程式會使用 azure.identity 套件及其 DefaultAzureCredential
類別。 當應用程式在 Azure 中執行時, DefaultAzureCredential
會自動偵測 App Service 是否有受控識別存在,如果是的話,則會使用它來存取其他 Azure 資源(在此案例中為記憶體和 PostgreSQL)。 不需要提供記憶體金鑰、憑證或認證給 App Service,才能存取這些資源。
流覽至 URL
http://$APP_SERVICE_NAME.azurewebsites.net
的已部署應用程式。應用程式可能需要一兩分鐘的時間才能啟動。 如果您看到預設的應用程式頁面不是預設範例應用程式頁面,請稍候一分鐘並重新整理瀏覽器。
藉由新增餐廳以及一些具有餐廳相片的評論,測試範例應用程式的功能。
餐廳和評論資訊儲存在 適用於 PostgreSQL 的 Azure 資料庫,照片儲存在 Azure 儲存體。 以下是範例螢幕快照:
清理
在本教學課程中,所有 Azure 資源都是在相同的資源群組中建立的。 使用 az group delete 命令移除資源群組會移除資源群組中的所有資源,這是移除應用程式所用所有 Azure 資源最快的方式。
az group delete --name $RESOURCE_GROUP_NAME
您可以選擇性地新增 --no-wait
自變數,以允許命令在作業完成之前傳回。