Бөлісу құралы:


Использование .NET для управления списками ACL в Azure Data Lake Storage 2-го поколения

В этой статье показано, как использовать .NET для получения, настройки и обновления списков управления доступом к каталогам и файлам.

Наследование ACL уже доступно для новых дочерних элементов, созданных в родительском каталоге. Но можно также добавлять, обновлять и удалять списки управления доступом для существующих дочерних элементов родительского каталога без необходимости вносить эти изменения отдельно для каждого дочернего элемента.

Пакет (NuGet) | Примеры | Справочник по API | Сопоставление Gen1 с Gen2 | Отправить отзыв

Необходимые компоненты

  • Подписка Azure. См. страницу бесплатной пробной версии Azure.

  • В учетной записи хранения включено иерархическое пространство имен. Выполните эти инструкции, чтобы создать учетную запись.

  • Azure CLI версии2.6.0 или выше.

  • Одно из следующих разрешений безопасности:

    • Подготовленный субъект безопасности Идентификатора Microsoft Entra, которому назначена роль владельца данных большого двоичного объекта служба хранилища, область в целевой контейнер, учетную запись хранения, родительскую группу ресурсов или подписку.

    • Пользователь-владелец целевого контейнера или каталога, к которому планируется применять параметры ACL. Следует настроить ACL рекурсивно, то есть для всех дочерних элементов в целевом контейнере или каталоге.

    • Ключ учетной записи хранения.

Настройка проекта

Чтобы приступить к работе, установите пакет NuGet Azure.Storage.Files.DataLake.

  1. Откройте командное окно (например, Windows PowerShell).

  2. В каталоге проекта установите пакет Azure.Storage.Files.DataLake (предварительную версию) с помощью команды dotnet add package.

    dotnet add package Azure.Storage.Files.DataLake -v 12.6.0 -s https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-net/nuget/v3/index.json
    

    После этого добавьте это в начало файла кода.

    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;
    

Подключение к учетной записи

Чтобы использовать фрагменты кода из этой статьи, необходимо создать экземпляр DataLakeServiceClient, представляющий учетную запись хранения.

Подключение с помощью идентификатора Microsoft Entra

Примечание.

Если вы используете идентификатор Microsoft Entra для авторизации доступа, убедитесь, что субъект безопасности назначен служба хранилища роль владельца данных BLOB-объектов. Дополнительные сведения о применении разрешений ACL и последствиях их изменения см. на странице Модель управления доступом в Azure Data Lake Storage 2-го поколения.

Клиентская библиотека удостоверений Azure для .NET можно использовать для проверки подлинности приложения с помощью идентификатора Microsoft Entra.

После установки пакета добавьте этот оператор using в начало файла кода.

using Azure.Identity;

Во-первых, вам потребуется назначить одну из следующих ролей Управления доступом на основе ролей Azure (Azure RBAC) субъекту безопасности:

Роль Возможности настройки ACL
владелец данных BLOB-объектов хранилища; Все каталоги и файлы в учетной записи.
участник данных BLOB-объектов хранилища; Только каталоги и файлы, которыми владеет субъект безопасности.

Затем создайте экземпляр DataLakeServiceClient и передайте новый экземпляр класса 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;
}

Дополнительные сведения об использовании DefaultAzureCredential для авторизации доступа к данным см. в статье "Проверка подлинности приложений .NET с помощью служб Azure".

Подключение с помощью ключа учетной записи

Вы можете авторизовать доступ к данным с помощью ключей доступа к учетной записи (общий ключ). В этом примере создается экземпляр DataLakeServiceClient, авторизованный с помощью ключа учетной записи.

public static DataLakeServiceClient GetDataLakeServiceClient(string accountName, string accountKey)
{
    StorageSharedKeyCredential sharedKeyCredential =
        new StorageSharedKeyCredential(accountName, accountKey);

    string dfsUri = $"https://{accountName}.dfs.core.windows.net";

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

    return dataLakeServiceClient;
}

Внимание

Авторизация с помощью общего ключа не рекомендуется, так как она может быть менее безопасной. Чтобы обеспечить оптимальную безопасность, отключите авторизацию через общий ключ для учетной записи хранения, как описано в разделе "Запрет авторизации общего ключа" для учетной записи служба хранилища Azure.

Использование ключей доступа и строка подключения должно быть ограничено первоначальным подтверждением концепции приложений или прототипов разработки, которые не обращаются к рабочим или конфиденциальным данным. В противном случае классы проверки подлинности на основе маркеров, доступные в пакете SDK Azure, всегда должны быть предпочтительнее при проверке подлинности в ресурсах Azure.

Корпорация Майкрософт рекомендует клиентам использовать идентификатор Microsoft Entra или подписанный URL-адрес (SAS), чтобы авторизовать доступ к данным в служба хранилища Azure. Дополнительные сведения см. в разделе "Авторизация операций для доступа к данным".

Настройка списков ACL

При установке ACL вы замените весь список ACL, включая все его записи. Если вы хотите изменить уровень разрешений субъекта безопасности или добавить новый субъект безопасности в список управления доступом, не затрагивая другие существующие записи, следует обновить ACL. Сведения о том, как обновить список управления доступом вместо его замены, см. в разделе Обновление списков ACL этой статьи.

Если вы решили настроить ACL, необходимо добавить запись для пользователя-владельца, запись для группы-владельца и запись для всех других пользователей. Дополнительные сведения о пользователе-владельце, группе-владельце и других пользователях см. в разделе Пользователи и удостоверения.

В этом разделе показано, как выполнять следующие действия.

  • Настройка ACL для каталога
  • Настройка ACL для файла
  • Рекурсивная настройка ACL

Настройка ACL для каталога

Получите список управления доступом (ACL) каталога, вызвав метод DataLakeDirectoryClient.GetAccessControlAsync, и настройте ACL, вызвав метод DataLakeDirectoryClient.SetAccessControlList .

В этом примере мы получаем список ACL и настраиваем его для каталога с именем my-directory. В строке user::rwx,group::r-x,other::rw- пользователю-владельцу предоставляются разрешения на чтение, запись и выполнение, группе-владельцу — только на чтение и выполнение, а всем остальным — только на чтение и запись.

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);

}

Вы также можете получить и настроить ACL для корневого каталога контейнера. Чтобы получить корневой каталог, передайте пустую строку ("") в метод DataLakeFileSystemClient.GetDirectoryClient.

Настройка ACL для файла

Получите список управления доступом (ACL) файла, вызвав метод DataLakeFileClient.GetAccessControlAsync, и настройте ACL, вызвав метод DataLakeFileClient.SetAccessControlList .

В этом примере мы получаем список ACL и настраиваем его для файла с именем my-file.txt. В строке user::rwx,group::r-x,other::rw- пользователю-владельцу предоставляются разрешения на чтение, запись и выполнение, группе-владельцу — только на чтение и выполнение, а всем остальным — только на чтение и запись.

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);
}

Рекурсивная настройка ACL

Чтобы настроить списки ACL рекурсивно, вызовите метод DataLakeDirectoryClient.SetAccessControlRecursiveAsync. Передайте в этот метод СписокPathAccessControlItem. Каждый объект PathAccessControlItem определяет запись ACL.

Если нужно настроить запись ACL по умолчанию, можно установить для свойства PathAccessControlItem.DefaultScope в PathAccessControlItem значение true.

В этом примере список ACL задается для каталога my-parent-directory. Этот метод принимает логический параметр с именем isDefaultScope, указывающий, следует ли задавать ACL по умолчанию. Этот параметр используется в конструкторе PathAccessControlItem. Эти записи ACL предоставляют пользователю-владельцу разрешения на чтение, запись и выполнение, группе-владельцу — только на чтение и выполнение, а всем остальным доступ не предоставляется. Последняя запись ACL в этом примере предоставляет определенному пользователю разрешение на чтение и выполнение идентификатора xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx объекта.

    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);
}

Обновление ACL

При обновлении ACL происходит его изменение, а не полная замена. Например, можно добавить новый субъект безопасности в ACL, не затрагивая другие субъекты безопасности, перечисленные в этом же списке. Сведения о том, как заменить ACL вместо его обновления, см. в разделе Задание ACL этой статьи.

В этом разделе показано, как выполнять следующие действия.

  • Обновление списка ACL
  • Рекурсивное обновление ACL

Обновление списка ACL

Сначала получите список ACL для каталога, вызвав метод DataLakeDirectoryClient.GetAccessControlAsync. Скопируйте список записей ACL в новый список объектов PathAccessControl. Затем найдите запись, которую требуется обновить, и замените ее в списке. Задайте список ACL, вызвав метод DataLakeDirectoryClient.SetAccessControlList.

В этом примере корневой ACL контейнера обновляется путем замены записи ACL для всех остальных пользователей.

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);
    }

   }

Рекурсивное обновление ACL

Чтобы обновить ACL рекурсивно, создайте новый объект ACL с записью, которую требуется обновить, а затем используйте его в операции обновления ACL. Не изменяйте существующий список ACL, просто предоставьте записи ACL, которые необходимо обновить.

Для рекурсивного обновления ACL нужно вызвать метод DataLakeDirectoryClient.UpdateAccessControlRecursiveAsync. Передайте в этот метод СписокPathAccessControlItem. Каждый объект PathAccessControlItem определяет запись ACL.

Если нужно обновить запись ACL по умолчанию, можно установить для свойства PathAccessControlItem.DefaultScope в PathAccessControlItem значение true.

В этом примере обновляется запись ACL с разрешением на запись. Этот метод принимает логический параметр с именем isDefaultScope, указывающий, следует ли обновлять ACL по умолчанию. Этот параметр используется в конструкторе 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);

}

Удаление записей ACL

Вы можете удалить одну или несколько записей ACL. В этом разделе показано, как выполнять следующие действия.

  • Удаление записи ACL
  • Рекурсивное удаление записей ACL

Удаление записи ACL

Сначала получите список ACL для каталога, вызвав метод DataLakeDirectoryClient.GetAccessControlAsync. Скопируйте список записей ACL в новый список объектов PathAccessControl. Затем найдите запись, которую нужно удалить, и вызовите метод Remove коллекции. Задайте обновленный список ACL, вызвав метод DataLakeDirectoryClient.SetAccessControlList.

В этом примере корневой ACL контейнера обновляется путем замены записи ACL для всех остальных пользователей.

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);
    }

}

Рекурсивное удаление записей ACL

Чтобы удалить записи ACL рекурсивно, создайте новый объект ACL для удаляемой записи, а затем используйте его в операции удаления ACL. Не изменяйте существующий список ACL, просто предоставьте записи ACL, которые необходимо удалить.

Удалите записи ACL, вызвав метод DataLakeDirectoryClient.RemoveAccessControlRecursiveAsync. Передайте в этот метод СписокPathAccessControlItem. Каждый объект PathAccessControlItem определяет запись ACL.

Если нужно удалить запись ACL по умолчанию, можно установить для свойства PathAccessControlItem.DefaultScope в PathAccessControlItem значение true.

В этом примере удаляется запись ACL из списка управления доступом для каталога my-parent-directory. Этот метод принимает логический параметр с именем isDefaultScope, указывающий, следует ли удалять запись из ACL по умолчанию. Этот параметр используется в конструкторе 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);

}

Восстановление после сбоев

При рекурсивном изменении ACL могут возникать ошибки времени выполнения или разрешений. При ошибках времени выполнения перезапустите процесс с самого начала. Ошибки разрешений могут возникать, если субъект безопасности не имеет достаточных разрешений для изменения ACL каталога или файла в изменяемой иерархии каталогов. Устраните проблему с разрешениями, а затем возобновите процесс с точки сбоя с помощью маркера продолжения или перезапустите его с самого начала. Во втором случае использовать маркер продолжения не нужно. Вы можете повторно применить ACL без отрицательных последствий.

В этом примере в случае сбоя возвращается маркер продолжения. Приложение может снова вызвать этот метод после устранения ошибки и передать маркер продолжения. Если этот метод вызывается впервые, приложение может передать в него значение null для параметра маркера продолжения.

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;
    }

}

Если вы хотите, чтобы процесс продолжался без прерывания на ошибки разрешений, можно указать это.

Чтобы убедиться в том, что процесс завершается без прерывания, передайте объект AccessControlChangedOptions и задайте для свойства ContinueOnFailure этого объекта значение true.

В этом примере записи ACL задаются рекурсивно. Если этот код вызывает ошибку разрешения, он регистрирует этот сбой и возобновляет выполнение. В этом примере на консоль выводится число сбоев.

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());
}

Рекомендации

В этом разделе приведены рекомендации по рекурсивной настройке списков управления доступом.

Обработка ошибок времени выполнения

Ошибки времени выполнения могут возникать по многим причинам (например, в случае сбоя или проблемы с подключением клиента). При возникновении ошибки времени выполнения перезапустите процесс рекурсивной настройки ACL. Списки управления доступом можно повторно применить к элементам без негативного воздействия.

Обработка ошибок разрешений (403)

Если при выполнении процесса рекурсивной настройки ACL возникает исключение управления доступом, возможно, что субъект безопасности Active Directory не имеет достаточных разрешений для применения ACL к одному или нескольким дочерним элементам в иерархии каталогов. При возникновении ошибки, связанной с разрешением, процесс останавливается и предоставляется маркер продолжения. Устраните проблему с разрешениями, а затем используйте маркер продолжения для обработки оставшегося набора данных. Каталоги и файлы, которые уже были успешно обработаны, не должны обрабатываться повторно. Можно также перезапустить процесс рекурсивной настройки ACL. Списки управления доступом можно повторно применить к элементам без негативного воздействия.

Учетные данные

Рекомендуется подготовить субъект безопасности Microsoft Entra, которому назначена роль владельца данных большого двоичного объекта служба хранилища в область целевой учетной записи хранения или контейнера.

Производительность

Чтобы сократить задержку, рекомендуется запустить процесс рекурсивной настройки ACL на виртуальной машине Azure, расположенной в том же регионе, что и учетная запись хранения.

Ограничения для списков управления доступом

Максимальное число списков управления доступом, которое можно применить к каталогу или файлу, составляет 32 списка для доступа и 32 списка по умолчанию. Дополнительные сведения см. в статье Контроль доступа в Azure Data Lake Storage 2-го поколения.

См. также