サービス プリンシパルを使用したローカル開発時に Azure サービスに対して Python アプリを認証する

クラウド アプリケーションを作成する場合、開発者はローカル ワークステーションでアプリケーションをデバッグおよびテストする必要があります。 ローカル開発時に開発者のワークステーションでアプリケーションを実行する場合でも、アプリで使用されるすべての Azure サービスに対して認証する必要があります。 この記事では、ローカル開発時に使用する専用のアプリケーション サービス プリンシパル オブジェクトを設定する方法について説明します。

ローカルで実行されているアプリで開発者が .envファイルからアプリケーション サービス プリンシパルを取得し、その ID を使用して Azure リソースに接続する方法を示す図。

ローカル開発用の専用アプリケーション サービス プリンシパルを使用すると、アプリ開発時に最小限の特権の原則に従うことができます。 アクセス許可のスコープは開発時にアプリに必要なものだけに設定されるため、別のアプリで使用することを目的とした Azure リソースにアプリ コードが誤ってアクセスすることはありません。 また、これにより、開発環境でアプリに過剰な特権が与えられていたためにアプリが運用環境に移されたときに発生するバグも防ぐことができます。

アプリが Azure に登録されると、アプリケーション サービス プリンシパルがアプリ用に設定されます。 ローカル開発用にアプリを登録する場合は、次の手順を実行することをお勧めします。

  • アプリで作業する開発者ごとに個別のアプリ登録を作成します。 これにより、開発者ごとにローカル開発時に使用する個別のアプリケーション サービス プリンシパルが作成され、開発者が 1 つのアプリケーション サービス プリンシパルの資格情報を共有する必要がなくなります。
  • アプリごとに個別のアプリ登録を作成します。 これにより、アプリのアクセス許可のスコープがアプリに必要なものだけに設定されます。

ローカル開発時に、環境変数はアプリケーション サービス プリンシパルの ID で設定されます。 Azure SDK for Python では、これらの環境変数を読み取り、この情報を使用して、必要な Azure リソースに対してアプリが認証されます。

1 - Azure にアプリケーションを登録する

アプリケーション サービス プリンシパル オブジェクトは、Azure でアプリの登録を使用して作成されます。 これを行うには、Azure portal または Azure CLI のいずれかを使用します。

Azure CLI コマンドは、Azure Cloud Shell で、または Azure CLI がインストールされているワークステーション上で実行できます。

まず、az ad sp create-for-rbac コマンドを使用して、アプリの新しいサービス プリンシパルを作成します。 このコマンドは、アプリのアプリ登録も同時に作成します。

az ad sp create-for-rbac --name {service-principal-name}

このコマンドの出力は次のようになります。 これらの値をメモするか、次の手順でこれらの値が必要になり、パスワード (クライアント シークレット) 値を再び表示できなくなるため、このウィンドウを開いたままにします。 ただし、必要に応じて、サービス プリンシパルや既存のパスワードを無効にせずに、後で新しいパスワードを追加できます。

{
  "appId": "00000000-0000-0000-0000-000000000000",
  "displayName": "{service-principal-name}",
  "password": "abcdefghijklmnopqrstuvwxyz",
  "tenant": "33333333-3333-3333-3333-333333333333"
}

2 - ローカル開発用の Microsoft Entra セキュリティ グループを作成する

通常、アプリケーションで作業する開発者は複数いるため、個々のサービス プリンシパル オブジェクトにロールを割り当てるのではなく、Microsoft Entra セキュリティ グループを作成して、アプリがローカル開発で必要とするロール (アクセス許可) をカプセル化することをお勧めします。 これには次のような利点があります。

  • ロールはグループ レベルで割り当てられるため、すべての開発者に同じロールが割り当てられることが保証されます。
  • アプリに新しいロールが必要な場合は、アプリの Microsoft Entra グループに追加するだけで済みます。
  • 新しい開発者がチームに参加する場合は、アプリで作業するための適切なアクセス許可が開発者に与えられるように、その開発者用に新しいアプリケーション サービス プリンシパルを作成してグループに追加します。

Microsoft Entra ID でセキュリティ グループを作成するには、az ad group create コマンドを使用します。 --display-name パラメーターと --main-nickname パラメーターは必須です。 グループに指定する名前は、アプリケーションの名前に基づく必要があります。 また、グループの名前に "local-dev" のような語句を含め、グループの目的も示すと便利です。

az ad group create \
    --display-name MyDisplay \
    --mail-nickname MyDisplay  \
    --description "<group-description>"

コマンド出力のidプロパティ値をコピーします。 これはグループのオブジェクトIDです。 それは後のステップで必要になります。 このプロパティは、az広告グループ表示コマンドを使用して取得することもできます。

グループにメンバーを追加するには、アプリケーション サービス プリンシパルのオブジェクト ID が必要です。これは、アプリケーション ID とは異なります。 az ad sp list を使って、使用可能なサービス プリンシパルを一覧表示します。 --filter パラメーター コマンドは OData スタイル フィルターを受け取り、表示されているリストをフィルター処理するために使用できます。 --query パラメーターでは、必要な列のみに制限されます。

az ad sp list \
    --filter "startswith(displayName, 'msdocs')" \
    --query "[].{objectId:id, displayName:displayName}" \
    --output table

その後、az ad group member add コマンドを使用して、グループにメンバーを追加できます。

az ad group member add \
    --group <group-name> \
    --member-id <object-id>

Note

デフォルトでは、Microsoft Entraセキュリティグループの作成は、ディレクトリ内の特定の特権ロールに制限されます。 グループを作成できない場合は、ディレクトリの管理者に問い合わせてください。 既存のグループにメンバーを追加できない場合は、グループオーナーまたはディレクトリ管理者に問い合わせてください。 詳細については、「Microsoft Entraグループとグループ メンバシップの管理」を参照してください。

3 - アプリケーションにロールを割り当てる

次に、アプリで必要なリソースに対して必要なロール (アクセス許可) を決定し、それらのロールをアプリに割り当てる必要があります。 この例では、手順 2 で作成した Microsoft Entra グループにロールが割り当てられます。 役割は、リソース、リソースグループ、またはサブスクリプションの範囲で割り当てることができます。 次に、ほとんどのアプリケーションがすべてのAzureリソースを1つのリソースグループにグループ化するため、リソースグループスコープでロールを割り当てる例を示します。

azロール割り当て作成コマンドを使用して、Azureでユーザー、グループ、またはアプリケーションサービスのプリンシパルにロールが割り当てられます。 オブジェクトIDでグループを指定できます。 アプリケーション サービス プリンシパルを、appId で指定できます。

az role assignment create --assignee {appId or objectId} \
    --scope /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName} \
    --role "{roleName}" 

割り当て可能なロール名を取得するには、azロール定義リストコマンドを使用します。

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

たとえば、appId が 00000000-0000-0000-0000-000000000000 であるアプリケーション サービス プリンシパルに、ID が 11111111-1111-1111-1111-111111111111 であるサブスクリプションに含まれる msdocs-python-sdk-auth-example リソース グループのすべてのストレージ アカウントの Azure Storage blob コンテナとデータへの読み取り、書き込み、および削除のアクセスを許可するには、次のコマンドを使用して、アプリケーション サービス プリンシパルをストレージ BLOB データ共同作成者ロールに割り当てます。

az role assignment create --assignee 00000000-0000-0000-0000-000000000000 \
    --scope /subscriptions/11111111-1111-1111-1111-111111111111/resourceGroups/msdocs-python-sdk-auth-example \
    --role "Storage Blob Data Contributor"

Azure CLI を使用してリソースまたはサブスクリプション レベルでアクセス許可を割り当てる方法については、「Azure CLI を使用して Azure ロールを割り当てる」を参照してください。

4 - ローカル開発の環境変数を設定する

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=00000000-0000-0000-0000-000000000000
AZURE_TENANT_ID=11111111-1111-1111-1111-111111111111
AZURE_CLIENT_SECRET=abcdefghijklmnopqrstuvwxyz

最後に、アプリケーションのスタートアップ コードで、python-dotenv ライブラリを使用して、起動時に .env ファイルから環境変数を読み取ります。

from dotenv import load_dotenv

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

5 - アプリケーションに DefaultAzureCredential を実装する

Azure SDK クライアント オブジェクトを Azure に対して認証するには、アプリケーションで DefaultAzureCredential パッケージから azure.identity クラスを使用する必要があります。 このシナリオでは、DefaultAzureCredential で環境変数 AZURE_CLIENT_IDAZURE_TENANT_IDAZURE_CLIENT_SECRET が設定されていることを検出し、それらの変数を読み取り、Azure に接続するアプリケーション サービス プリンシパル情報を取得します。

まず、azure.identity パッケージを アプリケーションに追加します。

pip install azure-identity

次に、アプリで Azure SDK クライアント オブジェクトを作成する Python コードでは、次のことが必要になります。

  1. DefaultAzureCredential モジュールから azure.identity クラスをインポートします。
  2. DefaultAzureCredential オブジェクトを作成します。
  3. 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)