例: Python 用 Azure ライブラリを使用して Azure Storage にアクセスする

この記事では、Python アプリケーション コードで Azure クライアント ライブラリを使用して、Azure Blob ストレージ コンテナーにファイルをアップロードする方法を説明します。 この記事では、「例: Azure Storage の作成」に示されているリソースを作成していることを前提としています。

特に記載のない限り、この記事で使用されているコマンドはいずれも、Linux と macOS の bash および Windows のコマンド シェルで同じように動作します。

1: ローカルの開発環境を設定する

まだ行っていない場合は、このコードを実行できる環境を設定します。 次のことをお試しください。

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 を使用する

次の 2 つのセクションでは、例: Azure Storage を作成で作成した Blob コンテナーにアクセスする 2 つの方法を説明します。

最初の方法 (認証を使用) では、サービス プリンシパルを使用したローカル開発時に Azure サービスに対する Python アプリの認証で説明されている DefaultAzureCredential を使用してアプリを認証します。 この方法では最初に、アプリの ID に適切なアクセス許可を割り当てる必要があります。これが、推奨されるプラクティスです。

2 つ目の方法 (接続文字列を使用) では、接続文字列を使用して、ストレージアカウントに直接アクセスします。 こちらの方法の方が一見シンプルに見えますが、大きな欠点が 2 つあります。

  • 接続文字列は本質的に、接続元のエージェントをストレージ "アカウント" に対して認証するものであり、そのアカウント内の個々のリソースに対して認証を行うものではありません。 そのため、接続文字列では、許可する承認の範囲が必要以上に広くなってしまう可能性があります。

  • 接続文字列はアクセス情報をプレーン テキストで保持するため、適切に構築されていなかったり、セキュリティが適切に確保されていなかったりした場合に脆弱性のリスクが生じます。 そのような接続文字列が公開されれば、ストレージ アカウント内の広範なリソースへのアクセスに使用される可能性があります。

このような理由から、運用環境のコードでは認証方法を使用することをお勧めします。

4a: 認証付き Blob Storage を使用する

  1. 次のコードを含んだ 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}")
    

    参照リンク:

  2. AZURE_STORAGE_BLOB_URL という名前の環境変数を作成します。

    set AZURE_STORAGE_BLOB_URL=https://pythonazurestorage12345.blob.core.windows.net
    

    「pythonazurestorage12345」をストレージアカウントの名前で置き換えます。

    AZURE_STORAGE_BLOB_URL 環境変数は、この例のみで使用します。 Azure ライブラリでは使用されません。

  3. 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": "11111111-1111-1111-1111-111111111111"
    }
    

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

  4. アプリケーション サービス プリンシパルの環境変数を作成します。

    前のコマンドの出力値を使用して、次の環境変数を作成します。 これらの変数は、アプリケーション サービス プリンシパルを使用するように DefaultAzureCredential に指示します。

    • AZURE_CLIENT_ID → アプリ ID の値です。
    • AZURE_TENANT_ID → テナント ID の値です。
    • AZURE_CLIENT_SECRET →アプリ用に生成されたパスワード/資格情報。
    set AZURE_CLIENT_ID=00000000-0000-0000-0000-000000000000
    set AZURE_TENANT_ID=11111111-1111-1111-1111-111111111111
    set AZURE_CLIENT_SECRET=abcdefghijklmnopqrstuvwxyz
    
  5. コードを実行しようとします (意図的に失敗します)。

    python use_blob_auth.py
    
  6. 「この要求には、このアクセス許可を使用して操作を実行する権限はありません」というエラーを確認します。このエラーは、使用しているローカル サービス プリンシパルに Blob コンテナーへのアクセス許可がまだないことが原因で表示されます。

  7. az role assignment create Azure CLI コマンドを使用して、Blob コンテナーからサービス プリンシパルへの Contributor アクセス許可を許可します。

    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-rgpythonazurestorage12345 をお使いのストレージ アカウントとストレージ アカウントの正確な名前を含むリソース グループに置き換えます。 また、必要に応じて、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 を参照してください。

  8. アクセス許可が反映されるまで 1、2 分待機した後、コードをもう一度実行して、今度は動作することを確認します。 アクセス許可のエラーが再度表示された場合は、もう少し待ってから、もう一度コードを試してください。

ロールの割り当てについて詳しくは、Azure CLI を使用してロールのアクセス許可を割り当てる方法に関するページを参照してください。

4b: 接続文字列付き BLOB ストレージを使用する

  1. 次のコードを使用して、use_blob_conn_string.py という名前の Python ファイルを作成します。 ステップは、コメントで説明しています。

    import os
    import uuid
    
    # Import the client object from the SDK library
    from azure.storage.blob import BlobClient
    
    # Retrieve the connection string from an environment variable. Note that a
    # connection string grants all permissions to the caller, making it less
    # secure than obtaining a BlobClient object using credentials.
    conn_string = os.environ["AZURE_STORAGE_CONNECTION_STRING"]
    
    # Create the client object for the resource identified by the connection
    # string, indicating also the blob container and the name of the specific
    # blob we want.
    blob_client = BlobClient.from_connection_string(
        conn_string,
        container_name="blob-container-01",
        blob_name=f"sample-blob-{str(uuid.uuid4())[0:5]}.txt",
    )
    
    # 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}")
    
  2. AZURE_STORAGE_CONNECTION_STRING という名前の環境変数を作成します。この値は、ストレージ アカウントの完全な接続文字列です。 (この環境変数は、さまざまな Azure CLI コメントでも使用されます)。az storage account show-connection-string コマンドを実行すると、ストレージ アカウントの接続文字列を取得できます。

    az storage account show-connection-string --resource-group PythonAzureExample-Storage-rg --name pythonazurestorage12345
    

    PythonAzureExample-Storage-rgpythonazurestorage12345 をお使いのストレージ アカウントとストレージ アカウントの正確な名前を含むリソース グループに置き換えます。

    環境変数を設定するときは、引用符を含む出力内の connectionString プロパティの値全体を使用します。

  3. コードを実行します。

    python use_blob_conn_string.py
    

既に述べたように、この方法はシンプルではありますが、接続文字列によって、ストレージ アカウント内のすべての操作が承認されます。 前のセクションで説明したように、運用環境のコードでは、具体的なアクセス許可を使用することをお勧めします。

5. BLOB の作成を確認する

どちらかの方法のコードを実行したら、[Azure Portal] にアクセスし、Blob コンテナーに移動して、sample-source.txt ファイルと同じ内容の sample-blob-{random}.txt という名前の新しい Blob が既存しているかを確認します。

Azure portal page for the blob container, showing the uploaded file

AZURE_STORAGE_CONNECTION_STRING という名前の環境変数を作成した場合は、Azure CLI を使用して、az storage blob list を使用した Blob が既存するかを確認できます。

az storage blob list --container-name blob-container-01

認証付き Blob ストレージを使用する手順に従った場合、ストレージ アカウントの接続文字列を使用して、--connection-string パラメーターを前のコマンドに追加できます。 接続文字列を取得する方法については、「4b: 接続文字列で BLOB ストレージを使用する」の手順を参照してください。 引用符を含む接続文字列全体を使用します。

6: リソースをクリーンアップする

この例で使用したリソース グループおよびストレージ リソースを保持する必要が無い場合は、az group delete コマンドを実行します。 リソース グループではサブスクリプションに継続的な料金は発生しませんが、リソース グループ内のストレージ アカウントなどのリソースには料金が発生する可能性があります。 アクティブに使用していないグループをクリーン アップすることをお勧めします。 --no-wait 引数を使用すると、操作が完了するまで待機するのではなく、直ちにコマンドから戻ることができます。

az group delete -n PythonAzureExample-Storage-rg  --no-wait

コードから ResourceManagementClient.resource_groups.begin_delete メソッドを使用してリソース グループを削除することもできます。 「例: リソース グループを作成する」のコードでは、使用方法を示しています。

認証付き Blob ストレージを使用する手順に従った場合、作成したアプリケーション サービス プリンシパルを削除することが推奨されます。 az ad app delete コマンドを使用できます。 <AZURE_CLIENT_ID> プレースホルダーをサービス プリンシパルのアプリ ID で置き換えます。

az ad app delete --id <AZURE_CLIENT_ID>

関連項目