• Aucun résultat trouvé

Bases de données Oracle Virtual Private Database (VPD) pour la gestion des utilisateurs d applications

N/A
N/A
Protected

Academic year: 2022

Partager "Bases de données Oracle Virtual Private Database (VPD) pour la gestion des utilisateurs d applications"

Copied!
10
0
0

Texte intégral

(1)

Bases de données Oracle

Virtual Private Database (VPD) pour la gestion des utilisateurs d’applications

P.-A. Sunier, HEG-Arc Neuchâtel avec le concours de J. Greub pierre-andre.sunier@he-arc.ch

http://lgl.isnetne.ch/ Rubrique : Publications | Informatique | Base de données Oracle 6 novembre 2009

1 Problématique ... 1

2 Solution Oracle ... 1

3 Cadre du cas pratique ... 2

4 Problème du cas pratique ... 2

5 Mise en place du contexte ... 3

5.1 Pool de sessions ... 4

5.2 Gestion des droits ... 5

6 Mise en place des prédicats de restriction ... 5

6.1 Signature des fonctions de prédicats ... 5

6.2 Création des fonctions de prédicat ... 6

6.3 Déclaration des prédicats ... 8

7 Mise en place des fonctions d’authentification et d’autorisation ... 9

7.1 Authentification ... 9

7.2 Autorisation ... 10

1 Problématique

En certaines circonstances, il peut être nécessaire de restreindre l’accès aux tuples d’une ou plusieurs tables en fonction de critères tels que le rôle d’un utilisateur, ses privilèges ou encore la nature des données ; de manière classique, il s’agit de mettre ces restrictions sous forme de clauses WHERE sur chaque utilisation de tables ou de créer des vues spécifiques.

2 Solution Oracle

Oracle fournit une solution de restriction dynamique de l’accès aux tuples à l’aide de deux mécanismes à utiliser conjointement :

des prédicats, sous forme de fonctions PL/SQL rendant des clauses WHERE, à ajouter aux tables ; si un prédicat existe, toute manipulation de la table se fera impérativement en respectant la clause WHERE du prédicat.

des informations de contexte, sous forme de couples nom : valeur ; ces informations de contexte, définies à l’ouverture d’une session ou en cours de session, peuvent être interrogées par chaque fonction PL/SQL de prédicat pour que la restriction soit dynamique.

Pour la restriction d’accès aux tuples, Oracle a parlé de Fine Grained Access Control, puis de Row Level Security (RLS) et maintenant de Virtual Private Database (VPD).

La librairie qui gère ces restrictions d’accès est DBMS_RLS.

Le concept de contexte est géré par la libraire DBMS_SESSION et plus particulièrement la procédure SET_CONTEXT.

(2)

3 Cadre du cas pratique

Une des manières de gérer les utilisateurs d’une application est de mettre en place une structure de données pour piloter le traitement de l’identification et des autorisations. Une structure proche du modèle de données ci- dessous est utilisée couramment dans le cadre des environnements de développement d’applications Oracle.

L’entité SEC_GROUPE correspond aux différents rôles, ou responsabilités, au sein de l’organisation {COMPTABILITE, VENTE, SAV…}

L’entité SEC_AUTORISATION correspond aux éléments de l’application dont il s’agit de restreindre l’accès {Ajout d’un client, Encaissement d’une facture, Modification des prix produits…}

Un groupe, ou rôle, peut avoir accès à plusieurs autorisations.

Un utilisateur peut faire partie de plusieurs groupes (avoir plusieurs rôles) et donc hériter des autorisations de chacun des groupes.

[Pour plus de détails sur la gestion temporelle des utilisateurs, veuillez vous référer à notre article : http://lgl.isnetne.ch/publications/soug/Bd/ArticleTableMutation.pdf]

4 Problème du cas pratique

Nous avons défini que les utilisateurs sont classés en 3 catégories :

Les développeurs qui peuvent gérer les groupes, les autorisations et les utilisateurs.

Les super utilisateurs qui peuvent gérer les utilisateurs sauf eux-mêmes et les développeurs.

Les utilisateurs qui peuvent se connecter mais n’ont aucun droit de gestion.

En finalité:

Les développeurs ne doivent avoir aucune restriction.

Les super utilisateurs ne doivent pas pouvoir se gérer et gérer les développeurs ; de plus, ils ne doivent pas voir les groupes ou rôles ADMIN_DVLP et ADMIN_UTIL, respectivement d’administration des développeurs et d’administration des utilisateurs.

Les utilisateurs ne doivent rien voir de la gestion de la sécurité; ils doivent seulement pouvoir être identifiés et autorisés à utiliser certains éléments de l’application autres que la sécurité.

Figure 1 – Modèle de sécurité

(3)

5 Mise en place du contexte

La restriction d’utilisation des tables SEC_UTILISATION et SEC_GROUPES dépendant du contexte d’utilisation, nous commençons par mettre en place les éléments qui permettront justement de connaitre le contexte lors de l’exécution des requêtes.

1. Assurez-vous que vous ayez les droits d’exécuter le paquetage DBMS_SESSION.

2. Déclarez un espace de nommage pour votre environnement de contexte.

grant execute dbms_session to public [ou votre schéma]

create or replace context sec USING securite;

3. Créez le paquetage qui contiendra, vos informations de contexte ; dans notre cas, le paquetage SECURITE pour l’espace de nommage sec.

PROCEDURE fixe_contexte (p_util in VARCHAR2) AS

BEGIN

-- suppression de tous les prédicats RLS

dbms_session.set_context('sec','autorisation','TOUT');

-- Mise en place progressive des prédicats depuis les plus permissifs -- jusqu'aux plus restrictifs

IF groupe( p_util, 'ADMIN_DVLP') THEN

dbms_session.set_context('sec','autorisation','ADMIN_DVLP');

ELSE

IF groupe( p_util, 'ADMIN_UTIL') THEN

dbms_session.set_context('sec','autorisation','ADMIN_UTIL');

ELSE

dbms_session.set_context('sec','autorisation','RIEN');

END IF;

END IF;

END;

FUNCTION groupe( p_util in varchar2

,p_groupe in varchar2) RETURN BOOLEAN AS vl_compte integer;

vl_contexte Varchar2(2000);

BEGIN

select count(*) into vl_compte from sec_utilisateur u ,sec_util_grpe ug ,sec_groupe g

where (UPPER(u.ident) = UPPER(p_util))

and ((u.date_fin is null) or (u.date_fin >= trunc(sysdate))) and (ug.util_numero = u.numero)

and (ug.date_debut <= trunc(sysdate))

and ((ug.date_fin is null) or (ug.date_fin >= trunc(sysdate))) and (ug.grpe_numero = g.numero)

and (g.code = p_groupe);

return vl_compte = 1;

END;

Figure 2 – Espace de nommage de contexte et son paquetage associé

Figure 3 – Procédure FIXE_CONTEXTE du paquetage SECURITE

(4)

Dans le paquetage SECURITE, nous avons créé la procédure FIXE_CONTEXTE; elle reçoit en paramètre le nom de l’utilisateur1.

Cette procédure permet de définir les éléments de contexte qui nous sont utiles.

Pour indiquer les éléments de contexte au SGBD, nous utilisons la procédure

dbms_session.set_context(espaceNommage,elemContexte, valeurContexte). set_context reçoit en paramètre l’espace de nommage, un élément de contexte et une valeur pour cet élément de contexte.

Pour notre besoin, nous n’utilisons qu’un seul élément de contexte que nous avons nommé autorisation.

Nous avons aussi créé une fonction GROUPE ; elle reçoit en paramètre le nom de l’utilisateur et le nom d’un groupe ou rôle. Elle rend vrai si l’utilisateur appartient au groupe.

Cette fonction est interne au paquetage et sert à fixer le contexte dynamiquement.

Nous avons retenu comme valeurs possibles pour l’élément autorisation : RIEN, aucune autorisation

TOUT, autorisation totale

ADMIN_DVLP, autorisation pour les développeurs

ADMIN_UTIL, autorisation de super utilisateur pour administrer les utilisateurs d’application.

Pour plus de détails sur le paquetage DBMS_SESSION, nous conseillons au lecteur de se référer à la documentation Oracle.

http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_sessio.htm

5.1 Pool de sessions

Dans le cadre d’applications multi-tiers et plus particulièrement de pages Web, souvent les cartouches spécialisées Oracle2 des serveurs d’application gèrent l’accès au schéma contenant les paquetages PL/SQL au travers d’un pool de connexion.

Il est tout à fait courant qu’une page Web3 soit fournie par une session et que le traitement de sa soumission se fasse par une autre.

Sachant que les informations de contexte sont propres à une session, il est absolument impératif que nous fixions celui-ci lors de chaque invocation de procédure PL/SQL que ce soit pour la demande d’une page ou sa

soumission. Si nous ne faisons pas cela, un utilisateur B peut « hériter » du contexte d’un utilisateur A avec tous les risques de violation des mécanismes de sécurité.

PROCEDURE fixe_contexte (p_util in VARCHAR2) AS

BEGIN

-- suppression de tous les prédicats RLS

dbms_session.set_context('sec','autorisation','TOUT');

END;

La procédure FIXE_CONTEXTE va fixer le contexte en fonction de l’appartenance de l’utilisateur à l’un ou l’autre groupe.

1 Attribut IDENT de l’entité SEC_UTILISATEUR

2 Par exemple mod_plsql

3 Fournie par du Web PL/SQL, APEX ou autre…

Figure 4 – Procédure FIXE_CONTEXTE du paquetage SECURITE

(5)

La première instruction de FIXE_CONTEXTE est de mettre la valeur TOUT à l’élément de contexte autorisation. Cet élément de contexte détermine la restriction de lecture des tables SEC_UTILISATEUR et SEC_GROUPE ; la valeur TOUT rendra le prédicat toujours vrai et tous les enregistrements seront pris en compte.

Si nous omettons cette instruction et que la valeur du contexte récupérée de la session est à RIEN pour un utilisateur lambda de l’application, nous ne pourrions plus donner des droits de gestion aux développeurs ou super utilisateurs, à la limite, la connexion pourrait être impossible car la table SEC_UTILISATEURS serait vue comme vide.

5.2 Gestion des droits

La procédure dbms_session.set_context(espaceNommage,elemContexte, valeurContexte)ne peut être employée qu’au sein du paquetage que nous avons associé à l’espace de nommage par l’instruction :

create or replace context espaceNommage USING paquetageDédié;

Si vous utilisez cette procédure en dehors du paquetage, vous recevez l’erreur ORA_01031

6 Mise en place des prédicats de restriction

Le contexte d’utilisation étant en place, nous pouvons maintenant nous intéresser aux prédicats de restriction de manipulation des tables SEC_UTILISATEUR et SEC_GROUPE.

Assurez-vous que vous ayez les droits d’exécuter le paquetage DBMS_RLS.

grant execute dbms_rls to public [ou votre schéma]

Pour plus de détails sur le paquetage DBMS_SESSION, nous conseillons au lecteur de se référer à la documentation Oracle.

http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_rls.htm

6.1 Signature des fonctions de prédicats

Les prédicats se définissent sous forme de fonctions.

Les paramètres des fonctions de prédicat (owner in VARCHAR2 ,object_name in VARCHAR2) sont imposés par le paquetage DBMS_RLS ; les fonctions doivent retourner une chaîne de caractère qui sera intégrée dans une requête.

Cette chaine de retour devra rendre vrai ou faux pour chaque tuple lors de l’exécution de la requête.

Figure 5 – Erreur ORA-01031

Figure 6 – Droits d’exécution du paquetage DBMS_RLS

(6)

FUNCTION maFonctionPredicat( owner in VARCHAR2

,object_name in VARCHAR2) RETURN Varchar2 AS

vl_predicat varchar2(1000) := '';

BEGIN

IF sys_context(espaceNommage, elemContexte) = valeurContexte THEN vl_predicat := '1<>1';

RETURN vl_predicat ; END ;

La fonction sys_context va rechercher, pour un espace de nommage, la valeur d’un élément fixé pour la session courante.

6.2 Création des fonctions de prédicat

Toujours dans le paquetage SECURITE4 nous avons créé deux fonctions qui vont servir de prédicat.

La première fonction PREDICAT_GROUPE va restreindre l’accès à la table des groupes ou rôles en fonction du contexte.

FUNCTION predicat_groupe( owner in VARCHAR2

,object_name in VARCHAR2) RETURN Varchar2 AS vl_predicat varchar2(1000) := '';

BEGIN

vl_predicat := '1=1';

IF sys_context('sec','autorisation') = 'RIEN' THEN vl_predicat := '1<>1';

ELSE

IF (sys_context('sec','autorisation') = 'TOUT') OR (sys_context('sec','autorisation') = 'ADMIN_DVLP') OR (sys_context('sec','autorisation') IS NULL ) THEN vl_predicat := '1=1';

ELSE

IF sys_context('sec','autorisation') = 'ADMIN_UTIL' THEN

vl_predicat := '(code <> ''ADMIN_DVLP'') AND (code <> ''ADMIN_UTIL'')';

END IF;

END IF;

END IF;

RETURN vl_predicat;

END;

Pour un rappel de l’incidence des valeurs de l’élément autorisation, veuillez vous référer au chapitre 5.

4 Ces fonctions peuvent être dans n’importe quel paquetage ; nous les avons mises dans le paquetage SECURITE pour simplifier le déploiement de la gestion de la sécurité.

Figure 8 – Restriction sur la table SEC_GROUPE Figure 7 – Signature des fonctions de prédicat

(7)

La deuxième fonction PREDICAT_UTILISATEUR va restreindre l’accès à la table des utilisateurs en fonction du contexte.

FUNCTION predicat_utilisateur( owner in VARCHAR2

,object_name in VARCHAR2) RETURN Varchar2 AS vl_predicat varchar2(1000) := '';

BEGIN

vl_predicat := '1=1';

IF sys_context('sec','autorisation') = 'RIEN' THEN vl_predicat := '1<>1';

ELSE

IF (sys_context('sec','autorisation') = 'TOUT') OR (sys_context('sec','autorisation') = 'ADMIN_DVLP') OR (sys_context('sec','autorisation') IS NULL ) THEN vl_predicat := '1=1';

ELSE

IF sys_context('sec','autorisation') = 'ADMIN_UTIL' THEN vl_predicat := 'NUMERO NOT IN

(SELECT UTIL_NUMERO FROM SEC_UTIL_GRPE WHERE GRPE_NUMERO NOT IN

(SELECT NUMERO FROM SEC_GROUPE))';

END IF;

END IF;

END IF;

RETURN vl_predicat;

END;

Remarques:

Pour la valeur de contexte ADMIN_UTIL, nous excluons les utilisateurs qui ont un lien sur la table des groupes qui n’est plus atteignable du fait que les tuples ADMIN_DVLP et ADMIN_UTIL sont absents.

Le test (sys_context('sec','autorisation') IS NULL ) correspoond au cas où aucun contexte n’est fixé, par exemple, si l’on interroge la table depuis SQL*Plus.

Figure 9 – Restriction sur la table SEC_UTILISATEUR

(8)

6.3 Déclaration des prédicats

Les fonctions de prédicats étant créées, il nous faut maintenant les déclarer en tant que prédicats pour que le SGBD les intègre lors des prochaines requêtes.

Pour ce faire, vous disposez de la procédure dbms_rls.add_policy que vous exécutez pour chacune de vos fonctions de prédicat.

dbms_rls.drop_policy(object_schema => 'suniera_03', object_name => 'SEC_GROUPE', policy_name => 'mapolitique');

dbms_rls.add_policy(

object_schema => 'suniera_03', object_name => 'SEC_GROUPE', policy_name => 'mapolitique', function_schema => 'suniera_03',

policy_function => 'securite.predicat_groupe', statement_types => 'select',

update_check => TRUE, enable => TRUE,

static_policy => FALSE);

Remarques:

La procédure dbms_rls.drop_policy nous permet de supprimer un prédicat existant et de le recréer ensuite en modifiant ses paramètres.

Les valeurs possibles de statement_types sont : INDEX, SELECT, INSERT, UPDATE et DELETE.

Figure 10 – Déclaration du prédicat sur la table SEC_GROUPE

(9)

7 Mise en place des fonctions d’authentification et d’autorisation

Il nous reste à mettre en place maintenant, les fonctions d’authentification et d’autorisation d’utilisation des éléments applicatifs.

Nous les mettrons en place au sein du paquetage SECURITE.

7.1 Authentification

Pour l’authentification, nous avons développé la fonction AUTHENTIFIE ci-dessous. Elle reçoit en paramètre, le nom de l’utilisateur et le mot de passe ; elle rend vrai ou faux selon que l’utilisateur existe dans la table SEC_UTILISATEUR ou pas.

La seule chose importante à noter est la suppression de tous les prédicats éventuellement existants au cas où la session n’est pas nouvelle mais reprise d’un pool de sessions [Voir chapitre 5.1].

Function authentifie( p_username in varchar2

,p_password in varchar2) RETURN BOOLEAN AS vl_compte integer;

BEGIN

-- suppression de tous les prédicats RLS

-- les prédicats seront mis en place (après validation de l'utilisateur -- c'est-à-dire directement après cette fonction d'ahthentification dbms_session.set_context('sec','autorisation','TOUT');

select count(*) into vl_compte from sec_utilisateur

where (UPPER(ident) = UPPER(p_username)) and (mot_passe = p_password)

and ((date_fin is null) or (date_fin >= trunc(sysdate)));

return vl_compte = 1;

END;

Remarques:

Cette fonction sera affinée pour permettre de faire l’impasse sur le mot de passe si, par exemple, une connexion LDAP est reprise.

Le traitement de la date de fin est liée à notre choix de gestion temporelle des utilisateurs [Voir chapitre 3].

Figure 11 – Procédure d’authentification

(10)

7.2 Autorisation

Pour l’autorisation, nous avons développé la fonction AUTORISE ci-dessous. Elle reçoit en paramètre, le nom de l’utilisateur et le code d’une autorisation ; elle rend vrai ou faux selon que l’utilisateur dispose de cette autorisation ou pas.

La seule chose importante à noter est le traitement du contexte.

En effet l’utilisateur connecté n’a peut-être pas le droit de manipuler tout ou partie des tuples des tables restreintes. Toutefois, il est impératif pour la procédure de voir ces tuples pour déterminer les autorisations de l’utilisateur connecté ; par exemple, lorsque le super utilisateur est connecté, il ne sera plus dans la liste des utilisateurs! Dès lors, aucune autorisation ne pourrait lui être octroyée.

Pour résoudre ce dilemme, nous procédons en 4 étapes :

1. Enregistrement de la valeur de restriction existante au sein de la session lors de l’appel.

2. Suppression de toutes les restrictions.

3. Traitement de la demande d’autorisation.

4. Remise de la valeur de restriction initiale.

Function autorise( p_util in varchar2

,p_autorisation in varchar2) RETURN BOOLEAN AS vl_compte integer;

vl_contexte Varchar2(2000);

BEGIN

-- mémorisation du contexte mis en place lors de la connexion vl_contexte := sys_context('sec','autorisation');

-- suppression de tous les prédicats RLS

dbms_session.set_context('sec','autorisation','TOUT');

select count(*) into vl_compte from sec_utilisateur u ,sec_util_grpe ug ,sec_auto_grpe ag ,sec_autorisation a

where (UPPER(u.ident) = UPPER(p_util))

and ((u.date_fin is null) or (u.date_fin >= trunc(sysdate))) and (ug.util_numero = u.numero)

and (ug.date_debut <= trunc(sysdate))

and ((ug.date_fin is null) or (ug.date_fin >= trunc(sysdate))) and (ug.grpe_numero = ag.grpe_numero)

and (a.numero = ag.auto_numero) and (a.code = p_autorisation);

-- remise du contexte initial

dbms_session.set_context('sec','autorisation',vl_contexte);

return vl_compte >= 1;

END;

Remarque:

Le traitement relativement conséquent des dates est lié à notre choix de gestion temporelle des utilisateurs et de leurs appartenances aux groupes [Voir chapitre 3].

Figure 12 – Procédure d’autorisation

Références

Documents relatifs

Ensuite le Seigneur leur a dit : “L’homme est maintenant devenu comme l’un de nous, pour la connaissance du bien et du mal, il ne faut pas lui permettre de tendre la main pour

Donnez des droits de consultation de toutes les tables de la BD biblio aux bibliothécaires ainsi que des droits de consultation, d’insertion sur les tables des emprunts,

It’s also a good idea to check if any low cardinality indexes are being used, because this type of an index will make the database read a large number of data blocks into the

It describes how Oracle Enterprise Manager, the Automatic Workload Repos- itory, and the Automatic Database Diagnostic Monitor are used for performance monitoring and management,

Notre projet a permis de développer une application web qui permet de réaliser plusieurs tâches : la gestion des clients et produits est l’une des principales

Quel est le code des clients qui ont commandé le menu numéro 1 2.. Quel est le nom des clients qui ont commandé le menu numéro 1

SQL (sigle de Structured Query Language, en français langage de requête structurée) est un langage informatique normalisé servant à exploiter des bases de données

 Soit le code 38 du sujet de la question ne figure pas dans la table SUJET, Dans ce cas, il faut l’insérer avec le libellé ‘Sport’ dans la table SUJET. Liste des