Använda .NET för att hantera ACL:er i Azure Data Lake Storage Gen2

Den här artikeln visar hur du använder .NET för att hämta, ange och uppdatera åtkomstkontrollistor med kataloger och filer.

ACL-arv är redan tillgängligt för nya underordnade objekt som skapas under en överordnad katalog. Men du kan också lägga till, uppdatera och ta bort ACL:er rekursivt på befintliga underordnade objekt i en överordnad katalog utan att behöva göra dessa ändringar individuellt för varje underordnat objekt.

Paket (NuGet)Exempel-API-referens | | | Gen1 till Gen2-mappning | Ge feedback

Förutsättningar

  • En Azure-prenumeration. Se Hämta en kostnadsfri utvärderingsversion av Azure.

  • Ett lagringskonto med hierarkisk namnrymd (HNS) aktiverat. Följ dessa instruktioner för att skapa en.

  • Azure CLI-version 2.6.0 eller senare.

  • En av följande säkerhetsbehörigheter:

    • Ett etablerat Säkerhetsobjekt för Microsoft Entra-ID som har tilldelats rollen Lagringsblobdataägare, som är begränsad till målcontainern, lagringskontot, den överordnade resursgruppen eller prenumerationen.

    • Ägande användare av målcontainern eller katalogen som du planerar att tillämpa ACL-inställningar på. Om du vill ange ACL:er rekursivt inkluderar detta alla underordnade objekt i målcontainern eller katalogen.

    • Lagringskontonyckel.

Konfigurera projektet

Kom igång genom att installera NuGet-paketet Azure.Storage.Files.DataLake .

  1. Öppna ett kommandofönster (till exempel Windows PowerShell).

  2. Från projektkatalogen installerar du förhandsversionen av Azure.Storage.Files.DataLake med hjälp dotnet add package av kommandot .

    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
    

    Lägg sedan till dessa med hjälp av -instruktioner överst i kodfilen.

    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;
    

Anslut till kontot

Om du vill använda kodfragmenten i den här artikeln måste du skapa en DataLakeServiceClient-instans som representerar lagringskontot.

Anslut med hjälp av Microsoft Entra-ID

Kommentar

Om du använder Microsoft Entra-ID för att auktorisera åtkomst kontrollerar du att ditt säkerhetsobjekt har tilldelats rollen Lagringsblobdataägare. Mer information om hur ACL-behörigheter tillämpas och hur du ändrar dem finns i Åtkomstkontrollmodell i Azure Data Lake Storage Gen2.

Du kan använda Azure Identity-klientbiblioteket för .NET för att autentisera ditt program med Microsoft Entra-ID.

När du har installerat paketet lägger du till den här instruktionen överst i kodfilen.

using Azure.Identity;

Först måste du tilldela någon av följande rollbaserade åtkomstkontrollroller i Azure (Azure RBAC) till ditt säkerhetsobjekt:

Roll ACL-inställningsfunktion
Storage Blob Data-ägare Alla kataloger och filer i kontot.
Storage Blob Data-deltagare Endast kataloger och filer som ägs av säkerhetsobjektet.

Skapa sedan en DataLakeServiceClient-instans och skicka in en ny instans av klassen 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;
}

Mer information om hur du använder DefaultAzureCredential för att auktorisera åtkomst till data finns i Autentisera .NET-program med Azure-tjänster.

Anslut med hjälp av en kontonyckel

Du kan auktorisera åtkomst till data med hjälp av dina kontoåtkomstnycklar (delad nyckel). I det här exemplet skapas en DataLakeServiceClient-instans som är auktoriserad med kontonyckeln.

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

Varning

Auktorisering med delad nyckel rekommenderas inte eftersom det kan vara mindre säkert. För optimal säkerhet inaktiverar du auktorisering via delad nyckel för ditt lagringskonto enligt beskrivningen i Förhindra auktorisering av delad nyckel för ett Azure Storage-konto.

Användning av åtkomstnycklar och anslutningssträng bör begränsas till inledande konceptbevisappar eller utvecklingsprototyper som inte har åtkomst till produktion eller känsliga data. Annars bör de tokenbaserade autentiseringsklasserna som är tillgängliga i Azure SDK alltid föredras när du autentiserar till Azure-resurser.

Microsoft rekommenderar att klienter använder antingen Microsoft Entra-ID eller en signatur för delad åtkomst (SAS) för att ge åtkomst till data i Azure Storage. Mer information finns i Auktorisera åtgärder för dataåtkomst.

Ange ACL:er

När du anger en ACL ersätter du hela ACL:en inklusive alla dess poster. Om du vill ändra behörighetsnivån för ett säkerhetsobjekt eller lägga till ett nytt säkerhetsobjekt i ACL:n utan att påverka andra befintliga poster bör du uppdatera ACL:en i stället. Information om hur du uppdaterar en ACL i stället för att ersätta den finns i avsnittet Uppdatera ACL:er i den här artikeln.

Om du väljer att ange ACL måste du lägga till en post för den ägande användaren, en post för ägande gruppen och en post för alla andra användare. Mer information om den ägande användaren, ägande gruppen och alla andra användare finns i Användare och identiteter.

Det här avsnittet visar hur du:

  • Ange ACL för en katalog
  • Ange ACL för en fil
  • Ange ACL:er rekursivt

Ange ACL för en katalog

Hämta åtkomstkontrollistan (ACL) för en katalog genom att anropa metoden DataLakeDirectoryClient.GetAccessControlAsync och ange ACL genom att anropa metoden DataLakeDirectoryClient.SetAccessControlList .

Det här exemplet hämtar och anger ACL för en katalog med namnet my-directory. Strängen user::rwx,group::r-x,other::rw- ger den ägande användaren läs-, skriv- och körningsbehörigheter, ger ägande gruppen endast läs- och körningsbehörigheter och ger alla andra läs- och skrivbehörighet.

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

}

Du kan också hämta och ange ACL för rotkatalogen för en container. Om du vill hämta rotkatalogen skickar du en tom sträng ("") till metoden DataLakeFileSystemClient.GetDirectoryClient .

Ange ACL för en fil

Hämta åtkomstkontrollistan (ACL) för en fil genom att anropa metoden DataLakeFileClient.GetAccessControlAsync och ange ACL genom att anropa metoden DataLakeFileClient.SetAccessControlList .

Det här exemplet hämtar och anger ACL för en fil med namnet my-file.txt. Strängen user::rwx,group::r-x,other::rw- ger den ägande användaren läs-, skriv- och körningsbehörigheter, ger ägande gruppen endast läs- och körningsbehörigheter och ger alla andra läs- och skrivbehörighet.

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

Ange ACL:er rekursivt

Ange ACL:er rekursivt genom att anropa metoden DataLakeDirectoryClient.SetAccessControlRecursiveAsync . Skicka den här metoden till en lista överPathAccessControlItem. Varje PathAccessControlItem definierar en ACL-post.

Om du vill ange en standardpost för ACL kan du ange egenskapen PathAccessControlItem.DefaultScope för PathAccessControlItem till true.

I det här exemplet anges ACL för en katalog med namnet my-parent-directory. Den här metoden accepterar en boolesk parameter med namnet isDefaultScope som anger om standard-ACL ska anges. Den parametern används i konstruktorn för PathAccessControlItem. Posterna i ACL ger den ägande användaren läs-, skriv- och körningsbehörighet, ger ägande gruppen endast läs- och körningsbehörigheter och ger alla andra ingen åtkomst. Den senaste ACL-posten i det här exemplet ger en specifik användare med objekt-ID:t xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx läs- och körningsbehörighet.

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

Uppdatera ACL:er

När du uppdaterar en ACL ändrar du ACL:en i stället för att ersätta ACL:en. Du kan till exempel lägga till ett nytt säkerhetsobjekt till ACL utan att påverka andra säkerhetsobjekt som anges i ACL: n. Om du vill ersätta ACL:en i stället för att uppdatera den läser du avsnittet Ange ACL:er i den här artikeln.

Det här avsnittet visar hur du:

  • Uppdatera en ACL
  • Uppdatera ACL:er rekursivt

Uppdatera en ACL

Hämta först ACL:en för en katalog genom att anropa metoden DataLakeDirectoryClient.GetAccessControlAsync . Kopiera listan över ACL-poster till en ny lista överPathAccessControl-objekt . Leta sedan upp posten som du vill uppdatera och ersätt den i listan. Ange ACL genom att anropa metoden DataLakeDirectoryClient.SetAccessControlList .

Det här exemplet uppdaterar rot-ACL:en för en container genom att ersätta ACL-posten för alla andra användare.

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

   }

Uppdatera ACL:er rekursivt

Om du vill uppdatera en ACL rekursivt skapar du ett nytt ACL-objekt med den ACL-post som du vill uppdatera och använder sedan objektet i åtgärden uppdatera ACL. Hämta inte den befintliga ACL:en, ange bara ACL-poster som ska uppdateras.

Uppdatera en ACL rekursivt genom att anropa metoden DataLakeDirectoryClient.UpdateAccessControlRecursiveAsync . Skicka den här metoden till en lista överPathAccessControlItem. Varje PathAccessControlItem definierar en ACL-post.

Om du vill uppdatera en standardpost för ACL kan du ange egenskapen PathAccessControlItem.DefaultScope för PathAccessControlItem till true.

I det här exemplet uppdateras en ACL-post med skrivbehörighet. Den här metoden accepterar en boolesk parameter med namnet isDefaultScope som anger om standard-ACL ska uppdateras. Den parametern används i konstruktorn för 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);

}

Ta bort ACL-poster

Du kan ta bort en eller flera ACL-poster. Det här avsnittet visar hur du:

  • Ta bort en ACL-post
  • Ta bort ACL-poster rekursivt

Ta bort en ACL-post

Hämta först ACL:en för en katalog genom att anropa metoden DataLakeDirectoryClient.GetAccessControlAsync . Kopiera listan över ACL-poster till en ny lista överPathAccessControl-objekt . Leta sedan upp posten som du vill ta bort och anropa metoden Ta bort i samlingen. Ange den uppdaterade ACL:en genom att anropa metoden DataLakeDirectoryClient.SetAccessControlList .

Det här exemplet uppdaterar rot-ACL:en för en container genom att ersätta ACL-posten för alla andra användare.

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

}

Ta bort ACL-poster rekursivt

Om du vill ta bort ACL-poster rekursivt skapar du ett nytt ACL-objekt för ACL-post som ska tas bort och använder sedan objektet i ta bort ACL-åtgärden. Hämta inte den befintliga ACL:en. Ange bara de ACL-poster som ska tas bort.

Ta bort ACL-poster genom att anropa metoden DataLakeDirectoryClient.RemoveAccessControlRecursiveAsync . Skicka den här metoden till en lista överPathAccessControlItem. Varje PathAccessControlItem definierar en ACL-post.

Om du vill ta bort en standardpost för ACL kan du ange egenskapen PathAccessControlItem.DefaultScope för PathAccessControlItem till true.

Det här exemplet tar bort en ACL-post från ACL för katalogen med namnet my-parent-directory. Den här metoden accepterar en boolesk parameter med namnet isDefaultScope som anger om posten ska tas bort från standard-ACL. Den parametern används i konstruktorn för 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);

}

Återställa från fel

Du kan stöta på körnings- eller behörighetsfel när du ändrar ACL:er rekursivt. Starta om processen från början för körningsfel. Behörighetsfel kan inträffa om säkerhetsobjektet inte har tillräcklig behörighet för att ändra ACL för en katalog eller fil som finns i kataloghierarkin som ändras. Åtgärda behörighetsproblemet och välj sedan att antingen återuppta processen från felpunkten med hjälp av en fortsättningstoken eller starta om processen från början. Du behöver inte använda fortsättningstoken om du föredrar att starta om från början. Du kan använda ACL-poster igen utan någon negativ inverkan.

Det här exemplet returnerar en fortsättningstoken i händelse av ett fel. Programmet kan anropa den här exempelmetoden igen när felet har åtgärdats och skicka in fortsättningstoken. Om den här exempelmetoden anropas för första gången kan programmet skicka in värdet null för parametern fortsättningstoken.

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

}

Om du vill att processen ska slutföras utan avbrott av behörighetsfel kan du ange det.

För att säkerställa att processen slutförs utan avbrott skickar du in ett AccessControlChangedOptions-objekt och anger egenskapen ContinueOnFailure för objektet till true.

Det här exemplet anger ACL-poster rekursivt. Om den här koden påträffar ett behörighetsfel registrerar den det felet och fortsätter körningen. I det här exemplet skrivs antalet fel ut till konsolen.

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

Metodtips

Det här avsnittet innehåller några riktlinjer för bästa praxis för att ställa in ACL:er rekursivt.

Hantera körningsfel

Ett körningsfel kan inträffa av många orsaker (till exempel ett avbrott eller ett problem med klientanslutningen). Om du stöter på ett körningsfel startar du om den rekursiva ACL-processen. ACL:er kan tillämpas på objekt igen utan att orsaka en negativ inverkan.

Hantera behörighetsfel (403)

Om du stöter på ett undantag för åtkomstkontroll när du kör en rekursiv ACL-process kanske ditt AD-säkerhetsobjekt inte har tillräcklig behörighet för att tillämpa en ACL på ett eller flera av de underordnade objekten i kataloghierarkin. När ett behörighetsfel inträffar stoppas processen och en fortsättningstoken tillhandahålls. Åtgärda behörighetsproblemet och använd sedan fortsättningstoken för att bearbeta den återstående datauppsättningen. Katalogerna och filerna som redan har bearbetats behöver inte bearbetas igen. Du kan också välja att starta om den rekursiva ACL-processen. ACL:er kan tillämpas på objekt igen utan att orsaka en negativ inverkan.

Autentiseringsuppgifter

Vi rekommenderar att du etablerar ett Microsoft Entra-säkerhetsobjekt som har tilldelats rollen Storage Blob Data Owner i omfånget för mållagringskontot eller containern.

Prestanda

För att minska svarstiden rekommenderar vi att du kör den rekursiva ACL-processen på en virtuell Azure-dator (VM) som finns i samma region som ditt lagringskonto.

ACL-gränser

Det maximala antalet ACL:er som du kan använda för en katalog eller fil är 32 åtkomst-ACL:er och 32 standard-ACL:er. Mer information finns i Åtkomstkontroll i Azure Data Lake Storage Gen2.

Se även