Article
· Jan 29 8m de lecture

Sécurité des sous-tables

InterSystems IRIS offre de nombreuses options de sécurité configurables, mais beaucoup de développeurs utilisent surtout des rôles et des ressources pour sécuriser des tables ou des routines entières. Aujourd'hui, on va aller plus loin. On peut aussi sécuriser des colonnes et des lignes individuelles séparément, mais ces deux mécanismes fonctionnent très différemment. Commençons par les colonnes.

Sécurité des colonnes

À des fins de test et de démonstration, nous allons conserver une structure de table concise et simple. Nous avons une table appelée "Person" (Personne) dans l'espace de noms USER qui contient une colonne ID, une colonne date de naissance (DOB), et des colonnes prénom et nom. 

Class User.Person Extends %Persistent
{
    Property FirstName As %String;
    Property LastName As %String;
    Property DOB As %Date;
    Property User As %String;
}

Nous allons créer un rôle appelé limited_access qui mettra en œuvre certaines mesures de sécurité au niveau des colonnes, mais avant toute chose, nous devons veiller à ajouter la ressource %DB_User à ce rôle afin que l'utilisateur ait accès à la base de données. Cela fait, nous pouvons commencer à réfléchir aux colonnes. Nous allons dans l'onglet Tables SQL de la configuration des rôles pour nous assurer que l'espace de noms USER est sélectionné. Ensuite, nous cliquons sur le bouton Add Columns (Ajouter des colonnes), situé à droite du bouton Add Tables (Ajouter des tables). Une boîte de dialogue s'ouvre alors, où nous pouvons contrôler les autorisations des colonnes.

Cette interface ressemble beaucoup à l'écran utilisé pour ajouter des autorisations pour les tables. La seule différence remarquable est l'option DELETE, qui ne peut pas être contrôlée au niveau des colonnes. Cela est logique, car nous ne pouvons pas supprimer des colonnes individuelles d'un enregistrement dans une table. Cependant, nous conservons le contrôle sur les privilèges SELECT, INSERT, UPDATE et REFERENCES. Nous pouvons également utiliser les cases à cocher Grant Admin pour permettre aux utilisateurs disposant de ce rôle de déléguer le même privilège à d'autres utilisateurs ou rôles. Dans l'exemple d'aujourd'hui, nous allons accorder au rôle toutes les autorisations pour les colonnes ID, FirstName et LastName. Cependant, nous attribuerons uniquement le privilège SELECT pour la colonne DOB. Après avoir effectué ces modifications, nous enregistrerons le rôle. Vous remarquerez alors que la saisie pour cette table dans la configuration du rôle affiche un tiret (-) sous la colonne des privilèges. Cependant, elle comprend une option Edit Column.

Si nous cliquons sur le lien Edit Columns (Modifier les colonnes) à droite, nous pouvons consulter les autorisations exactes définies pour chaque colonne individuellement.

Ici, nous pouvons modifier ou révoquer des autorisations spécifiques pour certaines colonnes. Si nous cochons la case Add Columns (Ajouter des colonnes), le formulaire de configuration initial permettant d'ajouter des colonnes réapparaîtra ci-dessous, ce qui nous permettra d'effectuer d'autres ajouts. Si vous rencontrez une table répertoriée dans un rôle qui semble ne pas disposer des privilèges définis, vous devez cliquer sur le lien Edit Columns (Modifier les colonnes) pour vérifier les autorisations spécifiques à chaque colonne.

Afin de tester cette configuration, nous devons configurer un utilisateur doté de ce rôle. Nous nommerons cet utilisateur testuser. Il possédera notre rôle limited_access, et nous lui accorderons également le rôle %Developer afin qu'il puisse accéder à la partie SQL du portail de gestion et exécuter certaines requêtes. Prenons par exemple la requête SQL suivante.

INSERT INTO Person(DOB,FirstName,LastName) VALUES(%ODBCIN('1900-09-03'),'David','Hockenbroch')

Si nous exécutons cette requête en étant connecté en tant que superutilisateur avec les privilèges %All, la requête réussira. Cependant, si nous nous déconnectons du portail de gestion et nous reconnectons en tant qu'utilisateur test, une erreur se produira.

La requête échoue car l'utilisateur ne dispose pas des autorisations nécessaires pour saisir des données dans la colonne DOB. Si nous modifions la requête afin d'omettre la colonne restreinte, elle s'exécutera correctement. La requête suivante fonctionnera toujours pour cet utilisateur:

INSERT INTO Person(FirstName,LastName) VALUES('David','Hockenbroch')

De même, si l'utilisateur ne dispose pas des autorisations nécessaires pour mettre à jour ou sélectionner une colonne, toute requête violant ces restrictions échouera. Par exemple, si je supprime complètement la colonne DOB des privilèges de colonne, je ne pourrai pas exécuter la commande SELECT * FROM Person. Je devrai alors utiliser SELECT ID, FirstName, LastName FROM Person. Notez que si un utilisateur n'a pas accès à certaines colonnes calculées, les calculs seront tout de même exécutés correctement.

Si nous modifions légèrement la définition de notre classe, nous pouvons introduire un tout nouveau problème. Supposons que nous décidions de modifier la définition de notre classe pour inclure le mot-clé Required dans la propriété DOB. Si nous essayons ensuite d'exécuter la requête indiquée ci-dessus, cela provoquera une erreur au lieu de réussir.

Vous devez tenir compte de cela lorsque vous définissez les privilèges sur les colonnes: si vous refusez à un utilisateur l'autorisation INSERT pour une colonne donnée qui n'est pas attribuée automatiquement via un code de calcul, une expression initiale ou une méthode similaire, l'utilisateur ne pourra absolument pas insérer de lignes!

Sécurité au niveau des lignes

Nous allons maintenant aborder la sécurité au niveau des lignes. Notre objectif sera de garantir uniquement l'accès à une ligne à l'utilisateur qui l'a créée.

La sécurité au niveau des lignes est très différente de la sécurité au niveau des colonnes. Nous ne pouvons pas la configurer via le portail de gestion. Nous devons plutôt modifier notre définition de classe. Tout d'abord, nous devons ajouter une propriété:

Property Creator As %String [ SqlComputeCode = {set {*} = $USERNAME}, SqlComputed, SqlComputeOnChange = %%INSERT];

Il s'agit d'une propriété calculée SQL qui attribue automatiquement sa valeur au nom d'utilisateur actuel lorsqu'une ligne est insérée. Nous insérerons une ligne par utilisateur. Nous devrions alors observer les enregistrements suivants:

Ensuite, nous devons remplacer le paramètre ROWLEVELSECURITY dans la définition de classe. En le définissant à 1, IRIS stockera automatiquement la liste des lecteurs dans une propriété nommée %READERLIST. Cependant, dans notre cas, puisque nous avons créé une propriété pour stocker le nom d'utilisateur qui doit avoir accès à la ligne, nous remplacerons ce paramètre par le nom de cette colonne (Creator). N'oubliez pas que, comme la sécurité au niveau des lignes peut être gérée par rôle ou par nom d'utilisateur, nous pourrions utiliser plutôt une colonne contenant un nom de rôle si nous le souhaitions.

Si nous essayons maintenant de sélectionner des données dans cette table, la requête renverra un résultat vide. Ceci est dû au fait que nous avons ajouté la sécurité au niveau des lignes à une table existante, et que la sécurité au niveau des lignes repose sur la création d'un index pour le champ utilisé à des fins de sécurité. Nous devons maintenant reconstruire les index de la table. Nous allons le faire via le portail de gestion. Dans la zone SQL, nous sélectionnons la table à gauche, puis nous cliquons sur Actions et enfin sur Rebuild Table's Indices (Reconstruire les index de la table).

Maintenant que l'index approprié existe, lorsque les utilisateurs effectuent une sélection dans la table, ils ne voient que leurs propres lignes. Il est essentiel de noter que cette restriction s'applique même aux superutilisateurs ! Dans la plupart des contextes de sécurité dans IRIS, le rôle %All accorde l'accès à pratiquement tout, mais la sécurité au niveau des lignes est une exception notable. Même si nous exécutons une requête DELETE * FROM Person en tant que superutilisateur, elle ne supprimera que les lignes auxquelles le superutilisateur est autorisé à accéder.

Nous pourrions obtenir le même résultat d'une autre manière. Cette fois-ci, définissons le paramètre ROWLEVELSECURITY à 1, mais ajoutons une méthode %SecurityPolicy à notre classe.

ClassMethod %SecurityPolicy(Creator) As %String [ SqlProc ]
{
    return Creator
}

Cette méthode est définie comme une méthode de classe qui renvoie une chaîne et utilise le mot-clé SqlProc. Elle peut accepter n'importe quel nombre d'arguments, mais ceux-ci doivent être des noms de colonnes provenant de la classe elle-même, et les noms des arguments doivent correspondre exactement aux noms des colonnes. Dans ce cas, puisque nous travaillons avec une colonne appelée "Creator", l'argument de la méthode doit également être nommé "Creator". Nous renvoyons simplement la valeur de cette colonne pour atteindre notre objectif ici. Cette méthode peut être aussi complexe que vos besoins l'exigent, à condition qu'elle fournisse finalement un nom d'utilisateur ou un nom de rôle. Elle peut également fournir une liste de noms séparés par des virgules si nécessaire.

Lorsque le paramètre ROWLEVELSECURITY est défini à 1, la propriété %READERLIST est utilisée pour stocker la liste des personnes autorisées à accéder à la ligne. Si vous souhaitez afficher cette liste dans une requête, vous pouvez exécuter une commande semblable à ce qui suit.

SELECT %READERLIST, * FROM Person

La sécurité au niveau des lignes est appliquée en plus de la sécurité au niveau des tables. Un utilisateur ne peut pas accéder à une ligne, la mettre à jour ou la supprimer sans disposer des autorisations nécessaires pour les deux éléments: la table et la ligne. Il est important de noter que la sécurité au niveau des lignes n'est appliquée que lorsqu'on utilise SQL, et non lorsqu'on utilise l'accès aux objets ou lorsqu'on effectue une manipulation directe des variables globales. Soyez extrêmement prudent si vous accédez à vos données en contournant cette couche de sécurité!

Au moyen de l’application soigneuse de ces deux outils puissants, vous pouvez considérablement renforcer la sécurité de vos données!

Discussion (0)2
Connectez-vous ou inscrivez-vous pour continuer