Usar o Python para gerenciar ACLs no Azure Data Lake Storage
Veja neste artigo como usar o Python para obter, configurar 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 precisar fazer essas alterações individualmente em cada item filho.
Pacote (Índice de Pacote do Python) | Amostras | Amostras de ACL recursiva | Referência de API | Mapeamento de Gen1 para Gen2 | Enviar comentários
Pré-requisitos
- Assinatura do Azure – Crie uma gratuitamente.
- Uma conta de armazenamento precisa ter o HNS (namespace hierárquico) habilitado. Siga estas instruções para criar um.
- Python 3.8+
- CLI do Azure versão
2.6.0
ou superior - Uma das seguintes permissões de segurança:
- Uma entidade de segurança do Microsoft Entra ID provisionada à qual foi atribuída a função de Proprietário de Dados do Blob de Armazenamento no escopo do contêiner, conta de armazenamento, grupo de recursos pai ou assinatura de destino.
- Usuário proprietário do contêiner ou diretório de destino ao qual você planeja aplicar as configurações de ACL. Para definir ACLs recursivamente, isso inclui todos os itens filho no contêiner ou diretório de destino.
- Chave de conta de armazenamento.
Configurar o seu projeto
Esta seção fornece instruções sobre como preparar um projeto para funcionar com a biblioteca de clientes do Azure Data Lake Storage para Python.
No diretório do projeto, instale pacotes para as bibliotecas de cliente do Azure Data Lake Storage e do Azure Identity usando o comando pip install
. O pacote azure-identity é necessário para conexões sem senha com os serviços do Azure.
pip install azure-storage-file-datalake azure-identity
Em seguida, abra o arquivo de código e adicione as instruções de importação necessárias. Neste exemplo, adicionamos o seguinte ao nosso arquivo .py:
from azure.identity import DefaultAzureCredential
from azure.storage.filedatalake import DataLakeServiceClient
Conectar à conta
Para usar os snippets de código neste artigo, será necessário criar uma instância de DataLakeServiceClient que represente a conta de armazenamento. Você pode autorizar o objeto cliente com as credenciais do Microsoft Entra ID ou com uma chave de conta.
Você pode usar a Biblioteca de clientes de identidade do Azure para Python para autenticar seu aplicativo com a ID do Microsoft Entra.
Observação
Se estiver utilizando o Microsoft Entra ID para autorizar o acesso, verifique se a entidade de segurança foi atribuída à função 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.
Primeiro, atribua uma das seguintes funções do Azure RBAC (Controle de acesso baseado em função do Azure) à sua entidade de segurança:
Função | Capacidade de configuração de ACL |
---|---|
Proprietário de Dados do Blob de Armazenamento | Todos os diretórios e arquivos na conta. |
Colaborador de dados de blob de armazenamento | Somente diretórios e arquivos de propriedade da entidade de segurança. |
Em seguida, crie uma instância DataLakeServiceClient e passe em 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 aos dados, confira Visão geral: autenticar aplicativos Python no Azure usando o SDK do Azure.
Definir ACLs
Aodefiniruma ACL, vocêsubstitui toda a ACL, incluindo todas as entradas. Se você quiser 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, deverá atualizar a ACL. Para atualizar uma ACL em vez de substituí-la, confira a seção Atualizar ACLs deste artigo.
Esta seção mostra como:
- Definir o ACL de um diretório
- Definir o ACL de um arquivo.
Definir o ACL de um diretório
Obtenha a ACL (lista de controle de acesso) 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 rwxr-xrw-
fornece as permissões de leitura, gravação e execução do usuário proprietário, fornece ao grupo proprietário somente permissões de leitura e execução e concede 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)
Também é possível 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 o ACL de um arquivo.
Obtenha a ACL (lista de controle de acesso) 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 rwxr-xrw-
fornece as permissões de leitura, gravação e execução do usuário proprietário, fornece ao grupo proprietário somente permissões de leitura e execução e concede 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
Aodefiniruma ACL, vocêsubstituitoda a ACL, incluindo todas as entradas. Se você quiser 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, deverá atualizar a ACL. Para atualizar uma ACL em vez de substituí-la, confira a seção Atualizar ACLs recursivamente deste artigo.
Defina ACLs recursivamente chamando o método DataLakeDirectoryClient.set_access_control_recursive.
Para definir uma entrada de ACL padrão, adicione a cadeia de caracteres default:
ao início de cada cadeia 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 booliano chamado is_default_scope
que especifica se a ACL padrão deve ser definida. Se esse parâmetro for True
, a lista de entradas de 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 de ACL neste exemplo concede a um usuário específico as permissões de leitura da ID de objeto 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)
Para ver um exemplo que processa ACLs recursivamente em lotes especificando um tamanho de lote, confira o exemplo do 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, confira a seção Definir ACLs deste artigo.
Para atualizar uma ACL recursivamente, crie um novo objeto ACL com a entrada de ACL que você quer atualizar. Em seguida, use esse objeto na operação para atualizar a ACL. Não obtenha a ACL existente, basta fornecer as entradas de ACL a serem atualizadas. Atualize ACLs recursivamente chamando o método DataLakeDirectoryClient.update_access_control_recursive. Para atualizar uma entrada de ACL padrão, adicione a cadeia de caracteres default:
ao início de cada cadeia 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 booliano chamado is_default_scope
que especifica se a ACL padrão deve ser atualizada. Se esse parâmetro for True
, a entrada de 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, confira o exemplo do Python.
Remover entradas de ACL recursivamente
Você pode remover uma ou mais entradas de ACL. Para fazer isso recursivamente, crie um novo objeto ACL para a entrada de ACL a ser removida. Em seguida, use esse objeto na operação de remoção de ACL. Não obtenha a ACL existente, basta fornecer as entradas da ACL a serem removidas.
Remova as entradas de ACL chamando o método DataLakeDirectoryClient.remove_access_control_recursive. Para remover uma entrada de ACL padrão, adicione a cadeia de caracteres default:
ao início de cada cadeia de caracteres de entrada de ACL.
Este exemplo remove uma entrada ACL da ACL do diretório chamado my-parent-directory
. Esse método aceita um parâmetro booliano chamado is_default_scope
que especifica se a ACL padrão deve ser removida. Se esse parâmetro for True
, a entrada da 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, confira o exemplo do Python.
Recuperar de falhas
Talvez você encontre erros de runtime ou de permissão. Para erros de runtime, reinicie o processo desde o início. Poderão ocorrer erros de permissão 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ório que está sendo modificada. Resolva o problema de permissão e, em seguida, escolha retomar o processo no ponto de falha usando um token de continuação ou reiniciar o processo do início. Você não precisará usar o token de continuação se preferir reiniciar desde o início. É possível reaplicar entradas de ACL sem nenhum impacto negativo.
Este exemplo retorna um token de continuação no caso de uma falha. O aplicativo pode chamar esse método de exemplo novamente depois que o erro for 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 deNone
para o parâmetro de token de 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, confira o exemplo do Python.
Se você quiser que o processo seja concluído sem interrupções por erros de permissão, poderá especificar isso.
Para garantir que o processo seja concluído sem interrupções, não passe um token de continuação para o método DataLakeDirectoryClient.set_access_control_recursive.
Este exemplo define as entradas de 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, confira o exemplo do Python.
Práticas recomendadas
Esta seção fornece algumas diretrizes de práticas recomendadas para definir as ACLs recursivamente.
Manipulanr erros de tempo de execução
Um erro de runtime pode ocorrer por vários motivos (por exemplo: uma interrupção ou um problema de conectividade de cliente). Se você encontrar um erro de runtime, reinicie o processo de ACL recursivo. As ACLs podem ser reaplicadas para itens sem causar um impacto negativo.
Tratamento de 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, a entidade de segurança do AD poderá não ter permissão suficiente para aplicar uma ACL a um ou mais dos itens filho na hierarquia de diretórios. Quando ocorre um erro de permissão, o processo é interrompido e um token de continuação é fornecido. Corrija o problema de permissão e, em seguida, use o token de continuação para processar o conjunto de dados restante. Os diretórios e arquivos que já foram processados com êxito não precisam ser processados novamente. Você também pode optar por reiniciar o processo de ACL recursivo. As ACLs podem ser reaplicadas para itens sem causar um impacto negativo.
Credenciais
Recomendamos que você provisione uma entidade de segurança do Microsoft Entra que tenha sido atribuída à função de proprietário de dados do blob de armazenamento no escopo da conta de armazenamento de destino ou do contêiner.
Desempenho
Para reduzir a latência, recomendamos que você execute o processo de ACL recursivo em uma Máquina Virtual (VM) do Azure localizada na mesma região que a sua conta de armazenamento.
Limites de ACL
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, consulte Controle de acesso no Azure Data Lake Storage Gen2.