Partilhar via


Usar Python para gerenciar ACLs no Azure Data Lake Storage Gen2

Este artigo mostra como usar o Python para obter, definir e atualizar as listas de controle de acesso de diretórios e arquivos.

A herança de ACL já está disponível para novos itens filho criados em um diretório pai. Mas você também pode adicionar, atualizar e remover ACLs recursivamente nos itens filho existentes de um diretório pai sem ter que fazer essas alterações individualmente para cada item filho.

Pacote (Python Package Index) | Amostras | de ACL | recursiva Referência | da API Gen1 para Gen2 mapeamento | Enviar comentários

Pré-requisitos

  • Uma subscrição do Azure. Para obter mais informações, consulte Obter avaliação gratuita do Azure.

  • Uma conta de armazenamento com namespace hierárquico (HNS) habilitado. Siga estas instruções para criar um.

  • Versão da CLI 2.6.0 do Azure ou superior.

  • Uma das seguintes permissões de segurança:

Configure o seu projeto

Instale a biblioteca de cliente do Armazenamento do Azure Data Lake para Python usando pip.

pip install azure-storage-file-datalake

Adicione essas instruções de importação à parte superior do arquivo de código.

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

Conecte-se à conta

Para usar os trechos deste artigo, você precisará criar uma instância DataLakeServiceClient que represente a conta de armazenamento.

Conectar-se usando o Microsoft Entra ID

Nota

Se estiver a utilizar o Microsoft Entra ID para autorizar o acesso, certifique-se de que a sua entidade de segurança recebeu a função de Proprietário de Dados do Blob de Armazenamento. Para saber mais sobre como as permissões de ACL são aplicadas e os efeitos de alterá-las, consulte Modelo de controle de acesso no Azure Data Lake Storage Gen2.

Você pode usar a biblioteca de cliente de identidade do Azure para Python para autenticar seu aplicativo com o Microsoft Entra ID.

Primeiro, você terá que atribuir uma das seguintes funções de controle de acesso baseado em função do Azure (Azure RBAC) à sua entidade de segurança:

Função Capacidade de configuração de ACL
Proprietário dos Dados do Armazenamento de Blobs Todos os diretórios e arquivos na conta.
Contribuinte de Dados do Armazenamento de Blobs Somente diretórios e arquivos de propriedade da entidade de segurança.

Em seguida, crie uma instância DataLakeServiceClient e passe uma nova instância da classe 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

Para saber mais sobre como usar DefaultAzureCredential para autorizar o acesso a dados, consulte Visão geral: autenticar aplicativos Python no Azure usando o SDK do Azure.

Conectar-se usando uma chave de conta

Você pode autorizar o acesso aos dados usando as chaves de acesso da sua conta (Chave compartilhada). Este exemplo cria uma instância DataLakeServiceClient que é autorizada com a chave de conta.

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

Atenção

A autorização com chave compartilhada não é recomendada, pois pode ser menos segura. Para uma segurança ideal, desative a autorização através da Chave Partilhada para a sua conta de armazenamento, conforme descrito em Impedir autorização de Chave Partilhada para uma conta de Armazenamento do Azure.

O uso de chaves de acesso e cadeias de conexão deve ser limitado a aplicativos de prova de conceito iniciais ou protótipos de desenvolvimento que não acessam dados confidenciais ou de produção. Caso contrário, as classes de autenticação baseada em token disponíveis no SDK do Azure devem sempre ser preferidas ao autenticar nos recursos do Azure.

A Microsoft recomenda que os clientes usem o Microsoft Entra ID ou uma assinatura de acesso compartilhado (SAS) para autorizar o acesso aos dados no Armazenamento do Azure. Para obter mais informações, consulte Autorizar operações para acesso a dados.

Definir ACLs

Ao definir uma ACL, você substitui a ACL inteira, incluindo todas as suas entradas. Se desejar alterar o nível de permissão de uma entidade de segurança ou adicionar uma nova entidade de segurança à ACL sem afetar outras entradas existentes, atualize a ACL. Para atualizar uma ACL em vez de substituí-la, consulte a seção Atualizar ACLs deste artigo.

Esta seção mostra como:

  • Definir a ACL de um diretório
  • Definir a ACL de um arquivo

Definir a ACL de um diretório

Obtenha a lista de controle de acesso (ACL) de um diretório chamando o método DataLakeDirectoryClient.get_access_control e defina a ACL chamando o método DataLakeDirectoryClient.set_access_control.

Este exemplo obtém e define a ACL de um diretório chamado my-directory. A cadeia de caracteres dá ao usuário proprietário permissões de leitura, gravação e execução, dá ao grupo proprietário apenas permissões de rwxr-xrw- leitura e execução e dá a todos os outros permissões de leitura e gravação.

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)

Você também pode obter e definir a ACL do diretório raiz de um contêiner. Para obter o diretório raiz, chame o método FileSystemClient._get_root_directory_client .

Definir a ACL de um arquivo

Obtenha a lista de controle de acesso (ACL) de um arquivo chamando o método DataLakeFileClient.get_access_control e defina a ACL chamando o método DataLakeFileClient.set_access_control.

Este exemplo obtém e define a ACL de um arquivo chamado my-file.txt. A cadeia de caracteres dá ao usuário proprietário permissões de leitura, gravação e execução, dá ao grupo proprietário apenas permissões de rwxr-xrw- leitura e execução e dá a todos os outros permissões de leitura e gravação.

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)

Definir ACLs recursivamente

Ao definir uma ACL, você substitui a ACL inteira, incluindo todas as suas entradas. Se desejar alterar o nível de permissão de uma entidade de segurança ou adicionar uma nova entidade de segurança à ACL sem afetar outras entradas existentes, atualize a ACL. Para atualizar uma ACL em vez de substituí-la, consulte a seção Atualizar ACLs recursivamente deste artigo.

Defina ACLs recursivamente chamando o método DataLakeDirectoryClient.set_access_control_recursive .

Se você quiser definir uma entrada de ACL padrão , adicione a cadeia de caracteres ao início de cada cadeia default: de caracteres de entrada de ACL.

Este exemplo define a ACL de um diretório chamado my-parent-directory.

Esse método aceita um parâmetro booleano chamado is_default_scope que especifica se a ACL padrão deve ser definida. Se esse parâmetro for True, a lista de entradas ACL será precedida pela cadeia de caracteres default:. As entradas neste exemplo concedem as seguintes permissões: permissões de leitura, gravação e execução para o usuário proprietário, permissões de leitura e execução para o grupo proprietário e permissões de leitura para todos os outros. A última entrada ACL neste exemplo fornece a um usuário específico com as permissões de leitura do ID xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx do objeto.

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)

Para ver um exemplo que processa ACLs recursivamente em lotes especificando um tamanho de lote, consulte o exemplo Python.

Atualizar ACLs recursivamente

Ao atualizar uma ACL, você modifica a ACL em vez de substituí-la. Por exemplo, você pode adicionar uma nova entidade de segurança à ACL sem afetar outras entidades de segurança listadas na ACL. Para substituir a ACL em vez de atualizá-la, consulte a seção Definir ACLs deste artigo.

Para atualizar uma ACL recursivamente, crie um novo objeto ACL com a entrada ACL que você deseja atualizar e use esse objeto na operação de atualização da ACL. Não obtenha a ACL existente, apenas forneça entradas de ACL para serem atualizadas. Atualize uma ACL recursivamente chamando o método DataLakeDirectoryClient.update_access_control_recursive . Se desejar atualizar uma entrada de ACL padrão , adicione a cadeia de caracteres ao início de cada cadeia default: de caracteres de entrada de ACL.

Este exemplo atualiza uma entrada ACL com permissão de gravação.

Este exemplo define a ACL de um diretório chamado my-parent-directory. Esse método aceita um parâmetro booleano chamado is_default_scope que especifica se a ACL padrão deve ser atualizada. se esse parâmetro for True, a entrada ACL atualizada será precedida pela cadeia de caracteres 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)

Para ver um exemplo que processa ACLs recursivamente em lotes especificando um tamanho de lote, consulte o exemplo Python.

Remover entradas da ACL recursivamente

Você pode remover uma ou mais entradas da ACL. Para remover entradas ACL recursivamente, crie um novo objeto ACL para entrada ACL a ser removida e, em seguida, use esse objeto na operação remover ACL. Não obtenha a ACL existente, apenas forneça as entradas da ACL a serem removidas.

Remova as entradas da ACL chamando o método DataLakeDirectoryClient.remove_access_control_recursive . Se você quiser remover uma entrada de ACL padrão , adicione a cadeia de caracteres ao início da cadeia de caracteres de entrada de default: ACL.

Este exemplo remove uma entrada ACL da ACL do diretório chamado my-parent-directory. Esse método aceita um parâmetro booleano chamado is_default_scope que especifica se a entrada deve ser removida da ACL padrão. se esse parâmetro for True, a entrada ACL atualizada será precedida pela cadeia de caracteres 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)

Para ver um exemplo que processa ACLs recursivamente em lotes especificando um tamanho de lote, consulte o exemplo Python.

Recupere-se de falhas

Você pode encontrar erros de tempo de execução ou permissão. Para erros de tempo de execução, reinicie o processo desde o início. Erros de permissão podem ocorrer se a entidade de segurança não tiver permissão suficiente para modificar a ACL de um diretório ou arquivo que está na hierarquia de diretórios que está sendo modificada. Resolva o problema de permissão e, em seguida, opte por retomar o processo a partir do ponto de falha usando um token de continuação ou reiniciar o processo desde o início. Você não precisa usar o token de continuação se preferir reiniciar desde o início. Você pode reaplicar entradas de ACL sem qualquer impacto negativo.

Este exemplo retorna um token de continuação em caso de falha. O aplicativo pode chamar esse método de exemplo novamente após o erro ter sido resolvido e passar o token de continuação. Se esse método de exemplo for chamado pela primeira vez, o aplicativo poderá passar um valor de para o parâmetro de token de None continuação.

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

Para ver um exemplo que processa ACLs recursivamente em lotes especificando um tamanho de lote, consulte o exemplo Python.

Se desejar que o processo seja concluído ininterruptamente por erros de permissão, você pode especificar isso.

Para garantir que o processo seja concluído ininterruptamente, não passe um token de continuação para o método DataLakeDirectoryClient.set_access_control_recursive .

Este exemplo define entradas ACL recursivamente. Se esse código encontrar um erro de permissão, ele registrará essa falha e continuará a execução. Este exemplo imprime o número de falhas no console.

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)

Para ver um exemplo que processa ACLs recursivamente em lotes especificando um tamanho de lote, consulte o exemplo Python.

Melhores práticas

Esta seção fornece algumas diretrizes de práticas recomendadas para definir ACLs recursivamente.

Manipulando erros de tempo de execução

Um erro de tempo de execução pode ocorrer por vários motivos (por exemplo: uma interrupção ou um problema de conectividade do cliente). Se você encontrar um erro de tempo de execução, reinicie o processo de ACL recursivo. As ACLs podem ser reaplicadas aos itens sem causar um impacto negativo.

Manipulando erros de permissão (403)

Se você encontrar uma exceção de controle de acesso durante a execução de um processo de ACL recursivo, sua entidade de segurança do AD pode não ter permissão suficiente para aplicar uma ACL a um ou mais itens filho na hierarquia de diretórios. Quando ocorre um erro de permissão, o processo para e um token de continuação é fornecido. Corrija o problema de permissão e use o token de continuação para processar o conjunto de dados restante. Os diretórios e arquivos que já foram processados com sucesso não precisarão ser processados novamente. Você também pode optar por reiniciar o processo de ACL recursiva. As ACLs podem ser reaplicadas aos itens sem causar um impacto negativo.

Credenciais

Recomendamos que você provisione uma entidade de segurança do Microsoft Entra à qual tenha sido atribuída a função de Proprietário de Dados do Blob de Armazenamento no escopo da conta ou contêiner de armazenamento de destino.

Desempenho

Para reduzir a latência, recomendamos que você execute o processo de ACL recursiva em uma máquina virtual (VM) do Azure localizada na mesma região da sua conta de armazenamento.

Limites do LCA

O número máximo de ACLs que você pode aplicar a um diretório ou arquivo é de 32 ACLs de acesso e 32 ACLs padrão. Para obter mais informações, veja Controlo de acesso no Azure Data Lake Storage Gen2.

Consulte também