Compartir a través de


Uso de Python para administrar listas de control de acceso (ACL) en Azure Data Lake Storage

En este artículo se muestra cómo usar Python para obtener, establecer y actualizar las listas de control de acceso de directorios y archivos.

La herencia de ACL ya está disponible para los nuevos elementos secundarios que se crean en un directorio primario. Ahora bien, también se pueden agregar, actualizar y quitar listas de control de acceso de forma recursiva en los elementos secundarios existentes de un directorio primario sin tener que realizar estos cambios individualmente para cada elemento secundario.

Paquete (índice de paquetes de Python) | Muestras | Ejemplos de ACL recursivas | Referencia de API | Asignación de Gen1 a Gen2 | Ofrecer comentarios

Requisitos previos

  • Una suscripción a Azure: cree una cuenta gratuita.
  • Una cuenta de almacenamiento de Azure que tenga habilitado el espacio de nombres jerárquico (HNS). Siga estas instrucciones para crear uno.
  • Python 3.8 y versiones posteriores
  • CLI de Azure versión 2.6.0 o posterior.
  • Uno de los siguientes permisos de seguridad:
    • Una entidad de seguridad aprovisionada de Microsoft Entra ID a la que se ha asignado el rol Propietario de datos de blobs de almacenamiento, con ámbito para el contenedor de destino, el grupo de recursos primario o la suscripción.
    • El usuario propietario del contenedor o directorio de destino al que va a aplicar la configuración de ACL. Para establecer listas de control de acceso de forma recursiva, se incluyen todos los elementos secundarios en el contenedor o el directorio de destino.
    • Clave de la cuenta de almacenamiento.

Configurar su proyecto

En esta sección se explica cómo preparar un proyecto para que funcione con la biblioteca cliente de Azure Data Lake Storage para Python.

En el directorio del proyecto, instale los paquetes para las bibliotecas cliente de Azure Data Lake Storage y Azure Identity mediante el comando pip install. El paquete azure-identity es necesario para las conexiones sin contraseña a los servicios de Azure.

pip install azure-storage-file-datalake azure-identity

A continuación, abra el archivo de código y agregue las instrucciones de importación necesarias. En este ejemplo, agregamos lo siguiente al archivo .py:

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

Conexión con la cuenta

Para usar los ejemplos de código de este artículo, tiene que crear una instancia de DataLakeServiceClient que represente la cuenta de almacenamiento. Puede autorizar el objeto de cliente con credenciales de Microsoft Entra ID o con una clave de cuenta.

Puede usar la biblioteca cliente de identidad de Azure para Python para autenticar la aplicación con Microsoft Entra ID.

Nota:

Si usa Microsoft Entra ID para autorizar el acceso, asegúrese de que la entidad de seguridad tenga asignado el rol Propietario de datos de blobs de almacenamiento. Para obtener más información sobre cómo se aplican los permisos de ACL y las consecuencias de cambiarlos, consulte Modelo de control de acceso de Azure Data Lake Storage .

En primer lugar, asigne uno de los siguientes roles de control de acceso basado en roles de Azure (Azure RBAC) a la entidad de seguridad:

Role Capacidad de configuración de ACL
Propietario de datos de blobs de almacenamiento Todos los directorios y archivos de la cuenta.
Colaborador de datos de blobs de almacenamiento Solo los directorios y archivos que pertenecen a la entidad de seguridad.

A continuación, cree una instancia de DataLakeServiceClient y pase una nueva instancia de la clase 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 más información sobre el uso de DefaultAzureCredential para autorizar el acceso a los datos, consulte Información general: Autenticación de aplicaciones de Python en Azure mediante el SDK de Azure.

Establecimiento de listas de control de acceso

Cuando establece una ACL, debe reemplazar toda la ACL, incluidas todas sus entradas. Si quiere cambiar el nivel de permiso de una entidad de seguridad o agregar una nueva entidad de seguridad a la ACL sin que esto afecte a otras entradas existentes, debe actualizar la ACL en su lugar. Para actualizar una ACL en lugar de reemplazarla, consulte la sección Actualización de ACL de este artículo.

Esta sección le muestra cómo:

  • Establecer la ACL de un directorio
  • Establecer la ACL de un archivo

Establecer la ACL de un directorio

Obtenga la lista de control de acceso (ACL) de un directorio llamando al método DataLakeDirectoryClient.get_access_control y establezca dicha lista con una llamada al método DataLakeDirectoryClient.set_access_control.

En este ejemplo se obtiene y después se establece la ACL de un directorio denominado my-directory. La cadena rwxr-xrw- concede al usuario propietario permisos de lectura, escritura y ejecución, permisos de solo lectura y ejecución al grupo propietario, y permisos de lectura y escritura al resto.

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)

También puede obtener y establecer la ACL del directorio raíz de un contenedor. Para obtener el directorio raíz, llame al método FileSystemClient._get_root_directory_client.

Establecer la ACL de un archivo

Obtenga la lista de control de acceso (ACL) de un archivo llamando al método DataLakeFileClient.get_access_control y establezca dicha lista con una llamada al método DataLakeFileClient.set_access_control.

En este ejemplo se obtiene y después se establece la ACL de un archivo denominado my-file.txt. La cadena rwxr-xrw- concede al usuario propietario permisos de lectura, escritura y ejecución, permisos de solo lectura y ejecución al grupo propietario, y permisos de lectura y escritura al resto.

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)

Establecimiento de listas de control de acceso de forma recursiva

Cuando establece una ACL, debe reemplazar toda la ACL, incluidas todas sus entradas. Si quiere cambiar el nivel de permiso de una entidad de seguridad o agregar una nueva entidad de seguridad a la ACL sin que esto afecte a otras entradas existentes, debe actualizar la ACL en su lugar. Para actualizar una ACL en lugar de reemplazarla, consulte la sección Actualizar una ACL de forma recursiva de este artículo.

Establezca ACL de forma recursiva llamando al método DataLakeDirectoryClient.set_access_control_recursive.

Si desea establecer una entrada de la ACL predeterminada, agregue la cadena default: al principio de cada cadena de entrada de ACL.

En este ejemplo se establece la ACL de un directorio denominado my-parent-directory.

Este método acepta un parámetro booleano denominado is_default_scope que especifica si se debe establecer la ACL predeterminada. Si ese parámetro es True, la lista de entradas de la ACL va precedida de la cadena default:. Las entradas de este ejemplo conceden los siguientes permisos: permisos de lectura, escritura y ejecución para el usuario propietario, permisos de lectura y ejecución para el grupo propietario y permisos de lectura para todos los demás. La última entrada de la ACL de este ejemplo proporciona permisos de lectura a un usuario específico con el identificador 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 un ejemplo que procesa ACLs recursivamente en lotes especificando un tamaño de lote, vea el ejemplo de Python.

Actualización de listas de control de acceso de forma recursiva

Cuando actualiza una ACL, modifica la ACL en lugar de reemplazarla. Por ejemplo, puede agregar una nueva entidad de seguridad a la ACL sin que esto afecte a otras entidades de seguridad que se enumeran en la ACL. Para reemplazar la ACL en lugar de actualizarla, consulte la sección Establecimiento de listas de control de acceso de este artículo.

Para actualizar una ACL de forma recursiva, cree un nuevo objeto ACL con la entrada de la ACL que quiera actualizar y, a continuación, use ese objeto en la operación para actualizar la ACL. No debe obtener la ACL existente, simplemente proporcione las entradas de la ACL que se vayan a actualizar. Actualice una ACL de forma recursiva llamando al método DataLakeDirectoryClient.update_access_control_recursive. Si desea actualizar una entrada de la ACL predeterminada, agregue la cadena default: al principio de cada cadena de entrada de la ACL.

En este ejemplo se actualiza una entrada de ACL con permiso de escritura.

En este ejemplo se establece la ACL de un directorio denominado my-parent-directory. Este método acepta un parámetro booleano denominado is_default_scope que especifica si se debe actualizar la ACL predeterminada. Si ese parámetro es True, la entrada de la ACL actualizada va precedida de la cadena 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 un ejemplo que procesa ACLs recursivamente en lotes especificando un tamaño de lote, vea el ejemplo de Python.

Eliminación de las entradas de ACL de forma recursiva

Puede quitar una o varias entradas de ACL. Para quitar entradas de ACL de forma recursiva, cree un nuevo objeto de ACL para la entrada de ACL que se va a quitar y, a continuación, use ese objeto en la operación para quitar la ACL. No debe obtener la ACL existente; simplemente proporcione las entradas de la ACL que se van a quitar.

Elimine entradas de ACL llamando al método DataLakeDirectoryClient.remove_access_control_recursive. Si desea quitar una entrada de la ACL predeterminada, agregue la cadena default: al principio de la cadena de entrada de la ACL.

En este ejemplo se quita una entrada de la ACL del directorio llamado my-parent-directory. Este método acepta un parámetro booleano denominado is_default_scope que especifica si se debe quitar la entrada de la ACL predeterminada. Si ese parámetro es True, la entrada de la ACL actualizada va precedida de la cadena 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 un ejemplo que procesa ACLs recursivamente en lotes especificando un tamaño de lote, vea el ejemplo de Python.

Recuperación de errores

Podría encontrar errores de tiempo de ejecución o de permisos. En el caso de los errores de tiempo de ejecución, reinicie el proceso desde el principio. Los errores de permisos pueden producirse si la entidad de seguridad no tiene permisos suficientes para modificar la ACL de un directorio o archivo que se encuentra en la jerarquía de directorios que se está modificando. Solucione el problema de permisos y, a continuación, elija reanudar el proceso desde el punto de error mediante un token de continuación, o bien reinicie el proceso desde el principio. No tiene que usar el token de continuación si prefiere reiniciar desde el principio. Puede volver a aplicar las entradas de ACL sin ningún efecto negativo.

Este ejemplo devuelve un token de continuación en caso de que se produzca un error. La aplicación puede volver a llamar a este método de ejemplo después de que se haya solucionado el error y pasar el token de continuación. Si se llama a este método de ejemplo por primera vez, la aplicación puede pasar un valor de None para el parámetro del token de continuación.

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 un ejemplo que procesa ACLs recursivamente en lotes especificando un tamaño de lote, vea el ejemplo de Python.

Si desea que el proceso se complete sin que se interrumpa por errores de permisos, puede especificarlo.

Para asegurarse de que el proceso se completa sin interrupciones, no pase un token de continuación al DataLakeDirectoryClient.set_access_control_recursive.

En este ejemplo se establecen las entradas de ACL de forma recursiva. Si este código se encuentra un error de permiso, lo registra y continúa la ejecución. En este ejemplo se imprime el número de errores en la consola.

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 un ejemplo que procesa ACLs recursivamente en lotes especificando un tamaño de lote, vea el ejemplo de Python.

Procedimientos recomendados

En esta sección se proporcionan algunas directrices de procedimientos recomendados para configurar las ACL de forma recursiva.

Manejo de errores de tiempo de ejecución

Se puede producir un error de tiempo de ejecución por muchos motivos (por ejemplo: una interrupción o un problema de conectividad de cliente). Si se produce un error de tiempo de ejecución, reinicie el proceso de ACL recursivo. Las ACL se pueden volver a aplicar a los elementos sin provocar ningún efecto negativo.

Manejo de errores de permisos (403)

Si experimenta una excepción de control de acceso al ejecutar un proceso de ACL recursivo, es posible que la entidad de seguridad de AD no tenga permisos suficientes para aplicar una ACL a uno o varios de los elementos secundarios de la jerarquía de directorios. Cuando se produce un error de permiso, el proceso se detiene y se proporciona un token de continuación. Repare el problema de permisos y, después, use el token de continuación para procesar el conjunto de datos restante. Los directorios y archivos que ya se han procesado correctamente no tendrán que procesarse de nuevo. También puede optar por reiniciar el proceso de ACL recursivo. Las ACL se pueden volver a aplicar a los elementos sin provocar ningún efecto negativo.

Credenciales

Se recomienda que aprovisione una entidad de seguridad de Microsoft Entra a la que se haya asignado el rol Propietario de datos de blobs de almacenamiento en el ámbito de la cuenta de almacenamiento o el contenedor de destino.

Rendimiento

Para reducir la latencia, se recomienda ejecutar el proceso de ACL recursivo en una máquina virtual de Azure que se encuentre en la misma región que la cuenta de almacenamiento.

Límites de ACL

El número máximo de ACL que puede aplicar a un directorio o archivo es de 32 ACL de acceso y 32 ACL predeterminadas. Para más información, consulte Control de acceso en Azure Data Lake Storage Gen2.

Consulte también