Article
· Jan 30 9m de lecture

Le package de sécurité - Gestion des rôles par programmation

Nous sommes de retour à %SYS ! Puisque nous avons abordé la gestion des utilisateurs et des ressources dans les deux derniers articles, nous pouvons enfin passer aux rôles. Comme vous l’avez peut-être deviné, il existe de nombreuses méthodes pour les gérer que vous avez déjà vues dans nos écrits précédents. Cependant, nous pouvons encore rencontrer des différences clés dans cette classe particulière

Avant de commencer, gardez à l’esprit qu’il s’agit d’une autre classe qui ne doit pas être manipulée via un accès SQL direct. Dans les versions plus récentes d'IRIS, vous trouverez un déclencheur NoSQL qui vous empêchera de toute façon de le faire. Toutefois, si vous possédez une ancienne version de Caché, pensez à être prudent

Les rôles ont des champs de nom et de description qui doivent suivre les mêmes règles que les propriétés correspondantes dans la classe de ressources. Le nom comporte au maximum soixante-quatre caractères. Il n'est pas sensible à la casse, ne peut pas contenir de deux-points ni de virgules et ne peut pas commencer par un signe de pourcentage, sauf s'il s'agit d'un rôle défini par le système. La description peut contenir jusqu'à deux cent cinquante-six caractères et inclure des virgules et des deux-points. Elle est là pour que vous donniez une description de ce qu'est le rôle.

En plus des propriétés mentionnées ci-dessus, les rôles possèdent également une propriété GrantedRoles. Il s'agit d'une liste de noms de rôles accordés par ce rôle. Supposons que nous ayons un rôle appelé NS1_Read qui accorde des autorisations de sélection à toutes les tables de l'espace de noms NS1 et un autre rôle appelé NS2_Read qui accorde des autorisations de sélection à toutes les tables de l'espace de noms NS2. Nous pourrions également créer un rôle All_Read qui accorderait des autorisations de sélection à toutes les tables des deux espaces de noms en lui attribuant les rôles accordés NS1_Read et NS2_Read. Si cette dernière peut nous aider à accomplir la même chose, elle nécessite également beaucoup de travail supplémentaire. De plus, l’utilisation de la propriété GrantedRoles simplifie la synchronisation des modifications apportées aux rôles. Cela signifie que toute modification apportée aux rôles accordés sera immédiatement reflétée dans le rôle All_Read sans nécessité de modifications supplémentaires

Les rôles sont également liés aux ressources. Il crée une liste d'objets Security.Resource sur lesquels nous pouvons parcourir (ne la confondez pas avec la classe Security.Resources dont nous avons entendu parler dans le dernier article). Examinons une longue et puissante ligne de code pour en savoir plus :

for x=1:1:myrole.Resources.Count() {write myrole.Resources.GetAt(x).Name," ",myrole.Resources.GetAt(x).PermissionLogicalToDisplay(myrole.Resources.GetAt(x).Permission),!}

Supposons que la variable myrole soit n’importe quel objet Security.Roles valide. Dans ce cas, cette boucle écrira le nom de chaque ressource accordée par le rôle ainsi que l'autorisation qu'elle accorde à ce rôle. Elle utilise la méthode LogicalToDisplay de la propriété Permission car la propriété Permission est un entier, mais elle est plus facile à lire si nous la convertissons en sa valeur d'affichage. Si nous avions un rôle qui accordait l'autorisation d'utilisation sur la ressource %Admin_Task, elle écrirait « %Admin_Task U ».

Nous commencerons à explorer les méthodes en examinant la méthode Get. Cela nous permettra immédiatement de découvrir certaines incohérences entre Security.Roles et les classes que nous avons examinées dans nos articles précédents. Dans les autres classes, la méthode Get prenait deux arguments : une chaîne contenant le nom de l'objet et une valeur passée par référence qui renvoyait le tableau des propriétés. Pourtant, dans cette classe, nous pouvons voir le troisième argument qui est passé par référence et renvoie l'objet rôle. Par conséquent, nous pouvons faire ce qui suit :

set sc = ##class(Security.Roles).Get("NS1_Read",.props,.myrole)

Cela définira la variable props contenant le tableau de propriétés et la variable myrole contenant l'objet rôle. Vous remarquerez que le tableau des propriétés ne contient que trois propriétés pour un rôle. Il s'agit de Description, GrantedRoles et Ressources. Dans ce tableau, props("Resources") est renvoyé sous la forme d'une chaîne contenant une liste de paires ressource:autorisation séparées par des virgules, l'autorisation étant affichée comme valeur d'affichage. GrantedRoles est également une liste de rôles séparés par des virgules.

Il existe également un rôle GetProperties qui prend deux arguments et ressemble beaucoup à notre méthode Get typique. Malheureusement, les arguments ne sont pas les mêmes. Contrairement à de nombreuses autres méthodes de ces classes, le premier argument est le handle d'objet du rôle plutôt qu'une chaîne contenant son nom. La seconde est une valeur passée par référence qui contiendra le tableau de propriétés.

Les valeurs du tableau de propriétés sont au format accepté par la méthode Create. Cependant, il ne peut pas accepter la totalité du tableau. Au lieu de cela, il accepte quatre chaînes : un nom, une description, des ressources et des rôles accordés, respectivement.

Supposons que j'ai les propriétés suivantes de mon rôle NS1_Read :

props("Description")="Read Role for NS1"
props("GrantedRoles")=""
props("Resources")="%DB_NS1:R"

Si je voulais l'utiliser pour créer le rôle NS2_Read qui donnerait l'autorisation d'écriture à la base de données, je pourrais procéder comme suit

set newprops("Description")= $REPLACE(props("Description"),"NS1","NS2")
set newprops("GrantedRoles") = props("GrantedRoles")
set newprops("Resources")=$REPLACE(props("Resources"),"NS1","NS2")

set sc = ##class(Security.Roles).Create("NS2_Read", newprops("Description"), newprops("Resources"), newprops("GrantedRoles"))

Cela créerait un nouveau rôle appelé NS2_Read avec la description « Read Role for NS2 » et une autorisation de lecture sur la ressource %DB_NS2. Pour créer le rôle All_Read, je pourrais utiliser

set sc = ##class(Security.Roles).Create(“All_Read",“Combined Read role for NS1 and NS2","","NS1_Read,NS2_Read")

Ce rôle ne dispose d'aucune autorisation de ressource. Néanmoins, puisqu'il accorde à l'utilisateur NS1_Read et NS2_Read, il confère toujours toutes les autorisations de ressources des deux rôles.

À partir de maintenant, toutes les méthodes suivantes devraient vous paraître terriblement familières :

  • set sc = ##class(Security.Roles).Modify("NS2_Read",.props) 
    modifierait le rôle NS2_Read en fonction du tableau de propriétés qui lui est transmis.
  • set sc = ##class(Security.Roles).Delete("NS2_Read") 
    supprimerait le rôle NS2_Read et renverrait un statut.
  • set exists = ##class(Security.Roles).Exists("NS2_Read",.myrole,.sc)
    vérifierait si le rôle NS2_Read existe, renverrait l'objet de rôle en tant que myrole si c'est le cas, définirait un code d'état dans sc et renverrait un booléen qui peut vous indiquer si le rôle existe ou non. N'oubliez pas que si la fonction renvoie un 0, vous devez vérifier sc pour clarifier si elle n'existe pas réellement ou s'il y a eu une erreur déterminant son existence !

Il existe également une méthode Rename que les autres classes n'avaient pas. Elle vous permet de renommer un objet rôle et de mettre à jour ce nom de rôle dans toutes les tables pertinentes en transmettant d'abord le nouveau nom, puis l'ancien. Cela signifie que si j'ai accidentellement nommé mon rôle NS2_Reed, je pourrais résoudre ce problème en utilisant la ligne suivante

set sc = ##class(Security.Roles).Rename("NS2_Read","NS2_Reed")

Les méthodes habituelles d’importation et d’exportation sont également présentes ici. Dans la méthode Export de cette classe, vous devez transmettre le nom du fichier sous forme de chaîne et le numexported par référence, comme d'habitude. Après cela, vous pouvez saisir une liste de rôles séparés par des virgules pour exporter uniquement ceux spécifiés ou un astérisque pour les exporter tous. Ensuite, vous devez saisir une liste de noms de ressources séparés par des virgules pour exporter uniquement les rôles qui contiennent ces ressources ou un astérisque pour toutes les ressources. Ensuite, vous devez passer un booléen précisant s'il faut ou non exporter les privilèges SQL. Enfin, vous pouvez saisir un autre numéro par référence privsexported pour renvoyer le nombre de privilèges SQL exportés. N'oubliez pas que les rôles de base de données commençant par %DB_ ne seront jamais exportés. Cependant, si vous souhaitez exporter tous les rôles accordant la ressource %DB_NS1 ainsi que tous les privilèges SQL associés, utilisez ce qui suit :

set sc = ##class(Security.Roles).Export("MyRoles.xml", .numexported, "*", "%DB_NS1", 1, .privsexported)

Une fois que vous avez ce fichier, si vous souhaitez importer ces rôles dans un autre système, appelez la commande suivante :

set sc = ##class(Security.Roles).Import("MyRoles.xml", .numimported, 1, .privsimported)

Cela importera tous ces rôles et leurs privilèges SQL associés. Il définira également numimported sur le nombre de rôles importés et privsimported sur le nombre d'enregistrements de privilèges SQL importés.

En parlant de privilèges SQL, nous n'avons pas encore examiné l'ajout d'autorisations de table SQL à un rôle. C’est pourtant une étape cruciale ! Je parie que dans la plupart des cas, vous l'avez fait en utilisant le portail de gestion système :

Je dois vous prévenir que cette pièce est très différente des autres classes. Nous devons utiliser la commande SQL Grant ici. Pour le faire dans votre code, vous pouvez utiliser du SQL intégré ou dynamique pour exécuter la requête. Selon la manière dont vous utilisez cette commande, vous pouvez la rendre assez spécifique ou très large. Considérez l'instruction SQL suivante, mais n'essayez pas de l'utiliser :

GRANT * ON * TO

Cela accorde les sept privilèges de base (%ALTER, DELETE, INSERT, SELECT, UPDATE, INSERT et EXECUTE) à toutes les tables de tous les utilisateurs existants. En fait, si nous remplaçons le dernier astérisque par _PUBLIC, ces autorisations seront également accordées à tous les futurs utilisateurs. Nous devrons définir l’accès d’une manière beaucoup plus étroite. Par exemple:

GRANT SELECT ON SCHEMA SQLUser TO NS1_Read

Cela accordera au rôle NS1_Read l'autorisation de sélectionner dans chaque table du schéma SQLUser, quel que soit l'espace de noms dans lequel la commande a été exécutée. Si nous avions une table SQLUser.People et que nous voulions uniquement y accorder l'accès, nous utiliserions la ligne suivante :

GRANT SELECT ON SQLUser.People TO NS1_Read

Si vous souhaitez spécifier des autorisations au niveau des colonnes, vous devez inclure une liste de noms de colonnes séparés par des virgules après chaque autorisation. Si cette table contient des champs appelés FirstName et LastName et que nous souhaitons que le rôle puisse les mettre à jour tout en lui permettant de sélectionner la table entière, utilisez la ligne ci-dessous :

GRANT SELECT,UPDATE(FirstName,LastName) ON SQLUser.People TO NS1_Read

Pour chacune de ces commandes, si nous ajoutons WITH GRANT OPTION à la fin, cela permettra à l'utilisateur d'accorder les mêmes autorisations à d'autres. Cela revient à cocher la case « Option Accorder » dans le portail de gestion du système. Si vous avez plusieurs tables ou rôles en tête, vous pouvez créer une liste séparée par des virgules pour accorder ces privilèges en même temps.

La commande grant peut également accorder des privilèges administratifs aux rôles. Vous connaissez peut-être cette liste dans l'onglet Privilèges SQL de la page Modifier les rôles dans le portail de gestion système.


 

Celles-ci sont accordées à peu près de la même manière mais sans la partie "ON" de la commande. Par exemple :

GRANT %CREATE_TABLE TO NS1_Read

Vous pouvez ajouter WITH ADMIN OPTION à cette commande d'octroi pour permettre à l'utilisateur de donner cette autorisation aux autres. C'est l'équivalent de l'utilisation de l'option « Attribuer avec l'option accorder » dans le portail de gestion du système

Maintenant que nous avons configuré les utilisateurs, les ressources et les rôles, surveillez notre prochain article : les applications !

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