共用方式為


使用服務主體在本機開發時驗證 Python 應用程式以連接 Azure 服務

開發人員在建立雲端應用程式時,通常需要在本地運行和測試他們的應用程式。 即使在本機開發期間,應用程式也必須向它互動的任何 Azure 服務進行驗證。 本文說明如何專門設定專用的服務主體身分識別,以在本機開發期間使用。

此圖顯示本機開發人員中執行的應用程式如何從 .env 檔案取得應用程式服務主體,然後使用該身分識別來連線到 Azure 資源。

用於本機開發的專用服務主體會遵循最小權限原則。 它們只會授與應用程式在開發期間所需的 Azure 資源的存取權。 這種有限的存取降低了無意中存取其他資源的風險。 它還有助於防止遷移到生產環境時與權限相關的錯誤,因為更廣泛的權限可能會導致問題。

在 Azure 中註冊應用程式以進行本機開發時:

  • 為每個開發人員建立個別的應用程式註冊:此方法會為每個開發人員提供自己的服務主體,避免共用認證,並啟用更精細的存取控制。
  • 為每個應用程式建立單獨的應用程式註冊:這種方法可確保每個應用程式僅擁有所需的權限,從而減少潛在的攻擊面。

若要在本機開發期間啟用驗證,請使用應用程式服務主體的認證來設定環境變數。 適用於 Python 的 Azure SDK 會偵測這些變數,並使用這些變數來驗證對 Azure 服務的要求。

在 Azure 中註冊應用程式

當您在 Azure 中註冊應用程式時,會建立應用程式服務主體物件。 您可以使用 Azure 入口網站或 Azure CLI 來執行此註冊。 註冊程式會在 Microsoft Entra ID 中建立應用程式註冊,並產生應用程式的服務主體物件。 服務主體物件可用來向 Azure 服務驗證應用程式。 應用程式註冊程式也會為應用程式產生用戶端密碼(密碼)。 此秘密可用來向 Azure 服務驗證應用程式。 用戶端密碼永遠不會儲存在原始檔控制中,而是儲存在 .env 應用程式目錄中的檔案中。 在執行階段,應用程式會讀取 .env 檔案,並設定適用於 Python 的 Azure SDK 用於驗證應用程式的環境變數。

下列步驟示範如何在 Azure 中註冊應用程式,並為應用程式建立服務主體。 Azure CLI 和 Azure 入口網站都顯示這些步驟。

Azure CLI 命令可以在 Azure Cloud Shell已安裝 Azure CLI 的工作站上執行。

首先,使用 az ad sp create-for-rbac 命令為應用程式建立新的服務主體。 此命令也會同時為應用程式建立應用程式註冊。

SERVICE_PRINCIPAL_NAME=<service-principal-name>
az ad sp create-for-rbac --name $SERVICE_PRINCIPAL_NAME

此命令的輸出如下所示。 請記下這些值,或讓此視窗保持開啟,因為您在後續步驟中需要這些值,而且無法再次檢視密碼 (客戶端密碼) 值。 不過,您可以稍後新增密碼,而不需視需要使服務主體或現有密碼失效。

{
  "appId": "00001111-aaaa-2222-bbbb-3333cccc4444",
  "displayName": "<service-principal-name>",
  "password": "Ee5Ff~6Gg7.-Hh8Ii9Jj0Kk1Ll2Mm3_Nn4Oo5Pp6",
  "tenant": "aaaabbbb-0000-cccc-1111-dddd2222eeee"
}

接下來,您需要取得 appID 值,並將其儲存到變數中。 此值可用來在本機開發環境中設定環境變數,讓適用於 Python 的 Azure SDK 可以使用服務主體向 Azure 進行驗證。

APP_ID=$(az ad sp list \
  --all \
  --query "[?displayName=='$SERVICE_PRINCIPAL_NAME'].appId | [0]" \
  --output tsv)

建立 Microsoft Entra 安全性群組以進行本機開發

由於多個開發人員通常會使用相同的應用程式,因此最好透過 Microsoft Entra 安全性群組來管理許可權。 建立包含應用程式本機開發所需角色的安全性群組,而不是個別將角色指派給每個開發人員的服務主體。 使用安全群組具有下列優點:

  • 由於角色是在群組層級指派,因此指派給每位開發人員的角色都能保證相同。
  • 如果應用程式需要新的角色,則只需要將它新增至應用程式的 Microsoft Entra 群組。
  • 如有新開發人員加入小組,則系統會為其建立新的應用程式服務主體並新增至群組,確定開發人員具備處理應用程式的適當權限。

az ad group create 命令是用來在 entra ID Microsoft中建立安全組。 --display-name--main-nickname 是必要參數。 提供給群組的名稱應根據應用程式而定。 在群組名稱中納入 'local-dev' 之類的字詞也很實用,這能指出群組的目的。

GROUP_DISPLAY_NAME="<group-name>"
GROUP_MAIL_NICKNAME="<group-mail-nickname>"
GROUP_DESCRIPTION="<group-description>"
az ad group create \
  --display-name $GROUP_DISPLAY_NAME \
  --mail-nickname $GROUP_MAIL_NICKNAME \
  --description $GROUP_DESCRIPTION

若要將成員新增至群組,您需要應用程式服務主體的物件識別碼,這與應用程式識別碼不同。 請用 az ad sp list 列出可用的服務主體。 --filter 參數命令會接受 OData 樣式篩選條件,且可如下所示用於篩選清單。 此 --query 參數將資料行限制為僅您感興趣的資料行。

SP_OBJECT_ID=$(az ad sp list \
  --filter "startswith(displayName,'$GROUP_DISPLAY_NAME')" \
  --query "[0].id" \
  --output tsv)

之後可用 az ad group member add 命令來將成員新增至群組。

az ad group member add \
    --group $GROUP_DISPLAY_NAME \
    --member-id $SP_OBJECT_ID

注意

根據預設,Microsoft Entra 安全組的建立僅限於目錄中的特定特殊許可權角色。 如果無法建立群組,請連絡目錄的系統管理員。 如果無法將成員新增至現有的群組,請連絡群組擁有者或目錄系統管理員。 若要深入了解,請參閱管理 Microsoft Entra 群組和群組成員資格

將角色指派給應用程式

接著,您必須決定應用程式針對哪些資源需要哪些角色 (權限),並將這些角色指派給應用程式。 在此範例中,角色會指派給步驟 2 中建立的 Microsoft Entra 群組。 角色可以在資源、資源群組或訂用帳戶範圍指派。 此範例示範如何在資源群組範圍中指派角色,因為大部分的應用程式都會將其所有 Azure 資源群組組成單一資源群組。

使用命令 az role assignment create 將角色指派給使用者、群組或應用程式服務主體。 您可以使用其物件識別碼來指定群組。 您可以使用其 appId 來指定應用程式服務主體。

RESOURCE_GROUP_NAME=<resource-group-name>
SUBSCRIPTION_ID=$(az account show --query id --output tsv)
ROLE_NAME=<role-name>
az role assignment create \
  --assignee "$APP_ID" \
  --scope "./subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP_NAME" \
  --role "$ROLE_NAME"

![!注意] 若要防止 Git Bash 處理 /subscriptions/...做為檔案路徑,在參數的字串 scope 前面加上 ./ ,並使用整個字串的雙引號。

若要取得可指派的角色名稱,請使用 az role definition list 命令。

az role definition list \
    --query "sort_by([].{roleName:roleName, description:description}, &roleName)" \
    --output table

例如,若要允許具有 appId 的應用程式服務主體 00001111-aaaa-2222-bbbb-3333cccc4444 對於訂閱 ID 為 的所有儲存帳戶中 Azure 儲存體 Blob 容器和數據進行讀取、寫入和刪除存取,請使用下列命令將應用程式服務主體指派給 aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e 角色,設定在 msdocs-python-sdk-auth-example 資源群組中。

az role assignment create --assignee 00001111-aaaa-2222-bbbb-3333cccc4444 \
    --scope "./subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/msdocs-python-sdk-auth-example" \
    --role "Storage Blob Data Contributor"

如需在資源或訂閱等級使用 Azure CLI 指派權限的更多資訊,請參閱使用 Azure CLI 指派 Azure 角色一文。

設定本機開發環境變數

物件會在 DefaultAzureCredential 執行階段在一組環境變數中尋找服務主體資訊。 由於大多數開發人員都會處理多個應用程式,因此在開發期間,可使用像 python-dotenv 這樣的套件,從儲存在應用程式目錄中的 .env 檔案中存取環境設定。 此設定會設定環境變數的範圍,以便只有此應用程式可以使用它們向 Azure 進行驗證。

檔案 .env 從不提交到版本控制,因為它包含 Azure 的應用程式密鑰。 適用於 Python 的標準 .gitignore 檔案會自動從簽入中排除 .env 檔案。

若要使用 python-dotenv 套件,請先在應用程式中安裝套件。

pip install python-dotenv

然後,在應用程式根目錄中建立 .env 檔案。 使用從應用程式註冊程式取得的值來設定環境變數值,如下所示:

  • AZURE_CLIENT_ID → 應用程式識別碼的值。
  • AZURE_TENANT_ID → 租戶 ID 值。
  • AZURE_CLIENT_SECRET → 為應用程式產生的密碼/認證。
AZURE_CLIENT_ID=00001111-aaaa-2222-bbbb-3333cccc4444
AZURE_TENANT_ID=aaaabbbb-0000-cccc-1111-dddd2222eeee
AZURE_CLIENT_SECRET=Ee5Ff~6Gg7.-Hh8Ii9Jj0Kk1Ll2Mm3_Nn4Oo5Pp6

最後,在應用程式的啟動代碼中,使用 python-dotenv 庫從 .env 檔案中讀取環境變數。

from dotenv import load_dotenv

if ( os.environ['ENVIRONMENT'] == 'development'):
    print("Loading environment variables from .env file")
    load_dotenv(".env")

在應用程式中實作 DefaultAzureCredential

若要向 Azure 驗證 Azure SDK 用戶端物件,您的應用程式應該使用 DefaultAzureCredential 套件中的 azure.identity 類別。 在此案例中, DefaultAzureCredential 會偵測環境變數 AZURE_CLIENT_IDAZURE_TENANT_IDAZURE_CLIENT_SECRET ,並設定並讀取這些變數,以取得要連線到 Azure 的應用程式服務主體資訊。

首先,將 azure.identity 套件新增至您的應用程式。

pip install azure-identity

接下來,針對在應用程式中建立 Azure SDK 用戶端物件的任何 Python 程式碼:

  1. 從模組匯入 DefaultAzureCredentialazure.identity 類別。
  2. 建立 DefaultAzureCredential 物件。
  3. DefaultAzureCredential 對象傳遞至 Azure SDK 用戶端物件建構函式。

下列程式碼區段示範其中一種範例。

from azure.identity import DefaultAzureCredential
from azure.storage.blob import BlobServiceClient

# Acquire a credential object
token_credential = DefaultAzureCredential()

blob_service_client = BlobServiceClient(
        account_url="https://<my_account_name>.blob.core.windows.net",
        credential=token_credential)