開発者は、多くの場合、クラウド アプリケーションを構築するときに、アプリをローカルで実行してテストする必要があります。 ローカル開発中でも、アプリケーションは対話するすべての Azure サービスに対して認証を行う必要があります。 この記事では、ローカル開発時に専用のサービス プリンシパル ID を構成する方法について説明します。
ローカル開発用の専用アプリケーション サービス プリンシパルは、最小特権の原則に従います。 アプリが開発中に必要とする Azure リソースにのみアクセス権を付与します。 この制限付きアクセスにより、誤って他のリソースに到達するリスクが軽減されます。 また、より広範なアクセス許可によって問題が発生する可能性がある運用環境に移行するときに、アクセス許可関連のバグを防ぐのにも役立ちます。
Azure でローカル開発用にアプリケーションを登録する場合:
- 開発者ごとに個別のアプリ登録を作成する: この方法では、各開発者に独自のサービス プリンシパルが提供されるため、資格情報を共有する必要が回避され、より詳細なアクセス制御が可能になります。
- アプリケーションごとに個別のアプリ登録を作成する: この方法により、各アプリに必要なアクセス許可のみが付与され、潜在的な攻撃対象領域が減少します。
ローカル開発中に認証を有効にするには、アプリケーション サービス プリンシパルの資格情報を使用して環境変数を設定します。 Azure SDK for Python は、これらの変数を検出し、それらを使用して Azure サービスへの要求を認証します。
Azure にアプリケーションを登録する
アプリケーション サービス プリンシパル オブジェクトは、Azure にアプリを登録するときに作成されます。 この登録は、Azure portal または Azure CLI を使用して実行できます。 登録プロセスでは、Microsoft Entra ID でアプリの登録が作成され、アプリのサービス プリンシパル オブジェクトが生成されます。 サービス プリンシパル オブジェクトは、Azure サービスに対してアプリを認証するために使用されます。
アプリ登録プロセスでは、アプリのクライアント シークレット (パスワード) も生成されます。 このシークレットは、Azure サービスに対してアプリを認証するために使用されます。 クライアント シークレットはソース管理ではなく、アプリケーション ディレクトリの .env ファイルに格納されます。 実行時に、アプリケーションは .env ファイルを読み取り、Azure SDK for Python がアプリの認証に使用する環境変数を設定します。
次の手順では、Azure にアプリを登録し、アプリのサービス プリンシパルを作成する方法を示します。 手順は、Azure CLI と Azure portal の両方で示されています。
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 値を取得し、変数に格納する必要があります。 この値は、Azure SDK for Python がサービス プリンシパルを使用して Azure に対して認証できるように、ローカル開発環境で環境変数を設定するために使用されます。
APP_ID=$(az ad sp list \
--all \
--query "[?displayName=='$SERVICE_PRINCIPAL_NAME'].appId | [0]" \
--output tsv)
ローカル開発用の Microsoft Entra セキュリティ グループを作成する
通常、複数の開発者が同じアプリケーションで作業するため、Microsoft Entra セキュリティ グループを使用してアクセス許可を管理することをお勧めします。 各開発者のサービス プリンシパルにロールを個別に割り当てるのではなく、アプリがローカル開発に必要なロールを含むセキュリティ グループを作成します。 セキュリティ グループを使用すると、次の利点があります。
- ロールはグループ レベルで割り当てられるため、すべての開発者に同じロールが割り当てられることが保証されます。
- アプリに新しいロールが必要な場合は、アプリの Microsoft Entra グループに追加するだけで済みます。
- 新しい開発者がチームに参加する場合は、アプリで作業するための適切なアクセス許可が開発者に与えられるように、その開発者用に新しいアプリケーション サービス プリンシパルを作成してグループに追加します。
Microsoft Entra ID でセキュリティ グループを作成するには、az ad group create コマンドを使用します。
--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
グループにメンバーを追加するには、アプリケーション サービス プリンシパルのオブジェクト ID が必要です。これは、アプリケーション ID とは異なります。
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リソースを1つのリソースグループにグループ化するため、リソースグループスコープでロールを割り当てる例を示します。
az role assignment create コマンドを使用して、ユーザー、グループ、またはアプリケーション サービス プリンシパルにロールを割り当てます。 オブジェクトIDでグループを指定できます。 アプリケーション サービス プリンシパルを、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ロール定義リストコマンドを使用します。
az role definition list \
--query "sort_by([].{roleName:roleName, description:description}, &roleName)" \
--output table
たとえば、appId が 00001111-aaaa-2222-bbbb-3333cccc4444 であるアプリケーション サービス プリンシパルに、ID が であるサブスクリプションに含まれる aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e リソース グループのすべてのストレージ アカウントの Azure Storage blob コンテナとデータへの読み取り、書き込み、および削除のアクセスを許可するには、次のコマンドを使用して、アプリケーション サービス プリンシパルをストレージ BLOB データ共同作成者ロールに割り当てます。
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→ アプリ 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 SDK クライアント オブジェクトを Azure に対して認証するには、アプリケーションで DefaultAzureCredential パッケージから azure.identity クラスを使用する必要があります。 このシナリオでは、 DefaultAzureCredential は、 AZURE_CLIENT_ID、 AZURE_TENANT_ID、および AZURE_CLIENT_SECRET が設定されている環境変数を検出し、それらの変数を読み取って、Azure に接続するアプリケーション サービス プリンシパル情報を取得します。
まず、azure.identity パッケージを アプリケーションに追加します。
pip install azure-identity
次に、アプリで Azure SDK クライアント オブジェクトを作成する Python コードの場合:
-
DefaultAzureCredentialモジュールからazure.identityクラスをインポートします。 -
DefaultAzureCredentialオブジェクトを作成します。 - Azure SDK クライアント オブジェクト コンストラクターに
DefaultAzureCredentialオブジェクトを渡します。
この例を次のコード セグメントに示します。
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)