Utiliser Python pour gérer les listes de contrôle d’accès dans Azure Data Lake Storage Gen2

Cet article explique comment utiliser Python pour récupérer, définir et mettre à jour les listes de contrôle d’accès des répertoires et des fichiers.

L’héritage des listes ACL est déjà disponible pour les nouveaux éléments enfants créés sous un répertoire parent. Toutefois, vous pouvez également ajouter, mettre à jour et supprimer des listes de contrôle d’accès de manière récursive au niveau des éléments enfants existants d’un répertoire parent sans avoir à apporter ces modifications individuellement à chaque élément enfant.

Package (Python Package Index) | Exemples | Exemples de listes de contrôle d’accès récursives | Référence de l’API | Mappage de Gen1 à Gen2 | Envoyer des commentaires

Prérequis

  • Un abonnement Azure. Pour plus d’informations, consultez Obtenir l’essai gratuit Azure.

  • Un compte de stockage doté d’un espace de noms hiérarchique (HNS) activé. Pour créer un test, suivez ces instructions.

  • Azure CLI version 2.6.0 ou ultérieure.

  • Une des autorisations de sécurité suivantes :

    • Un principal de sécurité Microsoft Entra ID approvisionné qui a reçu le rôle Propriétaire des données d’objet de stockage Blob dans l’étendue du conteneur cible, du compte de stockage, du groupe de ressources parent ou de l’abonnement.

    • Utilisateur propriétaire du conteneur ou du répertoire cible auquel vous envisagez d’appliquer les paramètres ACL. Pour définir des listes de contrôle d’accès de façon récursive, cela inclut tous les éléments enfants du conteneur ou du répertoire cible.

    • Clé du compte de stockage.

Configuration de votre projet

Installez la bibliothèque cliente Azure Data Lake Storage pour Python à l’aide de pip.

pip install azure-storage-file-datalake

Ajoutez les instructions d’importation suivantes au début de votre fichier de code.

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

Se connecter au compte

Pour utiliser les extraits de code de cet article, vous devez créer une instance DataLakeServiceClient qui représente le compte de stockage.

Se connecter à l’aide de Microsoft Entra ID

Remarque

Si vous utilisez Microsoft Entra ID pour autoriser l’accès, assurez-vous que le rôle Propriétaire des données blob du stockage est attribué à votre principal de sécurité. Pour en savoir plus sur l’application des autorisations de liste de contrôle d’accès et les conséquences de leur modification, consultez Modèle de contrôle d’accès dans Azure Data Lake Storage Gen2.

Vous pouvez utiliser la bibliothèque de client Azure Identity pour Python afin d’authentifier votre application auprès de Microsoft Entra ID.

Vous devrez d’abord attribuer l’un des rôles Contrôle d’accès en fonction du rôle (Azure RBAC) suivants à votre principal de sécurité :

Role Capacité de paramétrage ACL
Propriétaire des données Blob du stockage Tous les répertoires et fichiers du compte.
Contributeur aux données Blob du stockage Seuls les répertoires et les fichiers appartenant au principal de sécurité.

Ensuite, créez une instance DataLakeServiceClient et transmettez une nouvelle instance de la 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

Pour en savoir plus sur l’utilisation de DefaultAzureCredential pour autoriser l’accès aux données, consultez Vue d’ensemble : authentifier des applications Python sur Azure à l’aide du kit de développement logiciel (SDK) Azure.

Connexion avec une clé de compte

Vous pouvez autoriser l’accès aux données en utilisant des clés d’accès de votre compte (clé partagée). Cet exemple crée une instance DataLakeServiceClient qui est autorisée avec la clé de compte.

def get_service_client_account_key(self, account_name, account_key) -> DataLakeServiceClient:
    account_url = f"https://{account_name}.dfs.core.windows.net"
    service_client = DataLakeServiceClient(account_url, credential=account_key)

    return service_client

Attention

L’autorisation avec une clé partagée n’est pas recommandée, car elle peut être moins sécurisée. Pour une sécurité optimale, désactivez l’autorisation via une clé partagée pour votre compte de stockage, comme décrit dans Empêcher l’autorisation avec clé partagée pour un compte de stockage Azure.

L’utilisation de clés d’accès et de chaînes de connexion doit être limitée aux applications de preuve de concept initiales ou aux prototypes de développement qui n’accèdent pas aux données de production ou aux données sensibles. Sinon, les classes d’authentification basées sur des jetons disponibles dans le kit de développement logiciel (SDK) Azure doivent toujours être priorisées lors de l’authentification auprès de ressources Azure.

Microsoft recommande aux clients d’utiliser Microsoft Entra ID ou une signature d’accès partagé (SAP) pour autoriser l’accès aux données dans le service Stockage Azure. Pour en savoir plus, consultez Autoriser les opérations pour l’accès aux données.

Définir les listes de contrôle d’accès

Lorsque vous définissez une liste de contrôle d’accès (ACL), vous remplacez l’ensemble de l’ACL, y compris toutes ses entrées. Si vous souhaitez modifier le niveau d’autorisation d’un principal de sécurité ou ajouter un nouveau principal de sécurité à la liste de contrôle d’accès sans affecter d’autres entrées existantes, vous devez mettre à jour l’ACL à la place. Pour mettre à jour une liste de contrôle d’accès au lieu de la remplacer, consultez la section Mettre à jour une liste de contrôle d’accès de cet article.

Cette section vous montre comment :

  • Définir la liste de contrôle d’accès d’un répertoire
  • Définir la liste de contrôle d’accès d’un fichier

Définir la liste de contrôle d’accès d’un répertoire

Obtenez la liste de contrôle d’accès (ACL) d’un répertoire en appelant la méthode DataLakeDirectoryClient.get_access_control et définissez l’ACL en appelant la méthode DataLakeDirectoryClient.set_access_control.

Cet exemple obtient et définit la liste ACL d’un répertoire nommé my-directory. La chaîne rwxr-xrw- donne à l’utilisateur propriétaire des autorisations de lecture, d’écriture et d’exécution, donne au groupe propriétaire uniquement des autorisations de lecture et d’exécution et donne à tous les autres l’accès en lecture et en écriture.

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)

Vous pouvez également obtenir et définir la liste de contrôle d’accès du répertoire racine d’un conteneur. Pour récupérer le répertoire racine, appelez la méthode FileSystemClient._get_root_directory_client.

Définir la liste de contrôle d’accès d’un fichier

Obtenez la liste de contrôle d’accès (ACL) d’un fichier en appelant la méthode DataLakeFileClient.get_access_control et définissez l’ACL en appelant la méthode DataLakeFileClient.set_access_control.

Cet exemple obtient et définit la liste ACL d’un fichier nommé my-file.txt. La chaîne rwxr-xrw- donne à l’utilisateur propriétaire des autorisations de lecture, d’écriture et d’exécution, donne au groupe propriétaire uniquement des autorisations de lecture et d’exécution et donne à tous les autres l’accès en lecture et en écriture.

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)

Définir des listes de contrôle d’accès de façon récursive

Lorsque vous définissez une liste de contrôle d’accès (ACL), vous remplacez l’ensemble de l’ACL, y compris toutes ses entrées. Si vous souhaitez modifier le niveau d’autorisation d’un principal de sécurité ou ajouter un nouveau principal de sécurité à la liste de contrôle d’accès sans affecter d’autres entrées existantes, vous devez mettre à jour l’ACL à la place. Pour mettre à jour une liste de contrôle d’accès au lieu de la remplacer, consultez la section Mettre à jour les listes de contrôle d’accès de manière récursive de cet article.

Définissez les listes de contrôle d’accès de manière récursive en appelant la méthode DataLakeDirectoryClient.set_access_control_recursive.

Si vous souhaitez définir une entrée de liste de contrôle d’accès par défaut, ajoutez la chaîne default: au début de chaque chaîne d’entrée de liste de contrôle d’accès.

Cet exemple définit la liste ACL d’un répertoire nommé my-parent-directory.

Cette méthode accepte un paramètre booléen nommé is_default_scope qui spécifie s’il faut définir la liste de contrôle d’accès par défaut. Si ce paramètre est True, la liste des entrées ACL est précédée de la chaîne default:. Dans cet exemple, les entrées accordent les autorisations suivantes : autorisations de lecture, d’écriture et d’exécution pour l’utilisateur-propriétaire, autorisations de lecture et d’exécution pour le groupe propriétaire et autorisations de lecture pour tous les autres. La dernière entrée ACL dans cet exemple donne à un utilisateur spécifique, avec l’ID d’objet xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, des autorisations de lecture.

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)

Pour voir un exemple qui traite des ACL de manière récursive dans des lots en spécifiant une taille de lot, consultez l’exemple Python.

Mettre à jour les listes de contrôle d’accès de manière récursive

Lorsque vous mettez à jour une liste de contrôle d’accès, vous modifiez l’ACL au lieu de la remplacer. Par exemple, vous pouvez ajouter un nouveau principal de sécurité à la liste de contrôle d’accès sans affecter les autres principaux de sécurité listés dans l’ACL. Pour remplacer la liste de contrôle d’accès au lieu de la mettre à jour, consultez la section Mettre à jour une liste de contrôle d’accès de cet article.

Pour mettre à jour une liste de contrôle d’accès de manière récursive, créez un objet ACL avec l’entrée ACL à mettre à jour, puis utilisez cet objet dans l’opération de mise à jour de l’ACL. Ne récupérez pas la liste de contrôle d’accès existante, il vous suffit de fournir les entrées ACL à mettre à jour. Mettez à jour une liste de contrôle d’accès de manière récursive en appelant la méthode DataLakeDirectoryClient.update_access_control_recursive. Si vous souhaitez mettre à jour une entrée de liste de contrôle d’accès par défaut, ajoutez la chaîne default: au début de chaque chaîne d’entrée de liste de contrôle d’accès.

Cet exemple met à jour une entrée de liste de contrôle d’accès avec l’autorisation d’écriture.

Cet exemple définit la liste ACL d’un répertoire nommé my-parent-directory. Cette méthode accepte un paramètre booléen nommé is_default_scope qui spécifie s’il faut mettre à jour la liste de contrôle d’accès par défaut. Si la valeur de ce paramètre est True, l’entrée de la liste de contrôle d'accès mise à jour est précédée de la chaîne 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)

Pour voir un exemple qui traite des ACL de manière récursive dans des lots en spécifiant une taille de lot, consultez l’exemple Python.

Supprimer des entrées de liste de contrôle d’accès (ACL) de manière récursive

Vous pouvez supprimer une ou plusieurs entrées ACL. Pour supprimer des entrées ACL de manière récursive, créez un objet ACL pour l’entrée ACL à supprimer, puis utilisez cet objet dans l’opération de suppression de l’ACL. Ne récupérez pas la liste de contrôle d’accès existante, il vous suffit de fournir les entrées ACL à supprimer.

Supprimez des entrées de liste de contrôle d’accès en appelant la méthode DataLakeDirectoryClient.remove_access_control_recursive. Si vous souhaitez supprimer une entrée de liste de contrôle d’accès par défaut, ajoutez la chaîne default: au début de la chaîne d’entrée de liste de contrôle d’accès.

Cet exemple supprimer une entrée de liste de contrôle d’accès dans la liste ACL du répertoire nommé my-parent-directory. Cette méthode accepte un paramètre booléen nommé is_default_scope qui spécifie s’il faut supprimer l’entrée de la liste de contrôle d’accès par défaut. Si la valeur de ce paramètre est True, l’entrée de la liste de contrôle d'accès mise à jour est précédée de la chaîne 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)

Pour voir un exemple qui traite des ACL de manière récursive dans des lots en spécifiant une taille de lot, consultez l’exemple Python.

Récupérer suite à des échecs

Vous pouvez rencontrer des erreurs d’exécution ou d’autorisation. Pour les erreurs d’exécution, redémarrez le processus à partir du début. Des erreurs d’autorisation peuvent se produire si le principal de sécurité ne dispose pas des autorisations suffisantes pour modifier la liste de contrôle d’accès d’un répertoire ou d’un fichier qui se trouve dans la hiérarchie de répertoires en cours de modification. Résolvez le problème d’autorisation, puis choisissez de reprendre le processus à partir du point de défaillance à l’aide d’un jeton de continuation ou de redémarrer le processus à partir du début. Vous n’êtes pas obligé d’utiliser le jeton de continuation si vous préférez redémarrer à partir du début. Vous pouvez réappliquer les entrées de liste de contrôle d’accès sans incidence négative.

Cet exemple retourne un jeton de continuation en cas d’échec. L’application peut appeler à nouveau cet exemple de méthode une fois que l’erreur a été traitée et transmettre le jeton de continuation. Si cet exemple de méthode est appelé pour la première fois, l’application peut transmettre une valeur de None pour le paramètre de jeton de continuation.

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

Pour voir un exemple qui traite des ACL de manière récursive dans des lots en spécifiant une taille de lot, consultez l’exemple Python.

Si vous souhaitez que le processus se termine sans être interrompu par des erreurs d’autorisation, vous pouvez le spécifier.

Pour vous assurer que le processus se termine sans interruption, ne passez pas de jeton de continuation dans la méthode DataLakeDirectoryClient.set_access_control_recursive.

Cet exemple définit les entrées ACL de manière récursive. Si ce code rencontre une erreur d’autorisation, il enregistre cet échec et poursuit l’exécution. Cet exemple inscrit le nombre d’échecs sur la 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)

Pour voir un exemple qui traite des ACL de manière récursive dans des lots en spécifiant une taille de lot, consultez l’exemple Python.

Bonnes pratiques

Cette section décrit certaines des meilleures pratiques pour définir des listes de contrôle d’accès (ACL) de manière récursive.

Traitement des erreurs d’exécution

Une erreur d’exécution peut se produire pour de nombreuses raisons (par exemple, une panne ou un problème de connectivité client). Si vous rencontrez une erreur d’exécution, redémarrez le processus ACL récursif. Les listes de contrôle d’accès peuvent être réappliquées à des éléments sans impact négatif.

Traitement des erreurs d’autorisation (403)

Si vous rencontrez une exception de contrôle d’accès lors de l’exécution d’un processus ACL récursif, votre principal de sécurité AD peut ne pas disposer des autorisations suffisantes pour appliquer une liste de contrôle d’accès à un ou plusieurs des éléments enfants dans la hiérarchie de répertoires. Lorsqu’une erreur d’autorisation se produit, le processus s’arrête et un jeton de continuation est fourni. Corrigez le problème d’autorisation, puis utilisez le jeton de continuation pour traiter le jeu de données restant. Les répertoires et les fichiers qui ont déjà été traités correctement n’ont pas besoin d’être retraités. Vous pouvez également choisir de redémarrer le processus ACL récursif. Les listes de contrôle d’accès peuvent être réappliquées à des éléments sans impact négatif.

Informations d'identification

Nous vous recommandons de d’approvisionner un principal de sécurité Microsoft Entra auquel a été attribué le rôle Propriétaire des données Blob de stockage dans l’étendue du conteneur ou du compte de stockage cible.

Performances

Pour réduire la latence, nous vous recommandons d’exécuter le processus ACL récursif dans une machine virtuelle Azure située dans la même région que votre compte de stockage.

Limites des listes de contrôle d’accès (ACL)

Le nombre maximal de listes ACL que vous pouvez appliquer à un répertoire ou à un fichier est de 32 ACL d’accès et de 32 ACL par défaut. Pour plus d’informations, consultez Contrôle d’accès dans Azure Data Lake Storage Gen2.

Voir aussi