Azure Data Lake Storage で Python を使用して ACL を管理する
この記事では、Python を使用して、ディレクトリとファイルのアクセス制御リストを取得、設定、更新する方法について説明します。
ACL の継承は、親ディレクトリの下に作成された新しい子項目に対して既に利用可能です。 しかし、親ディレクトリの既存の子項目に対して ACL を再帰的に追加、更新、および削除することもできます。それぞれの子項目に対してこれらの変更を個別に行う必要はありません。
パッケージ (Python Package Index) | サンプル | 再帰 ACL のサンプル | API リファレンス | Gen1 から Gen2 へのマッピング | フィードバックを送る
前提条件
- Azure サブスクリプション - 無料アカウントを作成します。
- 階層型名前空間 (HNS) が有効になっている Azure ストレージ アカウント。 作成するには、こちらの手順に従います。
- python=3.8.10
- Azure CLI バージョン
2.6.0
以上。 - 次のセキュリティのアクセス許可のいずれか。
- ターゲット コンテナー、ストレージ アカウント、親リソース グループ、またはサブスクリプションのスコープでストレージ BLOB データ所有者ロールが割り当てられた、プロビジョニングされた Microsoft Entra ID セキュリティ プリンシパル。
- ACL 設定を適用する予定のターゲット コンテナーまたはディレクトリの所有ユーザー。 ACL を再帰的に設定する場合、これには、ターゲット コンテナーまたはディレクトリ内のすべての子項目が含まれます。
- ストレージ アカウント キー。
プロジェクトの設定
このセクションでは、Python 用 Azure Data Lake Storage クライアント ライブラリを操作するためのプロジェクトの準備について説明します。
プロジェクト ディレクトリから、pip install
コマンドを使用して、Azure Data Lake Storage と Azure ID のクライアント ライブラリのパッケージをインストールします。 Azure サービスへのパスワードレス接続には、azure-identity パッケージが必要です。
pip install azure-storage-file-datalake azure-identity
次にコード ファイルを開き、必要な import ステートメントを追加します。 この例では、以下を .py ファイルに追加します。
from azure.identity import DefaultAzureCredential
from azure.storage.filedatalake import DataLakeServiceClient
アカウントに接続する
この記事のコード例を実行するには、ストレージ アカウントを表す DataLakeServiceClient インスタンスを作成する必要があります。 Microsoft Entra ID の資格情報またはアカウント キーを使用してクライアント オブジェクトを認可できます。
Python 用 Azure ID クライアント ライブラリを使って、Microsoft Entra ID でアプリケーションを認証できます。
Note
Microsoft Entra ID を使用してアクセスを認可している場合は、セキュリティ プリンシパルにストレージ BLOB データ所有者ロールが割り当てられていることを確認します。 ACL アクセス許可の適用方法とその変更による影響の詳細については、「Azure Data Lake Storage のアクセス制御モデル」を参照してください。
まず、次のいずれかの Azure ロールベースのアクセス制御 (Azure RBAC) ロールをセキュリティ プリンシパルに割り当てます。
ロール | 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 アプリを認証する方法」を参照してください。
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 でのアクセス制御に関するページを参照してください。