ユーザー割り当てマネージド ID を使用して Django Web アプリを作成して Azure にデプロイする
このチュートリアルでは、 Django Web アプリを Azure App Service にデプロイします。 Web アプリは、Azure ロールベースのアクセス制御を使用して、ユーザー割り当て マネージド ID (パスワードレス接続) を使用して、 Azure Storage と Azure Database for PostgreSQL - フレキシブル サーバー リソースにアクセスします。 このコードでは、 DefaultAzureCredential クラスの Python 用 Azure ID クライアント ライブラリ が使用されています。 この DefaultAzureCredential
クラスは、App Service のマネージド ID が存在することを自動的に検出し、それを使用して他の Azure リソースにアクセスします。
このチュートリアルでは、ユーザー割り当てマネージド ID を作成し、App Service に割り当てて、データベースとストレージ アカウントのリソースにアクセスできるようにします。 システム割り当てマネージド ID の使用例については、「システム割り当てマネージド ID を使用して Flask Python Web アプリを作成して Azure にデプロイする」を参照してください。 ユーザー割り当てマネージド ID は、複数のリソースで使用でき、そのライフ サイクルは関連しているリソースのライフ サイクルと切り離されるために推奨されます。 マネージド ID 使用に関するベスト プラクティスの詳細については、「マネージド ID のベスト プラクティスのレコメンデーション」を参照してください。
このチュートリアルでは、Python Web アプリをデプロイし、 Azure CLI を使用して Azure リソースを作成する方法について説明します。 このチュートリアルのコマンドは、Bash シェルで実行するように記述されています。 ローカル環境や Azure Cloud Shell など、CLI がインストールされている Bash 環境であればチュートリアル コマンドを実行できます。 たとえば環境変数など、一部を変更して Windows コマンド シェルなどの他の環境でこれらのコマンドを実行できます。
サンプル アプリを入手する
Django サンプル アプリを使用して、このチュートリアルに従います。 サンプル アプリケーションを開発環境にダウンロードまたは複製します。
サンプルを複製します。
git clone https://github.com/Azure-Samples/msdocs-django-web-app-managed-identity.git
アプリケーション フォルダーに移動します。
cd msdocs-django-web-app-managed-identity
認証コードを確認する
サンプル Web アプリは、2 つの異なるデータ ストアに対して認証を行う必要があります。
- レビュー担当者から送信された写真を保存および取得する Azure Blob Storage サーバー。
- Azure Database for PostgreSQL - レストランとレビューを保存するフレキシブル サーバー データベース。
両方のデータ ストアに対して認証を行うために、DefaultAzureCredential を使用します。 DefaultAzureCredential
を使用すると、アプリは実行環境に応じて異なるサービス プリンシパルの ID で動作するよう設定できます。そのために、コードを変更する必要はありません。 たとえば、ローカル開発環境では、アプリは Azure CLI にサインインした開発者の ID で実行できます。一方、このチュートリアルのように Azure 環境では、ユーザー割り当てマネージド ID で実行できます。
いずれの場合も、アプリが実行されるセキュリティ プリンシパルには、アプリが使用する Azure リソースごとに、アプリが求めるアクションを実行できるロールが割り当てられている必要があります。 このチュートリアルでは、Azure CLI コマンドを使用して、ユーザー割り当てマネージド ID を作成し、Azure 上のアプリに割り当てます。 次に、作成した ID に Azure ストレージ アカウントと Azure Database for PostgreSQL サーバーに対する適切なロールを手動で割り当てます。 最後に、Azure 上のアプリの AZURE_CLIENT_ID
環境変数を設定して、マネージド ID を使用するように DefaultAzureCredential
を構成します。
ユーザー割り当てマネージド ID がアプリとそのランタイム環境で構成され、データ ストアに適切なロールが割り当てられると、DefaultAzureCredential
を使用して必要な Azure リソースに対して認証を行うことができます。
次のコードは、./restaurant_review/views.py
で写真をアップロードするための BLOB ストレージ クライアントを作成するために使用されます。 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
で Azure Database for PostgreSQL のアクセス トークンを取得するためにも使用されます。 この場合、資格情報インスタンスの 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 サービスを使用したアプリの認証の詳細については、「Azure SDK for Python を使用して 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
には、次のうちの 3 つのカテゴリの、8 から 128 文字が含まれている必要があります。英大文字、英小文字、数字、英数字以外の文字のうち、3 つのカテゴリの文字が含まれている必要があります。 ユーザー名またはパスワードを作成するとき、$
文字は 使用しない でください。 後で、これらの値を使用して環境変数を作成しますが、Python アプリの実行に使用する Linux コンテナー内では、環境変数内の$
文字に特殊な意味があります。az group create コマンドを使用して、リソース グループを作成します。
az group create --location $LOCATION --name $RESOURCE_GROUP_NAME
az postgres flexible-server create コマンドを使用して、PostgreSQL フレキシブル サーバーを作成します。 (このコマンドと後続のコマンドでは、Bash Shell ('\') の行継続文字が使用されます。 他のシェルの行連結文字を変更します。)
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 は価格レベルとコンピューティング構成の名前です。 詳しくは、「Azure Database for PostgreSQL の価格」をご覧ください。 利用可能な SKU を一覧表示するには、
az postgres flexible-server list-skus --location $LOCATION
を使用します。az postgres flexible-server ad-admin create コマンドを使用して、サーバーの Microsoft Entra 管理者として Azure アカウントを追加します。
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 アドレスを表示するツールや Web サイトを使って、コマンドの
<your IP>
を置き換えます。 たとえば、 IP アドレスを教えて Web サイトを使用できます。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 Service を作成してコードをデプロイする
サンプル アプリのルート フォルダーでこれらのコマンドを実行して、App Service を作成し、それにコードをデプロイします。
az webapp up コマンドを使用してアプリ サービスを作成します。
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の価格] のページをご覧ください。
az webapp config set コマンドを使用して、サンプル リポジトリで start.sh を使用するようにアプリ サービスを構成します。
az webapp config set \ --resource-group $RESOURCE_GROUP_NAME \ --name $APP_SERVICE_NAME \ --startup-file "start.sh"
ストレージ アカウントとコンテナーの作成
サンプル アプリでは、レビュー担当者から送信された写真がBLOBとしてAzure Storageに格納されます。
ユーザーがレビューで写真を送信すると、サンプル アプリはマネージド ID を使用してイメージをコンテナーに書き込み、
DefaultAzureCredential
ストレージ アカウントにアクセスします。ユーザーがレストランのレビューを表示すると、アプリは、関連付けられているレビューごとに、BLOB ストレージ内の写真へのリンクを返します。 ブラウザーで写真を表示するには、ストレージ アカウントで写真にアクセスできる必要があります。 BLOB データは、匿名 (非認証) アクセスによる読み取りを許可している必要があります。
このセクションでは、コンテナー内の BLOB へのパブリック読み取りアクセスを許可するストレージ アカウントとコンテナーを作成します。 後のセクションでは、ユーザー割り当てマネージド ID を作成し、ストレージ アカウントに 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
Note
コマンドが失敗した場合 (たとえば、ストレージ アカウントのネットワーク 規則によって要求がブロックされる可能性があることを示すエラーが表示された場合)、次のコマンドを入力して、コンテナーを作成するアクセス許可を持つ 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 を作成、ダウンロード、一覧表示する」を参照してください。 「所有者」、「共同作成者」、「ストレージ BLOB データ所有者」、「ストレージ BLOB データ共同作成者」など、いくつかの Azure ロールでは、ストレージ アカウントにコンテナーを作成できることに注意してください。
ユーザー割り当てマネージド ID を作成する
ユーザー割り当てマネージド ID を作成し、App Service に割り当てます。 マネージド ID は、データベースとストレージ アカウントにアクセスするために使用されます。
azidentitycreate コマンドを使用して、ユーザー割り当てのマネージド ID を作成し、後で使用できるようにクライアント ID を変数に出力します。
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 コマンドを使用してサブスクリプション ID を取得し、それをマネージド ID のリソース ID の構築に使用できる変数に出力します。
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
App Service にマネージド ID を割り当てるには、 az webapp identity assign コマンドを使用します。
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 コマンドを使用して、マネージド ID のクライアント ID とその他の 構成情報を含む 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
で行われます。
サンプル アプリ コードでは、ユーザー割り当てマネージド ID クライアント ID をコンストラクターに渡さずに DefaultAzureCredential
クラスのコンストラクターを使用します。 このシナリオでは、AZURE_CLIENT_ID
環境変数を確認することが代替策となります。この環境変数はアプリ設定として定義します。
AZURE_CLIENT_ID
環境変数が存在しない場合、システム割り当てマネージド ID が構成されていればそれが使用されます。 詳細については、「DefaultAzureCredential の概要」を参照してください。
マネージド ID 用にロールを作成します。
このセクションでは、マネージド ID のロールの割り当てを作成して、ストレージ アカウントとデータベースへのアクセスを有効にします。
az role assignment create コマンドを使用してストレージ アカウントへのアクセスを有効にするために、マネージド ID のロールの割り当てを作成します。
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 データベースに接続し、同じコマンドを実行してマネージド ID にロールを割り当てます。
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);"
コマンドの実行に問題がある場合は、PostgreSQL サーバーの Microsoft Entra 管理者としてユーザー アカウントを追加し、ファイアウォール規則で IP アドレスへのアクセスを許可していることを確認してください。 詳細については、「Azure PostgreSQL フレキシブル サーバーを作成する」セクションを参照してください。
Azure で Python Web アプリをテストする
サンプル Python アプリでは、 azure.identity パッケージとその DefaultAzureCredential
クラスを使用します。 Azure でアプリが実行されると、 DefaultAzureCredential
は App Services のマネージド ID が存在することを自動的に検出し、それを使用して他の Azure リソース (この場合はストレージと PostgreSQL) にアクセスします。 これらのリソースにアクセスするために、ストレージ キー、証明書、または資格情報を App Service に提供する必要はありません。
デプロイされたアプリケーションの URL (
http://$APP_SERVICE_NAME.azurewebsites.net
) を参照します。アプリが開始されるまでに 1 から 2 分かかる場合があります。 既定のサンプル アプリ ページではない既定のアプリ ページが表示される場合は、少し待ってからブラウザーを最新の情報に更新します。
サンプル アプリの機能をテストするには、レストランと、レストランの写真付きのレビューをいくつか追加します。
レストランとレビューの情報は Azure Database for PostgreSQL に保存され、写真は Azure Storage に保存されます。 スクリーンショットの例を次に示します。
クリーンアップ
このチュートリアルでは、すべての Azure リソースが同じリソース グループに作成されました。 az group delete コマンドを使用してリソース グループを削除すると、リソース グループ内のすべてのリソースが削除され、アプリに使用されているすべての Azure リソースを最も速く削除することができます。
az group delete --name $RESOURCE_GROUP_NAME
必要に応じて、 --no-wait
引数を追加すると、操作が完了する前にコマンドから戻ることができます。