Partager via


Sécurité au niveau des lignes

Utilisez l’appartenance à un 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 des clients aux seules 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 certaine partie d’une table. Vous pouvez, par exemple, souhaiter effectuer les opérations suivantes :

  • Accorder l’accès uniquement aux lignes qui répondent à certains critères
  • Anonymiser les données dans certaines colonnes
  • Toutes les options ci-dessus

Notes

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 du SNL. 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 Commandes de gestion pour la gestion de la stratégie de 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 de sécurité au niveau des lignes peut être configurée.
  • La stratégie de sécurité au niveau des lignes ne peut pas être configurée sur les tables externes.
  • La stratégie RLS ne peut pas être activée sur une table dans les circonstances suivantes :

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 du vendeur. Au lieu de donner à vos vendeurs l’accès à tous les enregistrements dans Sales, activez une stratégie de sécurité au niveau des lignes sur cette table pour renvoyer 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 ou d’une 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 de 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 des données différentes aux 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érence la table à l’aide de l’opérateur table() .

Par exemple :

.create-or-alter function RLSForCustomersTables(TableName: string) {
    table(TableName)
    | ...
}

Configurez ensuite 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')"

Produire 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 produire 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 des résultats différents pour les utilisateurs de différents groupes Microsoft Entra et générer une erreur pour tous les autres.

Autorisations de contrôle sur les bases de données d’suiveur

La stratégie RLS que vous configurez sur la base de données de production prend également effet dans les bases de données d’suiveurs. 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, que d’avoir différentes requêtes RLS dans les tables suivantes.

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
}

Notes

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 d’adeptes sera uniquement affecté par la complexité de DataForFollowerClusters.

Autres cas d’usage

  • 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 support. 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 les 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 de 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’entreprise d’un employé.
  • Une application multilocataire peut stocker des données provenant de nombreux locataires dans un jeu de tables unique (ce qui est efficace). Ils utiliseraient une stratégie RLS pour appliquer une séparation logique des lignes de données de chaque locataire des lignes de tous les autres locataires, 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 a 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 case activée l’appartenance à des dizaines, voire des centaines de groupes, sans impact majeur sur les performances des requêtes.
  • 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, est IsRestrictedUser é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 IsRestrictedUser prend truela valeur , seule la requête pour PartialData sera évaluée.

Améliorer les performances des requêtes lorsque RLS est utilisé

Impact sur les performances sur l’ingestion

Il n’y a aucun impact sur les performances sur l’ingestion.