Python을 사용하여 Azure Data Lake Storage Gen2에서 ACL 관리

이 문서에서는 Python을 사용해 디렉터리 및 파일의 액세스 제어 목록을 가져오고, 설정하고, 업데이트하는 방법을 보여 줍니다.

부모 디렉터리 아래에 만들어진 새 자식 항목에서는 이미 ACL 상속을 사용할 수 있는 상태입니다. 그러나 각 자식 항목을 개별적으로 변경할 필요 없이 부모 디렉터리의 기존 자식 항목에서 ACL을 재귀적으로 추가, 업데이트, 제거할 수도 있습니다.

패키지(Python 패키지 인덱스) | 샘플 | 재귀 ACL 샘플 | API 참조 | Gen1에서 Gen2로 매핑 | 피드백 제공

필수 구성 요소

  • Azure 구독 자세한 내용은 Azure 무료 평가판 가져오기 를 참조하세요.

  • HNS(계층 구조 네임스페이스)를 사용하도록 설정된 스토리지 계정입니다. 이러한 지침에 따라 라이브러리를 만듭니다.

  • Azure CLI 버전 2.6.0 이상.

  • 다음 보안 권한 중 하나입니다.

    • 대상 컨테이너, 스토리지 계정, 부모 리소스 그룹 또는 구독으로 범위가 할당된 Storage Blob 데이터 소유자 역할이 할당된 프로비전된 Microsoft Entra ID 보안 주체입니다.

    • ACL 설정을 적용하려는 대상 컨테이너 또는 디렉터리를 소유하는 담당 사용자. ACL을 재귀적으로 설정하기 위해 대상 컨테이너 또는 디렉터리의 모든 자식 항목을 포함합니다.

    • 스토리지 계정 키.

프로젝트 설정

pip를 사용하여 Python용 Azure Data Lake Storage 클라이언트 라이브러리를 설치합니다.

pip install azure-storage-file-datalake

코드 파일 맨 위에 다음 import 문을 추가합니다.

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

계정에 연결

이 문서의 코드 조각을 사용하려면 스토리지 계정을 나타내는 DataLakeServiceClient 인스턴스를 만들어야 합니다.

Microsoft Entra ID를 사용하여 연결

참고 항목

Microsoft Entra ID를 사용하여 액세스를 권한 부여하는 경우 보안 주체에 Storage Blob 데이터 소유자 역할이 할당되었는지 확인합니다. ACL 권한이 적용되는 방식과 권한 변경의 영향에 대한 자세한 내용은 Azure Data Lake Storage Gen2의 액세스 제어 모델을 참조하세요.

Python용 Azure ID 클라이언트 라이브러리를 사용하여 Microsoft Entra ID로 애플리케이션을 인증할 수 있습니다.

먼저 다음 Azure RBAC(Azure 역할 기반 액세스 제어) 역할 중 하나를 보안 주체에 할당해야 합니다.

역할 ACL 설정 기능
Storage Blob 데이터 소유자 계정에 있는 모든 디렉터리 및 파일입니다.
Storage Blob 데이터 Contributor 보안 주체가 소유하는 디렉터리와 파일만 해당.

다음으로 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를 사용하여 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 또는 SAS(공유 액세스 서명)를 사용하여 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 항목은 개체 ID가 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx인 특정 사용자에게 읽기 권한을 제공합니다.

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 항목의 재귀적 제거

하나 이상의 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 프로세스를 실행하는 동안 액세스 제어 예외가 발생하는 경우 디렉터리 계층 구조에 있는 하나 이상의 자식 항목에 ACL을 적용하는 데 충분한 권한이 AD 보안 주체에게 없을 수 있습니다. 권한 오류가 발생하면 프로세스가 중지되고 연속 토큰이 제공됩니다. 권한 문제를 해결한 다음 연속 토큰을 사용하여 나머지 데이터 세트를 처리하세요. 이미 성공적으로 처리된 디렉터리와 파일은 다시 처리하지 않아도 됩니다. 재귀 ACL 프로세스를 다시 시작하도록 선택할 수도 있습니다. 부정적인 영향 없이 항목에 ACL을 다시 적용할 수 있습니다.

자격 증명

대상 스토리지 계정 또는 컨테이너 범위에서 Storage Blob 데이터 소유자 역할이 할당된 Microsoft Entra 보안 주체를 프로비전하는 것이 좋습니다.

성능

대기 시간을 줄이려면 스토리지 계정과 동일한 지역에 있는 Azure VM(가상 머신)에서 재귀 ACL 프로세스를 실행하는 것이 좋습니다.

ACL 한도

디렉터리 또는 파일에 적용할 수 있는 최대 ACL 수는 액세스 ACL 32개 및 기본 ACL 32개입니다. 자세한 내용은 Azure Data Lake Storage Gen2의 액세스 제어를 참조하세요.

참고 항목