Stratégie de sécurité au niveau des lignes
S’applique à : ✅Microsoft Fabric✅Azure Data Explorer
Utilisez l’appartenance au groupe ou le contexte d’exécution pour contrôler l’accès aux lignes d’une table de base de données.
La sécurité au niveau des lignes (SNL) simplifie la conception et le codage de la sécurité. Elle vous permet d’appliquer des restrictions à l’accès aux lignes de données dans votre application. Par exemple, limitez l’accès des utilisateurs aux lignes pertinentes pour leur service ou limitez l’accès client aux données pertinentes pour leur entreprise.
La logique de restriction d’accès est implémentée dans la couche Base de données plutôt qu’à l’écart des données dans une autre couche Application. Le système de base de données applique les restrictions d’accès chaque fois que l’accès aux données est tenté à partir de n’importe quel niveau. Cette logique rend votre système de sécurité plus fiable et robuste en réduisant la surface d’exposition de votre système de sécurité.
RLS vous permet de fournir l’accès à d’autres applications et utilisateurs, uniquement à une partie spécifique d’une table. Vous pouvez, par exemple, souhaiter effectuer les opérations suivantes :
- Accorder l’accès uniquement aux lignes répondant à certains critères
- Anonymiser les données dans certaines des colonnes
- Toutes les options ci-dessus
Remarque
Lorsqu’une stratégie RLS est activée sur une table, l’accès est entièrement remplacé par la requête RLS définie sur la table. La restriction d’accès s’applique à tous les utilisateurs, y compris les administrateurs de base de données et le créateur RLS. La requête RLS doit inclure explicitement des définitions pour tous les types d’utilisateurs auxquels vous souhaitez accorder l’accès.
Pour plus d’informations, consultez les commandes de gestion pour la gestion de la stratégie sécurité au niveau des lignes.
Conseil
Ces fonctions sont souvent utiles pour les requêtes row_level_security :
Limites
- Il n’existe aucune limite quant au nombre de tables sur lesquelles la stratégie sécurité au niveau des lignes peut être configurée.
- Impossible de configurer la stratégie de sécurité au niveau des lignes sur les tables externes.
- La stratégie RLS ne peut pas être activée sur une table dans les circonstances suivantes :
- Lorsqu’elle est référencée par une requête de stratégie de mise à jour , alors que la stratégie de mise à jour n’est pas configurée avec une identité managée.
- Lorsqu’elle est référencée par une exportation continue qui utilise une méthode d’authentification autre que l’emprunt d’identité.
- Lorsqu’une stratégie d’accès en mode restreint est configurée pour la table.
- La requête RLS ne peut pas référencer les tables situées dans d’autres bases de données.
Exemples
Limiter l’accès à la table Sales
Dans une table nommée Sales
, chaque ligne contient des détails sur une vente. L’une des colonnes contient le nom de l’vendeur. Au lieu de donner à vos vendeurs l’accès à tous les enregistrements, Sales
activez une stratégie de sécurité au niveau des lignes sur cette table pour retourner uniquement les enregistrements où le vendeur est l’utilisateur actuel :
Sales | where SalesPersonAadUser == current_principal()
Vous pouvez également masquer l’adresse e-mail :
Sales | where SalesPersonAadUser == current_principal() | extend EmailAddress = "****"
Si vous souhaitez que chaque vendeur voit toutes les ventes d’un pays/région spécifique, vous pouvez définir une requête similaire à :
let UserToCountryMapping = datatable(User:string, Country:string)
[
"john@domain.com", "USA",
"anna@domain.com", "France"
];
Sales
| where Country in ((UserToCountryMapping | where User == current_principal_details()["UserPrincipalName"] | project Country))
Si vous avez un groupe qui contient les gestionnaires, vous pouvez leur donner accès à toutes les lignes. Voici la requête pour la stratégie sécurité au niveau des lignes.
let IsManager = current_principal_is_member_of('aadgroup=sales_managers@domain.com');
let AllData = Sales | where IsManager;
let PartialData = Sales | where not(IsManager) and (SalesPersonAadUser == current_principal()) | extend EmailAddress = "****";
union AllData, PartialData
Exposer différentes données à des membres de différents groupes Microsoft Entra
Si vous avez plusieurs groupes Microsoft Entra et que vous souhaitez que les membres de chaque groupe voient un sous-ensemble de données différent, utilisez cette structure pour une requête RLS.
Customers
| where (current_principal_is_member_of('aadgroup=group1@domain.com') and <filtering specific for group1>) or
(current_principal_is_member_of('aadgroup=group2@domain.com') and <filtering specific for group2>) or
(current_principal_is_member_of('aadgroup=group3@domain.com') and <filtering specific for group3>)
Appliquer la même fonction RLS sur plusieurs tables
Tout d’abord, définissez une fonction qui reçoit le nom de la table en tant que paramètre de chaîne et référencez la table à l’aide de l’opérateur table()
.
Par exemple :
.create-or-alter function RLSForCustomersTables(TableName: string) {
table(TableName)
| ...
}
Ensuite, configurez RLS sur plusieurs tables de cette façon :
.alter table Customers1 policy row_level_security enable "RLSForCustomersTables('Customers1')"
.alter table Customers2 policy row_level_security enable "RLSForCustomersTables('Customers2')"
.alter table Customers3 policy row_level_security enable "RLSForCustomersTables('Customers3')"
Générer une erreur lors d’un accès non autorisé
Si vous souhaitez que les utilisateurs de table non autorisés reçoivent une erreur au lieu de retourner une table vide, utilisez la assert()
fonction. L’exemple suivant montre comment générer cette erreur dans une fonction RLS :
.create-or-alter function RLSForCustomersTables() {
MyTable
| where assert(current_principal_is_member_of('aadgroup=mygroup@mycompany.com') == true, "You don't have access")
}
Vous pouvez combiner cette approche avec d’autres exemples. Par exemple, vous pouvez afficher différents résultats aux utilisateurs de différents groupes Microsoft Entra et générer une erreur pour tous les autres utilisateurs.
Contrôler les autorisations sur les bases de données de suivi
La stratégie RLS que vous configurez sur la base de données de production prend également effet dans les bases de données de suivi. Vous ne pouvez pas configurer différentes stratégies RLS sur les bases de données de production et de suivi. Toutefois, vous pouvez utiliser la current_cluster_endpoint()
fonction dans votre requête RLS pour obtenir le même effet, comme avoir des requêtes RLS différentes dans les tables de suivi.
Par exemple :
.create-or-alter function RLSForCustomersTables() {
let IsProductionCluster = current_cluster_endpoint() == "mycluster.eastus.kusto.windows.net";
let DataForProductionCluster = TempTable | where IsProductionCluster;
let DataForFollowerClusters = TempTable | where not(IsProductionCluster) | extend EmailAddress = "****";
union DataForProductionCluster, DataForFollowerClusters
}
Remarque
La fonction RLS ci-dessus n’a aucun impact sur les performances sur les requêtes sur le cluster leader. L’impact sur les performances sur les requêtes sur les clusters de suivi n’est affecté que par la complexité de DataForFollowerClusters
.
Contrôler les autorisations sur les bases de données de raccourci
La stratégie RLS que vous configurez sur la base de données de production prend également effet dans les bases de données de raccourci. Vous ne pouvez pas configurer différentes stratégies RLS sur les bases de données de production et de raccourci. Toutefois, vous pouvez utiliser la current_cluster_endpoint()
fonction dans votre requête RLS pour obtenir le même effet, car il existe différentes requêtes RLS dans les tables de raccourcis.
Par exemple :
.create-or-alter function RLSForCustomersTables() {
let IsProductionCluster = current_cluster_endpoint() == "mycluster.eastus.kusto.windows.net";
let DataForProductionCluster = TempTable | where IsProductionCluster;
let DataForFollowerClusters = TempTable | where not(IsProductionCluster) | extend EmailAddress = "****";
union DataForProductionCluster, DataForFollowerClusters
}
Remarque
La fonction RLS ci-dessus n’a aucun impact sur les performances des requêtes sur la base de données source. L’impact sur les performances sur les requêtes sur les bases de données de raccourcis n’est affecté que par la complexité de DataForFollowerClusters
.
Autres cas d’utilisation
- Une personne de support du centre d’appels peut identifier les appelants par plusieurs chiffres de leur numéro de sécurité sociale. Ce nombre ne doit pas être entièrement exposé à la personne de soutien. Une stratégie RLS peut être appliquée sur la table pour masquer tous les quatre derniers chiffres du numéro de sécurité sociale dans le jeu de résultats de n’importe quelle requête.
- Définissez une stratégie RLS qui masque les informations d’identification personnelle (PII) et permet aux développeurs d’interroger des environnements de production à des fins de résolution des problèmes sans violer les réglementations de conformité.
- Un hôpital peut définir une stratégie RLS qui permet aux infirmières d’afficher les lignes de données pour leurs patients uniquement.
- Une banque peut définir une stratégie RLS pour restreindre l’accès aux lignes de données financières en fonction de la division ou du rôle d’un employé.
- Une application multilocataire peut stocker des données de nombreux locataires dans un ensemble de tables unique (ce qui est efficace). Ils utilisent une stratégie RLS pour appliquer une séparation logique des lignes de données de chaque locataire des lignes de chaque autre locataire, afin que chaque locataire puisse voir uniquement ses lignes de données.
Impact sur les performances sur les requêtes
Lorsqu’une stratégie RLS est activée sur une table, il y aura un impact sur les performances sur les requêtes qui accèdent à cette table. L’accès à la table sera remplacé par la requête RLS définie sur cette table. L’impact sur les performances d’une requête RLS se compose normalement de deux parties :
- Vérifications d’appartenance dans Microsoft Entra ID : les vérifications sont efficaces. Vous pouvez vérifier l’appartenance en dizaines, voire des centaines de groupes sans impact majeur sur les performances de la requête.
- Filtres, jointures et autres opérations appliquées aux données : l’impact dépend de la complexité de la requête
Par exemple :
let IsRestrictedUser = current_principal_is_member_of('aadgroup=some_group@domain.com');
let AllData = MyTable | where not(IsRestrictedUser);
let PartialData = MyTable | where IsRestrictedUser and (...);
union AllData, PartialData
Si l’utilisateur ne fait pas partie de some_group@domain.com, IsRestrictedUser
il est évalué à false
. La requête évaluée est similaire à celle-ci :
let AllData = MyTable; // the condition evaluates to `true`, so the filter is dropped
let PartialData = <empty table>; // the condition evaluates to `false`, so the whole expression is replaced with an empty table
union AllData, PartialData // this will just return AllData, as PartialData is empty
De même, si elle IsRestrictedUser
est true
évaluée, seule la requête à PartialData
laquelle sera évaluée.
Améliorer les performances des requêtes lorsque RLS est utilisé
- Si un filtre est appliqué à une colonne de cardinalité élevée, par exemple, DeviceID, envisagez d’utiliser la stratégie de partitionnement ou la stratégie Ordre des lignes
- Si un filtre est appliqué à une colonne de cardinalité faible moyenne, envisagez d’utiliser la stratégie Ordre des lignes
Impact sur les performances sur l’ingestion
Il n’y a aucun impact sur les performances sur l’ingestion.