例: Python 用 Azure ライブラリを使用して Azure Storage にアクセスする
この記事では、Python アプリケーション コードで Azure クライアント ライブラリを使用して、Azure Blob ストレージ コンテナーにファイルをアップロードする方法を説明します。 この記事では、「例: Azure Storage の作成」に示されているリソースを作成していることを前提としています。
特に記載のない限り、この記事で使用されているコマンドはいずれも、Linux と macOS の bash および Windows のコマンド シェルで同じように動作します。
1. ローカルの開発環境を設定する
まだ行っていない場合は、このコードを実行できる環境を設定します。 次のことをお試しください。
venv
または任意のツールを使用して Python 仮想環境を構成します。 仮想環境は、ローカルまたは Azure Cloud Shell で作成し、そこでコードを実行できます。 仮想環境の使用を開始するには、必ず仮想環境をアクティブにします。Conda 環境を使用します。
Visual Studio Code または GitHub Codespaces で Dev コンテナを使用します。
2. ライブラリ パッケージをインストールする
requirements.txt ファイルに、必要なクライアント ライブラリ パッケージの行を追加して、ファイルを保存します。
azure-storage-blob
azure-identity
その後、ターミナルまたはコマンド プロンプトで、要件をインストールします。
pip install -r requirements.txt
3. アップロードするファイルを作成する
sample-source.txt という名前 のソース ファイルを作成します。 このファイル名は、コードで想定される名前です。
Hello there, Azure Storage. I'm a friendly file ready to be stored in a blob.
4. アプリ コードから Blob Storage を使用する
このセクションでは、「例: Azure Storage を作成する」で作成した BLOB コンテナーに内のデータにアクセスする 2 つの方法を示します。 BLOB コンテナー内のデータにアクセスするには、アプリが Azure で認証され、コンテナー内のデータにアクセスする権限を持っている必要があります。 このセクションでは、これを行うための 2 つの方法について説明します。
パスワードレス (推奨) 方式では、
DefaultAzureCredential
を使用してアプリを認証します。DefaultAzureCredential
は、開発者ツールの資格情報、アプリケーション サービス プリンシパル、マネージド ID など、一連の異なる資格情報を使用してアプリ (またはユーザー) を認証できるチェーン資格情報です。接続文字列方式では、接続文字列を使用してストレージ アカウントに直接アクセスします。
次のような理由から、可能な限りパスワードレス方式を使用することをお勧めします。
接続文字列方式では、接続元のエージェントをストレージ "アカウント" に対して認証します。そのアカウント内の個々のリソースに対して認証を行うわけではありません。 そのため、接続文字列では、許可する承認の範囲が必要以上に広くなってしまう可能性があります。
DefaultAzureCredential
を使用すると、Azure RBAC により、ストレージ リソースに対する最小限の権限をさらにきめ細かく、アプリを実行する ID に付与できます。接続文字列はアクセス情報をプレーン テキストで保持するため、適切に構築されていなかったり、セキュリティが適切に確保されていなかったりした場合に脆弱性のリスクが生じます。 そのような接続文字列が公開されれば、ストレージ アカウント内の広範なリソースへのアクセスに使用される可能性があります。
通常、接続文字列は環境変数に格納されるため、攻撃者から環境へのアクセスが可能になった場合、侵害を受ける危険性があります。
DefaultAzureCredential
でサポートされている資格情報の種類の多くについては、環境内にシークレットを格納する必要はありません。
DefaultAzureCredential
は、事前構成済みの資格情報チェーンです。 これは、最も一般的な認証フローおよび開発者ツールのほか、多くの環境をサポートするように設計されています。 DefaultAzureCredential
のインスタンスは、ランタイム環境、特定のよく知られている環境変数の値、(場合によっては) コンストラクターに渡されるパラメーターを組み合わせて、その情報に基づき、取得しようとしているトークンに対応する資格情報の種類を決定します。
次の手順では、アプリケーション サービス プリンシパルをアプリケーション ID として構成します。 アプリケーション サービス プリンシパルは、ローカル開発中の使用とオンプレミスでホストされるアプリでの使用の両方に適しています。 アプリケーション サービス プリンシパルを使用するように DefaultAzureCredential
を構成するには、環境変数 AZURE_CLIENT_ID
、AZURE_TENANT_ID
、および AZURE_CLIENT_SECRET
を設定します。
クライアント シークレットが構成されていることに注意してください。 これはアプリケーション サービス プリンシパルに必要ですが、シナリオによっては、環境変数にシークレットやパスワードを設定する必要のない資格情報を使用するように DefaultAzureCredential
を構成することもできます。
たとえばローカル開発で、構成された環境変数を使用してトークンを取得できない場合、DefaultAzureCredential
は、Azure CLI などの開発ツールに (既に) サインインしているユーザーを使用して、トークンを取得しようとします。Azure でホストされているアプリの場合は、マネージド ID を使用するように DefaultAzureCredential
を構成することもできます。 いずれの場合も、アプリのコードに変更は必要なく、構成とランタイム環境のみが変わるだけです。
次のコードを含んだ use_blob_auth.py という名前のファイルを作成します。 ステップは、コメントで説明しています。
import os import uuid from azure.identity import DefaultAzureCredential # Import the client object from the SDK library from azure.storage.blob import BlobClient credential = DefaultAzureCredential() # Retrieve the storage blob service URL, which is of the form # https://<your-storage-account-name>.blob.core.windows.net/ storage_url = os.environ["AZURE_STORAGE_BLOB_URL"] # Create the client object using the storage URL and the credential blob_client = BlobClient( storage_url, container_name="blob-container-01", blob_name=f"sample-blob-{str(uuid.uuid4())[0:5]}.txt", credential=credential, ) # Open a local file and upload its contents to Blob Storage with open("./sample-source.txt", "rb") as data: blob_client.upload_blob(data) print(f"Uploaded sample-source.txt to {blob_client.url}")
参照リンク:
AZURE_STORAGE_BLOB_URL
という名前の環境変数を作成します。「pythonazurestorage12345」をストレージアカウントの名前で置き換えます。
AZURE_STORAGE_BLOB_URL
環境変数は、この例のみで使用します。 Azure ライブラリでは使用されません。az ad sp create-for-rbac コマンドを使用して、アプリに対して新しいサービス プリンシパルを作成します。 このコマンドは、アプリのアプリ登録を同時に作成します。 サービス プリンシパルに、選択した名前を付けます。
az ad sp create-for-rbac --name <service-principal-name>
このコマンドの出力は次のようになります。 これらの値をメモするか、次の手順でこれらの値が必要になり、パスワード (クライアント シークレット) 値を再び表示できなくなるため、このウィンドウを開いたままにします。 ただし、必要に応じて、サービス プリンシパルや既存のパスワードを無効にせずに、後で新しいパスワードを追加できます。
{ "appId": "00001111-aaaa-2222-bbbb-3333cccc4444", "displayName": "<service-principal-name>", "password": "Aa1Bb~2Cc3.-Dd4Ee5Ff6Gg7Hh8Ii9_Jj0Kk1Ll2", "tenant": "aaaabbbb-0000-cccc-1111-dddd2222eeee" }
Azure CLI コマンドは、 Azure Cloud Shell で、または Azure CLI がインストールされているワークステーション上で実行できます。
アプリケーション サービス プリンシパルの環境変数を作成します。
前のコマンドの出力値を使用して、次の環境変数を作成します。 これらの変数は、アプリケーション サービス プリンシパルを使用するように
DefaultAzureCredential
に指示します。AZURE_CLIENT_ID
→ アプリ ID の値です。AZURE_TENANT_ID
→ テナント ID の値です。AZURE_CLIENT_SECRET
→アプリ用に生成されたパスワード/資格情報。
コードを実行しようとします (意図的に失敗します)。
python use_blob_auth.py
「この要求には、このアクセス許可を使用して操作を実行する権限はありません」というエラーを確認します。このエラーは、使用しているローカル サービス プリンシパルに Blob コンテナーへのアクセス許可がまだないことが原因で表示されます。
Azure CLI コマンド az role assignment create を使用して、BLOB コンテナーに対する "ストレージ BLOB データ共同作成者" アクセス許可をサービス プリンシパルに付与します。
az role assignment create --assignee <AZURE_CLIENT_ID> \ --role "Storage Blob Data Contributor" \ --scope "/subscriptions/<AZURE_SUBSCRIPTION_ID>/resourceGroups/PythonAzureExample-Storage-rg/providers/Microsoft.Storage/storageAccounts/pythonazurestorage12345/blobServices/default/containers/blob-container-01"
--assignee
因数は、サービス プリンシパルを識別します。 <AZURE_CLIENT_ID> プレースホルダーをサービス プリンシパルのアプリ ID で置き換えます。--scope
引数は、対象となるロールの割り当て先を指定するものです。 この例では、[Storage Blob Data Contributor] ロールを、「blob-container-01」という名前のコンテナーのサービス プリンシパルに許可します。PythonAzureExample-Storage-rg
とpythonazurestorage12345
をお使いのストレージ アカウントとストレージ アカウントの正確な名前を含むリソース グループに置き換えます。 また、必要に応じて、BLOB コンテナーの名前を調整します。 間違った名前を使用すると、"Can not perform requested operation on nested resource. Parent resource 'pythonazurestorage12345' not found." (ネストされたリソースに対して要求された操作を実行できません。親リソース 'pythonazurestorage12345' が見つかりません) というエラーが表示されます。<AZURE_SUBSCRIPTION_ID> プレース ホルダーをお使いの Azure サブスクリプション ID に置き換えます。 (az account show を実行する、出力の
id
プロパティからお使いのサブスクリプション ID を取得できます。)
ヒント
bash シェルを使用した際に、ロール割り当てコマンドが「接続アダプターが見つかりません」というエラーを返す場合、
export MSYS_NO_PATHCONV=1
を設定して、パス変換を回避します。 詳しくは、こちらの issue を参照してください。アクセス許可が反映されるまで 1、2 分待機した後、コードをもう一度実行して、今度は動作することを確認します。 アクセス許可のエラーが再度表示された場合は、もう少し待ってから、もう一度コードを試してください。
ロールの割り当てについて詳しくは、Azure CLI を使用してロールのアクセス許可を割り当てる方法に関するページを参照してください。
重要
前の手順では、アプリはアプリケーション サービス プリンシパルで実行されました。 アプリケーション サービス プリンシパルの構成には、クライアント シークレットが必要です。 ただし、同じコードを使用して、環境でパスワードやシークレットを明示的に構成する必要のない、異なる資格情報の種類でアプリを実行することもできます。 たとえば、開発中であれば、DefaultAzureCredential
は、Azure CLI 経由でサインインするために使用する資格情報など、開発者ツールの資格情報を使用できます。また、Azure でホストされているアプリの場合は、マネージド ID を使用できます。 詳細については、「Azure SDK for Python を使用して Azure サービスに対して Python アプリを認証する方法」を参照してください。
5. BLOB の作成を確認する
どちらかの方法のコードを実行したら、[Azure Portal] にアクセスし、Blob コンテナーに移動して、sample-source.txt ファイルと同じ内容の sample-blob-{random}.txt という名前の新しい Blob が既存しているかを確認します。
AZURE_STORAGE_CONNECTION_STRING
という名前の環境変数を作成した場合は、Azure CLI を使用して、az storage blob list を使用した Blob が既存するかを確認できます。
az storage blob list --container-name blob-container-01
パスワードレス認証を使用する手順に従った場合、ストレージ アカウントの接続文字列を使用して、--connection-string
パラメーターを前のコマンドに追加できます。 接続文字列を取得するには、az storage account show-connection-string コマンドを使用します。
az storage account show-connection-string --resource-group PythonAzureExample-Storage-rg --name pythonazurestorage12345 --output tsv
--connection-string
パラメーターの値として、接続文字列全体を使用します。
Note
コンテナーに対する "Azure ユーザー アカウントに" ロールが Azure ユーザー アカウントに設定されている場合は、次のコマンドを使用して、コンテナー内の BLOB を一覧表示できます。
az storage blob list --container-name blob-container-01 --account-name pythonazurestorage12345 --auth-mode login
6.リソースをクリーンアップする
この例で使用したリソース グループおよびストレージ リソースを保持する必要が無い場合は、az group delete コマンドを実行します。 リソース グループではサブスクリプションに継続的な料金は発生しませんが、リソース グループ内のストレージ アカウントなどのリソースには引き続き料金が発生する可能性があります。 アクティブに使用していないグループをクリーン アップすることをお勧めします。 --no-wait
引数を使用すると、操作が完了するまで待機するのではなく、直ちにコマンドから戻ることができます。
az group delete -n PythonAzureExample-Storage-rg --no-wait
コードから ResourceManagementClient.resource_groups.begin_delete
メソッドを使用してリソース グループを削除することもできます。 「例: リソース グループを作成する」のコードでは、使用方法を示しています。
パスワードレス認証を使用する手順に従った場合は、作成したアプリケーション サービス プリンシパルを削除することが推奨されます。 az ad app delete コマンドを使用できます。 <AZURE_CLIENT_ID> プレースホルダーをサービス プリンシパルのアプリ ID で置き換えます。
az ad app delete --id <AZURE_CLIENT_ID>