Azure Data Lake Storage Gen2 で Python を使用して ACL を管理する

この記事では、Python を使用して、ディレクトリとファイルのアクセス制御リストを取得、設定、更新する方法について説明します。

ACL の継承は、親ディレクトリの下に作成された新しい子項目に対して既に利用可能です。 しかし、親ディレクトリの既存の子項目に対して ACL を再帰的に追加、更新、および削除することもできます。それぞれの子項目に対してこれらの変更を個別に行う必要はありません。

パッケージ (Python Package Index) | サンプル | 再帰 ACL のサンプル | API リファレンス | Gen1 から Gen2 へのマッピング | フィードバックを送る

前提条件

  • Azure サブスクリプション。 詳細については、Azure 無料試用版の取得に関するページを参照してください。

  • 階層型名前空間 (HNS) が有効になっているストレージ アカウント。 作成するには、こちらの手順に従います。

  • Azure CLI バージョン 2.6.0 以上。

  • 次のセキュリティのアクセス許可のいずれか。

    • ターゲット コンテナー、ストレージ アカウント、親リソース グループ、またはサブスクリプションのスコープでストレージ BLOB データ所有者ロールが割り当てられた、プロビジョニングされた Microsoft Entra ID セキュリティ プリンシパル

    • ACL 設定を適用する予定のターゲット コンテナーまたはディレクトリの所有ユーザー。 ACL を再帰的に設定する場合、これには、ターゲット コンテナーまたはディレクトリ内のすべての子項目が含まれます。

    • ストレージ アカウント キー。

プロジェクトの設定

Python 向けの Azure Data Lake Storage クライアント ライブラリを、pip を使用してインストールします。

pip install azure-storage-file-datalake

次の import ステートメントを、コード ファイルの先頭に追加します。

from azure.storage.filedatalake import DataLakeServiceClient
from azure.identity import DefaultAzureCredential

アカウントに接続する

この記事のスニペットを使用するには、ストレージ アカウントを表す DataLakeServiceClient インスタンスを作成する必要があります。

Microsoft Entra ID を使用して接続する

Note

Microsoft Entra ID を使用してアクセスを承認している場合は、セキュリティ プリンシパルに ストレージ BLOB データ所有者ロールが割り当てられていることを確認してください。 ACL アクセス許可の適用方法とその変更による影響の詳細については、「Azure Data Lake Storage Gen2 のアクセス制御モデル」を参照してください。

Python 用 Azure ID クライアント ライブラリを使って、Microsoft Entra ID でアプリケーションを認証できます。

まず、次のいずれかのAzure ロールベースのアクセス制御 (Azure RBAC) ロールをセキュリティ プリンシパルに割り当てる必要があります。

Role ACL 設定機能
ストレージ BLOB データ所有者 アカウント内のすべてのディレクトリとファイル。
ストレージ BLOB データ共同作成者 セキュリティ プリンシパルによって所有されているディレクトリとファイルのみ。

次に、DataLakeServiceClient インスタンスを作成し、DefaultAzureCredential クラスの新しいインスタンスを渡します。

def get_service_client_token_credential(self, account_name) -> DataLakeServiceClient:
    account_url = f"https://{account_name}.dfs.core.windows.net"
    token_credential = DefaultAzureCredential()

    service_client = DataLakeServiceClient(account_url, credential=token_credential)

    return service_client

DefaultAzureCredential を使用してデータへのアクセスを認可する方法の詳細については、「概要: Azure SDK for Python を使用して Azure サービスに対して Python アプリを認証する方法」を参照してください。

アカウント キーを使用して接続する

アカウント アクセス キー (共有キー) を使用して、データへのアクセスを承認できます。 この例では、アカウント キーで承認された DataLakeServiceClient インスタンスを作成します。

def get_service_client_account_key(self, account_name, account_key) -> DataLakeServiceClient:
    account_url = f"https://{account_name}.dfs.core.windows.net"
    service_client = DataLakeServiceClient(account_url, credential=account_key)

    return service_client

注意事項

共有キーを使用した承認は、安全性が低い可能性があるため、お勧めしません。 最適なセキュリティを確保するには、「Azure Storage アカウントの共有キーによる承認を禁止する」の説明に従って、ストレージ アカウントの共有キーによる承認を無効にします。

アクセス キーと接続文字列の使用は、運用環境や機密データにアクセスしない概念実証アプリまたは開発プロトタイプに限定する必要があります。 それ以外の場合は、Azure リソースに対する認証時に、Azure SDK で使用できるトークンベースの認証クラスを常に優先する必要があります。

Microsoft は、クライアントが Microsoft Entra ID または Shared Access Signature (SAS) を使って、Azure Storage 内のデータへのアクセスを承認することをお勧めします。 詳細については、「Azure Storage 内のデータへのアクセスを承認する」を参照してください。

ACL を設定する

ACL を設定する場合は、ACL 全体 (そのすべてのエントリを含む) を置換します。 セキュリティ プリンシパルのアクセス許可レベルの変更または ACL への新しいセキュリティ プリンシパルの追加を、他の既存のエントリに影響を与えることなく行いたい場合は、代わりに ACL を "更新" する必要があります。 ACL を置換するのでなく更新するには、この記事の「ACL を更新する」セクションを参照してください。

ここでは、次の操作方法について説明します。

  • ディレクトリの ACL を設定する
  • ファイルの ACL を設定する

ディレクトリの ACL を設定する

DataLakeDirectoryClient.get_access_control メソッドを呼び出してディレクトリのアクセス制御リスト (ACL) を取得し、DataLakeDirectoryClient.set_access_control メソッドを呼び出して ACL を設定します。

この例では、my-directory という名前のディレクトリの ACL を取得して設定します。 rwxr-xrw- 文字列により、所有ユーザーには読み取り、書き込み、および実行のアクセス許可が、所有グループには読み取りと実行のアクセス許可のみが、他のすべてのユーザーに読み取りと書き込みのアクセス許可が付与されます。

def manage_directory_permissions():
    try:
        file_system_client = service_client.get_file_system_client(file_system="my-file-system")

        directory_client = file_system_client.get_directory_client("my-directory")
        
        acl_props = directory_client.get_access_control()
        
        print(acl_props['permissions'])
        
        new_dir_permissions = "rwxr-xrw-"
        
        directory_client.set_access_control(permissions=new_dir_permissions)
        
        acl_props = directory_client.get_access_control()
        
        print(acl_props['permissions'])
    
    except Exception as e:
     print(e)

また、コンテナーのルート ディレクトリの ACL を取得して設定することもできます。 ルート ディレクトリを取得するには、FileSystemClient._get_root_directory_client メソッドを呼び出します。

ファイルの ACL を設定する

DataLakeFileClient.get_access_control メソッドを呼び出してファイルのアクセス制御リスト (ACL) を取得し、DataLakeFileClient.set_access_control メソッドを呼び出して ACL を設定します。

この例では、my-file.txt という名前のファイルの ACL を取得して設定します。 rwxr-xrw- 文字列により、所有ユーザーには読み取り、書き込み、および実行のアクセス許可が、所有グループには読み取りと実行のアクセス許可のみが、他のすべてのユーザーに読み取りと書き込みのアクセス許可が付与されます。

def manage_file_permissions():
    try:
        file_system_client = service_client.get_file_system_client(file_system="my-file-system")

        directory_client = file_system_client.get_directory_client("my-directory")
        
        file_client = directory_client.get_file_client("uploaded-file.txt")

        acl_props = file_client.get_access_control()
        
        print(acl_props['permissions'])
        
        new_file_permissions = "rwxr-xrw-"
        
        file_client.set_access_control(permissions=new_file_permissions)
        
        acl_props = file_client.get_access_control()
        
        print(acl_props['permissions'])

    except Exception as e:
     print(e)

ACL を再帰的に設定する

ACL を "設定する" 場合は、ACL 全体 (そのすべてのエントリを含む) を置換します。 セキュリティ プリンシパルのアクセス許可レベルの変更または ACL への新しいセキュリティ プリンシパルの追加を、他の既存のエントリに影響を与えることなく行いたい場合は、代わりに ACL を "更新" する必要があります。 ACL を置換するのでなく更新するには、この記事の「ACL を再帰的に更新する」セクションを参照してください。

DataLakeDirectoryClient.set_access_control_recursive メソッドを呼び出すことによって、ACL を再帰的に設定します。

既定の ACL エントリを設定する場合は、各 ACL エントリ文字列の先頭に文字列 default: を追加します。

この例では、my-parent-directory という名前のディレクトリの ACL を設定します。

このメソッドは、既定の ACL を設定するかどうかを指定する is_default_scope という名前のブール型パラメーターを受け取ります。 そのパラメーターが True の場合、ACL エントリの一覧の前に文字列 default: が付きます。 この例のエントリでは、所有ユーザーには読み取り、書き込み、実行のアクセス許可を付与し、所有グループには読み取りと実行のアクセス許可を付与し、他のすべてのユーザーには読み取りアクセス許可を付与します。 この例の最後の ACL エントリでは、xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx というオブジェクト ID を持つ特定のユーザーに、読み取りアクセス許可を付与しています。

def set_permission_recursively(is_default_scope):
    
    try:
        file_system_client = service_client.get_file_system_client(file_system="my-container")

        directory_client = file_system_client.get_directory_client("my-parent-directory")

        acl = 'user::rwx,group::r-x,other::r--,user:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:r--'   

        if is_default_scope:
           acl = 'default:user::rwx,default:group::r-x,default:other::r--,default:user:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:r--'

        directory_client.set_access_control_recursive(acl=acl)
        
        acl_props = directory_client.get_access_control()
        
        print(acl_props['permissions'])

    except Exception as e:
     print(e)

バッチ サイズを指定してバッチ内の ACL を再帰的に処理する例については、Python のサンプルをご覧ください。

ACL を再帰的に更新する

ACL を "更新する" 場合は、ACL を置換するのでなく ACL を変更します。 たとえば、ACL にリストされている他のセキュリティ プリンシパルに影響を与えることなく、新しいセキュリティ プリンシパルを ACL に追加することができます。 ACL を更新するのでなく、置換する場合は、この記事の「ACL を設定する」セクションを参照してください。

ACL を再帰的に更新するには、更新したい ACL エントリを含む新しい ACL オブジェクトを作成してから、そのオブジェクトを ACL の更新操作で使用します。 既存の ACL は取得せずに、更新する ACL エントリを指定するだけです。 DataLakeDirectoryClient.update_access_control_recursive メソッドを呼び出すことによって、ACL を再帰的に更新します。 既定の ACL エントリを更新する場合は、各 ACL エントリ文字列の先頭に文字列 default: を追加します。

この例では、書き込みアクセス許可を持つ ACL エントリを更新します。

この例では、my-parent-directory という名前のディレクトリの ACL を設定します。 このメソッドは、既定の ACL を更新するかどうかを指定する is_default_scope という名前のブール型パラメーターを受け取ります。 そのパラメーターが True の場合、更新された ACL エントリの前に文字列 default: が付きます。

def update_permission_recursively(is_default_scope):
    
    try:
        file_system_client = service_client.get_file_system_client(file_system="my-container")

        directory_client = file_system_client.get_directory_client("my-parent-directory")
              
        acl = 'user:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:rwx'   

        if is_default_scope:
           acl = 'default:user:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:rwx'

        directory_client.update_access_control_recursive(acl=acl)

        acl_props = directory_client.get_access_control()
        
        print(acl_props['permissions'])

    except Exception as e:
     print(e)

バッチ サイズを指定してバッチ内の ACL を再帰的に処理する例については、Python のサンプルをご覧ください。

ACL エントリを再帰的に削除する

1 つ以上の ACL エントリを削除できます。 ACL エントリを再帰的に削除するには、削除する ACL エントリ用に新しい ACL オブジェクトを作成してから、そのオブジェクトを ACL の削除操作で使用します。 既存の ACL は取得せずに、削除する ACL エントリを指定するだけです。

DataLakeDirectoryClient.remove_access_control_recursive メソッドを呼び出すことによって、ACL エントリを削除します。 既定の ACL エントリを削除する場合は、ACL エントリ文字列の先頭に文字列 default: を追加します。

この例では、my-parent-directory という名前のディレクトリの ACL から ACL エントリを削除します。 このメソッドは、既定の ACL からエントリを削除するかどうかを指定する is_default_scope という名前のブール型パラメーターを受け取ります。 そのパラメーターが True の場合、更新された ACL エントリの前に文字列 default: が付きます。

def remove_permission_recursively(is_default_scope):

    try:
        file_system_client = service_client.get_file_system_client(file_system="my-container")

        directory_client = file_system_client.get_directory_client("my-parent-directory")

        acl = 'user:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'

        if is_default_scope:
           acl = 'default:user:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'

        directory_client.remove_access_control_recursive(acl=acl)

    except Exception as e:
     print(e)

バッチ サイズを指定してバッチ内の ACL を再帰的に処理する例については、Python のサンプルをご覧ください。

エラーからの復旧

実行時エラーまたはアクセス許可エラーが発生する可能性があります。 実行時エラーが発生した場合は、プロセスを最初から再開します。 アクセス許可エラーは、セキュリティ プリンシパルに、変更対象のディレクトリ階層内にあるディレクトリまたはファイルの ACL を変更するための十分なアクセス許可がない場合に発生する可能性があります。 アクセス許可の問題を解決してから、継続トークンを使用してエラーの発生時点からプロセスを再開するか、最初からプロセスを再開するかを選択します。 最初から再開する場合は、継続トークンを使用する必要はありません。 ACL エントリは、悪影響を及ぼすことなく再適用できます。

この例では、エラーが発生した場合に継続トークンを返します。 アプリケーションでは、エラーが解決された後にこの例のメソッドを再び呼び出し、継続トークンを渡すことができます。 この例のメソッドが初めて呼び出される場合は、アプリケーションで継続トークン パラメーターに対して None の値を渡すことができます。

def resume_set_acl_recursive(continuation_token):
    
    try:
        file_system_client = service_client.get_file_system_client(file_system="my-container")

        directory_client = file_system_client.get_directory_client("my-parent-directory")
              
        acl = 'user::rwx,group::rwx,other::rwx,user:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:r--'

        acl_change_result = directory_client.set_access_control_recursive(acl=acl, continuation=continuation_token)

        continuation_token = acl_change_result.continuation

        return continuation_token
        
    except Exception as e:
     print(e) 
     return continuation_token

バッチ サイズを指定してバッチ内の ACL を再帰的に処理する例については、Python のサンプルをご覧ください。

アクセス許可エラーによって中断されずにプロセスを完了したい場合は、それを指定できます。

プロセスが中断されずに確実に完了されるようにするには、DataLakeDirectoryClient.set_access_control_recursive メソッドに後続トークンを渡さないようにします。

この例では、ACL エントリを再帰的に設定します。 このコードでアクセス許可エラーが発生した場合は、そのエラーが記録されて、実行が継続されます。 この例では、エラーの数をコンソールに出力します。

def continue_on_failure():
    
    try:
        file_system_client = service_client.get_file_system_client(file_system="my-container")

        directory_client = file_system_client.get_directory_client("my-parent-directory")
              
        acl = 'user::rwx,group::rwx,other::rwx,user:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:r--'

        acl_change_result = directory_client.set_access_control_recursive(acl=acl)

        print("Summary: {} directories and {} files were updated successfully, {} failures were counted."
          .format(acl_change_result.counters.directories_successful, acl_change_result.counters.files_successful,
                  acl_change_result.counters.failure_count))
        
    except Exception as e:
     print(e)

バッチ サイズを指定してバッチ内の ACL を再帰的に処理する例については、Python のサンプルをご覧ください。

ベスト プラクティス

このセクションでは、ACL を再帰的に設定するためのベスト プラクティス ガイドラインについて説明します。

実行時エラーの処理

実行時エラーは、さまざまな理由で発生する可能性があります (たとえば、停電やクライアント接続の問題など)。 実行時エラーが発生した場合は、再帰的な ACL プロセスを再開します。 ACL は、悪影響を及ぼすことなく項目に再適用できます。

アクセス許可エラー (403) の処理

再帰的な ACL プロセスの実行中にアクセス制御の例外が発生した場合、AD のセキュリティ プリンシパルに、ディレクトリ階層内にある 1 つ以上の子項目に ACL を適用するための十分なアクセス許可がない可能性があります。 アクセス許可エラーが発生すると、プロセスが停止し、継続トークンが提供されます。 アクセス許可の問題を修正してから、継続トークンを使用して残りのデータセットを処理します。 既に正常に処理済みのディレクトリとファイルをもう一度処理する必要はありません。 再帰的な ACL プロセスを再開することも選択できます。 ACL は、悪影響を及ぼすことなく項目に再適用できます。

資格情報

ターゲット ストレージ アカウントまたはコンテナーのスコープ内のストレージ BLOB データ所有者ロールが割り当てられている Microsoft Entra セキュリティ プリンシパルをプロビジョニングすることをお勧めします。

パフォーマンス

待機時間を短縮するには、ストレージ アカウントと同じリージョンにある Azure 仮想マシン (VM) で再帰的な ACL プロセスを実行することをお勧めします。

ACL の制限

ディレクトリまたはファイルに適用できる ACL の最大数は、アクセス ACL が 32 個と既定 ACL が 32 個です。 詳細については、Azure Data Lake Storage Gen2 でのアクセス制御に関するページを参照してください。

関連項目