Compartir por


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

En este artículo se muestra cómo usar .NET 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 (NuGet) | Ejemplos | Referencia de API | Asignación de Gen1 a Gen2 | Envíenos sus comentarios

Requisitos previos

  • Una suscripción a Azure: cree una cuenta gratuita.
  • Cuenta de almacenamiento Azure que tiene habilitado el espacio de nombres jerárquico (HNS). Siga estas instrucciones para crear uno.
  • 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 muestra cómo configurar un proyecto para que funcione con la biblioteca de cliente de Azure Storage Data Lake.

Instalar paquetes

Desde el directorio del proyecto, instale paquetes para las bibliotecas de cliente de Azure Storage Data Lake y Azure Identity mediante el comando dotnet add package. El paquete Azure.Identity es necesario para las conexiones sin contraseña a los servicios de Azure.

dotnet add package Azure.Storage.Files.DataLake
dotnet add package Azure.Identity

Agregue directivas using.

Agregue estas directivas using al principio del archivo de código:

using Azure;
using Azure.Core;
using Azure.Storage;
using Azure.Storage.Files.DataLake;
using Azure.Storage.Files.DataLake.Models;
using System.Collections.Generic;
using System.Threading.Tasks;

Conexión con la cuenta

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

Puede usar la biblioteca cliente de identidad de Azure para .NET 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 una de los siguientes roles del control de acceso basado en roles de Azure (Azure RBAC) a su entidad de seguridad principal:

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.

public static DataLakeServiceClient GetDataLakeServiceClient(string accountName)
{
    string dfsUri = $"https://{accountName}.dfs.core.windows.net";

    DataLakeServiceClient dataLakeServiceClient = new DataLakeServiceClient(
        new Uri(dfsUri),
        new DefaultAzureCredential());

    return dataLakeServiceClient;
}

Para obtener más información sobre el uso de DefaultAzureCredential para autorizar el acceso a los datos, consulte Cómo autenticar aplicaciones .NET con servicios 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.

Si elige establecer la lista de control de acceso, debe agregar una entrada para el usuario propietario, otra para el grupo propietario y una tercera para los demás usuarios. Para más información sobre el usuario propietario, el grupo propietario y el resto de usuarios, consulte Usuarios e identidades.

Esta sección le muestra cómo:

  • Establecer la ACL de un directorio
  • Establecer la ACL de un archivo
  • Establecimiento de listas de control de acceso de forma recursiva

Establecer la ACL de un directorio

Obtenga la lista de control de acceso (ACL) de un directorio al llamar al método DataLakeDirectoryClient.GetAccessControlAsync y establezca dicha lista con una llamada al método DataLakeDirectoryClient.SetAccessControlList.

En este ejemplo se obtiene y después se establece la ACL de un directorio denominado my-directory. La cadena user::rwx,group::r-x,other::rw- 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.

public async Task ManageDirectoryACLs(DataLakeFileSystemClient fileSystemClient)
{
    DataLakeDirectoryClient directoryClient =
      fileSystemClient.GetDirectoryClient("");

    PathAccessControl directoryAccessControl =
        await directoryClient.GetAccessControlAsync();

    foreach (var item in directoryAccessControl.AccessControlList)
    {
        Console.WriteLine(item.ToString());
    }

    IList<PathAccessControlItem> accessControlList
        = PathAccessControlExtensions.ParseAccessControlList
        ("user::rwx,group::r-x,other::rw-");

    directoryClient.SetAccessControlList(accessControlList);

}

También puede obtener y establecer la ACL del directorio raíz de un contenedor. Para obtener el directorio raíz, pase una cadena vacía ("") en el método DataLakeFileSystemClient.GetDirectoryClient.

Establecer la ACL de un archivo

Obtenga la lista de control de acceso (ACL) de un archivo al llamar al método DataLakeFileClient.GetAccessControlAsync y establezca dicha lista con una llamada al método DataLakeFileClient.SetAccessControlList.

En este ejemplo se obtiene y después se establece la ACL de un archivo denominado my-file.txt. La cadena user::rwx,group::r-x,other::rw- 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.

public async Task ManageFileACLs(DataLakeFileSystemClient fileSystemClient)
{
    DataLakeDirectoryClient directoryClient =
        fileSystemClient.GetDirectoryClient("my-directory");

    DataLakeFileClient fileClient =
        directoryClient.GetFileClient("hello.txt");

    PathAccessControl FileAccessControl =
        await fileClient.GetAccessControlAsync();

    foreach (var item in FileAccessControl.AccessControlList)
    {
        Console.WriteLine(item.ToString());
    }

    IList<PathAccessControlItem> accessControlList
        = PathAccessControlExtensions.ParseAccessControlList
        ("user::rwx,group::r-x,other::rw-");

    fileClient.SetAccessControlList(accessControlList);
}

Establecimiento de listas de control de acceso de forma recursiva

Establezca las listas de control de acceso de forma recursiva llamando al método DataLakeDirectoryClient.SetAccessControlRecursiveAsync. Pase a este método una lista de PathAccessControlItem. Cada PathAccessControlItem define una entrada de la ACL.

Si desea establecer una entrada de la ACL predeterminada, puede establecer la propiedad PathAccessControlItem.DefaultScope de PathAccessControlItem en true.

En este ejemplo se establece la ACL de un directorio denominado my-parent-directory. Este método acepta un parámetro booleano denominado isDefaultScope que especifica si se debe establecer la ACL predeterminada. Ese parámetro se utiliza en el constructor de PathAccessControlItem. Las entradas de la ACL conceden al usuario propietario permisos de lectura, escritura y ejecución, permisos solo de lectura y ejecución al grupo propietario, y ningún permiso al resto. La última entrada de ACL de este ejemplo proporciona a un usuario específico con el identificador de objeto xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx permisos de lectura y ejecución.

    public async Task SetACLRecursively(DataLakeServiceClient serviceClient, bool isDefaultScope)
{
    DataLakeDirectoryClient directoryClient =
        serviceClient.GetFileSystemClient("my-container").
            GetDirectoryClient("my-parent-directory");

    List<PathAccessControlItem> accessControlList =
        new List<PathAccessControlItem>()
    {
new PathAccessControlItem(AccessControlType.User,
    RolePermissions.Read |
    RolePermissions.Write |
    RolePermissions.Execute, isDefaultScope),

new PathAccessControlItem(AccessControlType.Group,
    RolePermissions.Read |
    RolePermissions.Execute, isDefaultScope),

new PathAccessControlItem(AccessControlType.Other,
    RolePermissions.None, isDefaultScope),

new PathAccessControlItem(AccessControlType.User,
    RolePermissions.Read |
    RolePermissions.Execute, isDefaultScope,
    entityId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"),
    };

    await directoryClient.SetAccessControlRecursiveAsync
        (accessControlList, null);
}

Actualización de ACL

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.

Esta sección le muestra cómo:

  • Actualización de una ACL
  • Actualización de listas de control de acceso de forma recursiva

Actualización de una ACL

En primer lugar, para obtener la ACL de un directorio, llame al método DataLakeDirectoryClient.GetAccessControlAsync. Copie la lista de entradas de ACL en una nueva lista de objetos PathAccessControl. A continuación, busque la entrada que desea actualizar y reemplácela en la lista. Establezca la ACL mediante una llamada al método DataLakeDirectoryClient.SetAccessControlList.

En este ejemplo se actualiza la ACL raíz de un contenedor mediante la sustitución de la entrada de ACL de todos los demás usuarios.

public async Task UpdateDirectoryACLs(DataLakeFileSystemClient fileSystemClient)
{
    DataLakeDirectoryClient directoryClient =
      fileSystemClient.GetDirectoryClient("");

    PathAccessControl directoryAccessControl =
        await directoryClient.GetAccessControlAsync();

    List<PathAccessControlItem> accessControlListUpdate 
        = (List<PathAccessControlItem>)directoryAccessControl.AccessControlList;

    int index = -1;

    foreach (var item in accessControlListUpdate)
    {
        if (item.AccessControlType == AccessControlType.Other)
        {
            index = accessControlListUpdate.IndexOf(item);
            break;
        }
    }

    if (index > -1)
    {
        accessControlListUpdate[index] = new PathAccessControlItem(AccessControlType.Other,
        RolePermissions.Read |
        RolePermissions.Execute);

        directoryClient.SetAccessControlList(accessControlListUpdate);
    }

   }

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

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 obtenga la ACL existente, solo tiene que proporcionar entradas de ACL que se van a actualizar.

Actualice una ACL de forma recursiva llamando al método DataLakeDirectoryClient.UpdateAccessControlRecursiveAsync. Pase a este método una lista de PathAccessControlItem. Cada PathAccessControlItem define una entrada de la ACL.

Si desea actualizar una entrada de la ACL predeterminada, puede establecer la propiedad PathAccessControlItem.DefaultScope de PathAccessControlItem en true.

En este ejemplo se actualiza una entrada de ACL con permiso de escritura. Este método acepta un parámetro booleano denominado isDefaultScope que especifica si se debe actualizar la ACL predeterminada. Ese parámetro se utiliza en el constructor de PathAccessControlItem.

public async Task UpdateACLsRecursively(DataLakeServiceClient serviceClient, bool isDefaultScope)
{
    DataLakeDirectoryClient directoryClient =
        serviceClient.GetFileSystemClient("my-container").
        GetDirectoryClient("my-parent-directory");

    List<PathAccessControlItem> accessControlListUpdate =
        new List<PathAccessControlItem>()
    {
new PathAccessControlItem(AccessControlType.User,
    RolePermissions.Read |
    RolePermissions.Write |
    RolePermissions.Execute, isDefaultScope,
    entityId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"),
    };

    await directoryClient.UpdateAccessControlRecursiveAsync
        (accessControlListUpdate, null);

}

Eliminación de entradas de ACL

Puede quitar una o varias entradas de ACL. Esta sección le muestra cómo:

  • Eliminación de una entrada de ACL
  • Eliminación de las entradas de ACL de forma recursiva

Eliminación de una entrada de ACL

En primer lugar, para obtener la ACL de un directorio, llame al método DataLakeDirectoryClient.GetAccessControlAsync. Copie la lista de entradas de ACL en una nueva lista de objetos PathAccessControl. A continuación, busque la entrada que desea quitar y llame al método Remove de la colección. Establezca la ACL actualizada mediante una llamada al método DataLakeDirectoryClient.SetAccessControlList.

En este ejemplo se actualiza la ACL raíz de un contenedor mediante la sustitución de la entrada de ACL de todos los demás usuarios.

public async Task RemoveDirectoryACLEntry
    (DataLakeFileSystemClient fileSystemClient)
{
    DataLakeDirectoryClient directoryClient =
      fileSystemClient.GetDirectoryClient("");

    PathAccessControl directoryAccessControl =
        await directoryClient.GetAccessControlAsync();

    List<PathAccessControlItem> accessControlListUpdate
        = (List<PathAccessControlItem>)directoryAccessControl.AccessControlList;

    PathAccessControlItem entryToRemove = null;

    foreach (var item in accessControlListUpdate)
    {
        if (item.EntityId == "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")
        {
            entryToRemove = item;
            break;
        }
    }

    if (entryToRemove != null)
    {
        accessControlListUpdate.Remove(entryToRemove);
        directoryClient.SetAccessControlList(accessControlListUpdate);
    }

}

Eliminación de las entradas de ACL de forma recursiva

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 obtenga la ACL existente, simplemente proporcione las entradas de ACL que se van a quitar.

Elimine entradas de ACL llamando al método DataLakeDirectoryClient.RemoveAccessControlRecursiveAsync. Pase a este método una lista de PathAccessControlItem. Cada PathAccessControlItem define una entrada de la ACL.

Si desea quitar una entrada de la ACL predeterminada, puede establecer la propiedad PathAccessControlItem.DefaultScope de PathAccessControlItem en true.

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 isDefaultScope que especifica si se debe quitar la entrada de la ACL predeterminada. Ese parámetro se utiliza en el constructor de PathAccessControlItem.

public async Task RemoveACLsRecursively(DataLakeServiceClient serviceClient, bool isDefaultScope)
{
    DataLakeDirectoryClient directoryClient =
        serviceClient.GetFileSystemClient("my-container").
            GetDirectoryClient("my-parent-directory");

    List<RemovePathAccessControlItem> accessControlListForRemoval =
        new List<RemovePathAccessControlItem>()
        {
    new RemovePathAccessControlItem(AccessControlType.User, isDefaultScope,
    entityId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"),
        };

    await directoryClient.RemoveAccessControlRecursiveAsync
        (accessControlListForRemoval, null);

}

Recuperación de errores

Al modificar listas de control de acceso de forma recursiva, es posible que se produzcan errores del entorno de ejecución o de los 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 null para el parámetro del token de continuación.

public async Task<string> ResumeAsync(DataLakeServiceClient serviceClient,
    DataLakeDirectoryClient directoryClient,
    List<PathAccessControlItem> accessControlList,
    string continuationToken)
{
    try
    {
        var accessControlChangeResult =
            await directoryClient.SetAccessControlRecursiveAsync(
                accessControlList, continuationToken: continuationToken, null);

        if (accessControlChangeResult.Value.Counters.FailedChangesCount > 0)
        {
            continuationToken =
                accessControlChangeResult.Value.ContinuationToken;
        }

        return continuationToken;
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
        return continuationToken;
    }

}

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, pase un objeto AccessControlChangedOptions y establezca la propiedad ContinueOnFailure de ese objeto en true.

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.

public async Task ContinueOnFailureAsync(DataLakeServiceClient serviceClient,
    DataLakeDirectoryClient directoryClient,
    List<PathAccessControlItem> accessControlList)
{
    var accessControlChangeResult =
        await directoryClient.SetAccessControlRecursiveAsync(
            accessControlList, null, new AccessControlChangeOptions()
            { ContinueOnFailure = true });

    var counters = accessControlChangeResult.Value.Counters;

    Console.WriteLine("Number of directories changed: " +
        counters.ChangedDirectoriesCount.ToString());

    Console.WriteLine("Number of files changed: " +
        counters.ChangedFilesCount.ToString());

    Console.WriteLine("Number of failures: " +
        counters.FailedChangesCount.ToString());
}

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