PostgreSQL
La base de données la plus sophistiquée au monde.

Ouverture de session

Navigation

Contactez-nous

Administration du site :
"equipe chez postgresqlfr point org"

Contact presse :
"fr chez postgresql point org"

Contact association :
"bureau chez postgresqlfr point org"

Questions PostgreSQL :
 IRC :
  serveur irc.freenode.net
  canal #postgresqlfr

Recherche

Accéder aux archives

« Octobre 2008  
Lun Mar Mer Jeu Ven Sam Dim
  2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31  

Syndication

Flux XML

Sondage

Quelle est la version de PostgreSQL la plus répandue sur vos serveurs ?
8.3
10%
8.2
42%
8.1
40%
8.0
2%
7.4
6%
7.3 ou antérieure
0%
Nombre de votes: 48

Utilisation des rĂ´les dans PostgreSQL 8.1

Technique | Utilisation des rĂ´les dans PostgreSQL 8.1

Par Guillaume Lelarge le 29/11/2005 - 18:56

Ce document est un rappel de l'utilisation des utilisateurs et groupes pour les versions antérieures à la 8.1 et une introduction aux rôles, concept remplaçant les utilisateurs/groupes à partir de PostgreSQL 8.1.

PostgreSQL 8.1 modifie la gestion des utilisateurs. Le concept des utilisateurs et des groupes est remplacĂ© par un concept plus global : celui des rĂ´les. Un rĂ´le correspond Ă  un utilisateur et/ou Ă  un groupe. Un rĂ´le a des droits et il peut ĂŞtre membre d'un ou plusieurs autres rĂ´les.

Le concept des utilisateurs et des groupes est facile à appréhender. Malheureusement, il ne donne pas beaucoup de liberté dans son utilisation. Un utilisateur fait partie d'un ou plusieurs groupes. Il hérite en cela des droits de ces groupes. À partir du moment où un utilisateur fait partie d'un groupe, il dispose des droits de ce groupe. Il lui est impossible de masquer les droits du groupe pour ne voir que les siens. Il lui est aussi impossible de masquer ses droits par ceux du groupe. Les rôles permettent tout cela.

Ă€ sa crĂ©ation, un rĂ´le peut avoir plusieurs options spĂ©ciales :

  • login, le rĂ´le est autorisĂ© Ă  se connecter sur une base
  • createdb, le rĂ´le est autorisĂ© Ă  crĂ©er une base de donnĂ©es
  • createrole, le rĂ´le est autorisĂ© Ă  crĂ©er un autre rĂ´le
  • superuser, le rĂ´le a tous les droits car il est un superutilisateur

Tout de suite, nous apercevons une différence importante avec les versions précédentes. Un rôle pouvant créer un autre rôle n'est pas forcément un superutilisateur. Pour qu'un rôle soit superutilisateur, il doit avoir été créé avec l'option superuser par un superutilisateur. Cela sous-entend un point extrêmement important pour l'administration d'un serveur de bases de données : il est maintenant possible de nommer un administrateur, chargé de la création des bases et des rôles, qui ne soit pas malgré tout le maître absolu du SGBD. Certes, il pourra créer des bases mais cela ne lui donnera pas le droit de supprimer objets et données dans cette base (en supposant qu'un autre rôle soit le propriétaire de la base). Nous verrons plus tard que les rôles permettent une meilleure prise en compte de la sécurité.

Une fois un rĂ´le crĂ©Ă©, il est possible de le rendre propriĂ©taire d'objets et de lui donner/enlever des droits sur les objets. Pour cela, vous disposez des instructions SQL habituelles : ALTER objet SET OWNER / GRANT / REVOKE. Vous pouvez intĂ©grer un rĂ´le Ă  un autre avec la commande ALTER GROUP groupe ADD USER utilisateur. Tout cela ressemble aux versions prĂ©cĂ©dentes de PostgreSQL : il existe des utilisateurs (rĂ´les ayant le doit LOGIN) et des groupes (rĂ´les comprenants d'autres rĂ´les comme membres).

Passons Ă  la pratique avec un exemple simple. Mettons-nous dans le cas d'une entreprise stockant ces factures dans une base de donnĂ©es PostgreSQL. Lors de la conception du schĂ©ma de cette base, une table contenant les factures a Ă©tĂ© crĂ©Ă©e :

postgres@metier=# CREATE TABLE facture (f_id int4, f_objet varchar(200));

Les droits relatifs aux personnes du service secrétariat sont gérés grâce à un rôle nommé secrétariat.

postgres@metier=# CREATE ROLE secretariat;

Anne fait partie du secrĂ©tariat et doit ĂŞtre ajoutĂ©e Ă  ce groupe :

postgres@metier=# CREATE ROLE anne LOGIN IN GROUP SECRETARIAT;

Ce groupe a le droit de visualiser, d'ajouter et de mettre à jour des factures. Étant pour l'instant la seule de ce service, elle aura aussi le droit de supprimer des factures erronées.

postgres@metier=# GRANT SELECT, INSERT, UPDATE, DELETE ON facture TO secretariat;

Connectons-nous en tant que anne :

bash# psql -U anne metier

Et insĂ©rons une facture :

anne@metier=> insert into facture (f_id, f_objet) values (1, 'PostgreSQL par la pratique');
INSERT 0 1
anne@metier=>select * from facture;
f_id | f_objet
------+---------
1 | PostgreSQL par la pratique
(1 ligne)

anne@metier=>insert into facture (f_id, f_objet) values (2, 'Cahiers du Programmeur PostgreSQL');
INSERT 0 1
anne@metier=>select * from facture;
f_id | f_objet
------+---------
1 | PostgreSQL par la pratique
2 | Cahiers du Programmeur PostgreSQL
(2 lignes)

anne@metier=>delete from facture where f_id=1;
DELETE 1
anne@metier=>select * from facture;
f_id | f_objet
------+---------
2 | Cahiers du Programmeur PostgreSQL
(1 ligne)

Après quelques opérations, nous nous apercevons que le rôle est bien paramétré.

Très bien. Jusque-là, ce n'est qu'une simple utilisation des rôles, identique à ce qu'il était possible de faire avec les utilisateurs et groupes de la version précédente.

Une nouvelle personne est embauchée au service du secrétariat. Cette nouvelle personne n'aura pas le droit de supprimer de factures, étant donné qu'elle vient tout juste d'arriver dans le service. Nous allons donc créer un rôle d'administrateur des factures qui ne pourra que supprimer une facture.

Commençons par créer le rôle d'administrateur des factures et donnons lui les droits de suppression sur la table facture.

postgres@metier=# CREATE ROLE admin_secretariat;
CREATE
postgres@metier=# GRANT DELETE ON facture TO admin_secretariat;
GRANT

Supprimons le droit de suppression du groupe secrĂ©tariat :

postgres@metier=# REVOKE DELETE ON facture FROM secretariat;
REVOKE

CrĂ©ons la nouvelle personne et ajoutons-lĂ  dans le groupe secretariat :

postgres@metier=# CREATE ROLE beatrice LOGIN IN ROLE secretariat;
CREATE

N'oublions pas d'ajouter Anne dans le nouveau rĂ´le d'administrateur des factures.

postgres@metier=# GRANT admin_secretariat TO anne;
GRANT

Testons nos modifications :

postgres@metier=#\c metier beatrice
Vous êtes maintenant connecté à la base de données «metier» en tant qu'utilisateur «beatrice».
beatrice@metier=>insert into facture (f_id, f_objet) values (3, 'PostgreSQL Essential References');
INSERT 0 1
beatrice@metier=>update facture set f_objet='PostgreSQL Essential Reference' where f_id=3;
UPDATE 1
beatrice@metier=>delete from facture where f_id=3;
ERREUR: droit refusé pour la relation facture
beatrice@metier=>\c metier anne
Vous êtes maintenant connecté à la base de données «metier» en tant qu'utilisateur «anne».
anne@metier=>insert into facture (f_id, f_objet) values (4, 'PostgreSQL Essential Reference');
INSERT 0 1
anne@metier=>update facture set f_objet='objet 4.5' where f_id=4;
UPDATE 1
anne@metier=>delete from facture where f_id=4;
DELETE 1

Tout va bien. Bien qu'un peu plus complexe, cela Ă©tait dĂ©jĂ  possible avec les anciennes versions. Passons maintenant Ă  la notion d'hĂ©ritages direct et indirect. Dans ces exemples, tout utilisateur qui se connectait avait directement les droits qui lui Ă©taient propres et ceux qu'il hĂ©ritait des groupes dont il Ă©tait membre. Supposons que l'administrateur de la base de donnĂ©es gère correctement sa base. Il ne se connecte pas en superutilisateur en permanence, mais uniquement quand les circonstances l'exigent. Anne absente, il doit pouvoir supprimer une facture si le cas se prĂ©sente sans pour autant avoir Ă  dĂ©gainer les super-pouvoirs du superutilisateur. Solution simple : il va devenir membre du groupe admin_secretariat. Il n'a pas besoin d'avoir le droit de crĂ©er ou modifier les factures, simplement de pouvoir les supprimer. Si nous l'ajoutons directement dans ce groupe, dès sa connexion, il aura le droit de supprimer des factures. Or, ce n'est pas un travail qu'il va faire frĂ©quemment. Il ne faut donc pas que ce droit de suppression soit automatique. Son utilisateur sera donc dĂ©clarĂ© comme ne bĂ©nĂ©ficiant pas directement des droits des groupes dont il est membre. Supposons que le rĂ´le de cet administrateur s'appelle admin_metier... voici sa dĂ©finition :

postgres@metier=# CREATE ROLE admin_metier LOGIN NOINHERIT;
CREATE
postgres@metier=# GRANT admin_secretariat TO admin_metier;
GRANT

Connectons-nous en tant qu'admin_metier et voyons quelles opĂ©rations sont autorisĂ©es sur la table facture :

postgres@metier=#\c metier admin_metier
Vous êtes maintenant connecté à la base de données «metier» en tant qu'utilisateur «admin_metier».
admin_metier@metier=>insert into facture (f_id, f_objet) values (5, 'PostgreSQL 8 et PHP 5');
ERREUR: droit refusé pour la relation facture
admin_metier@metier=>update facture set f_objet='objet 4.5' where f_id=4;
ERREUR: droit refusé pour la relation facture
admin_metier@metier=>delete from facture where f_id=4;
ERREUR: droit refusé pour la relation facture

Les trois opérations de base nous sont refusées alors que seule DELETE devait fonctionner. Voyons pourquoi.

admin_metier@metier=>\dp
Privilèges d'accès de la base de données «metier»
Schéma | Nom | Type | Privilèges d'accès
--------+------------------+----------+---------------------------------------------------------------------------------------
public | facture | table | {postgres=arwdRxt/postgres,secretariat=arw/postgres,admin_secretariat=d/postgres}
(1 ligne)

La colonne « Privilèges d'accès Â» contient un tableau dont chaque Ă©lĂ©ment prĂ©cise les droits attribuĂ©s Ă  un rĂ´le ainsi que le rĂ´le qui a attribuĂ© ces droits. Par exemple, le premier Ă©lĂ©ment indique que le rĂ´le postgres a reçu les droits « arwdRxt Â» (plus prĂ©cisĂ©ment tous les droits) de lui-mĂŞme (normal car c'est le superutilisateur de cette base). Le deuxième Ă©lĂ©ment indique que le rĂ´le secretariat a reçu les droits « arw Â» de l'utilisateur postgres. Voici un petit tableau rappelant la signification de chaque lettre (pour plus d'information, voir la page de manuel sur la commande GRANT) :

r SELECT
w UPDATE
a INSERT
R RULE
x REFERENCES
r TRIGGER
X EXECUTE
U USAGE
C CREATE
T TEMPORARY

admin_secretariat ne dispose que du droit de suppression (d). Or, nous demandons dans la requĂŞte de supprimer toutes les lignes dont f_id vaut 4. Pour cela, nous devons pouvoir lire cette table. Donnons donc le droit de lire (r) cette table au rĂ´le admin_secretariat.

admin_metier@metier=>\c metier postgres
Vous êtes maintenant connecté à la base de données «metier» en tant qu'utilisateur «postgres».
postgres@metier=#grant select on facture to admin_secretariat;
GRANT
postgres@metier=#\c metier admin_metier
Vous êtes maintenant connecté à la base de données «metier» en tant qu'utilisateur «admin_metier».
admin_metier@metier=>delete from facture where f_id=5;
ERREUR: droit refusé pour la relation facture
admin_metier@metier=>set role admin_secretariat;
SET
admin_metier@metier=>delete from facture where f_id=3;
DELETE 1

Tout fonctionne maintenant à merveille. L'administrateur de la base n'a pas automatiquement les droits associés aux rôles dont il est membre. C'est une grande amélioration dans la gestion des droits des utilisateurs et groupes de la base de données car elle permet de mieux protéger les données.

Abordons maintenant deux fonctionnalitĂ©s peu connues mais très intĂ©ressantes. Le fichier .psqlrc permet de configurer certains paramètres en exĂ©cution au lancement de psql. Ce fichier est très utile quand un utilisateur souhaite paramètrer finement sa connexion suivant son travail. Malheureusement, cela ne fonctionne que pour le programme psql. En utilisant d'autres outils, il faudra que ces derniers fournissent un moyen Ă©quivalent... ce qui ne sera pas toujours le cas. Sachez donc qu'il est aussi possible d'enregistrer les valeurs de certains paramètres directement au niveau des rĂ´les... donc des valeurs appliquĂ©es quelque soit l'outil utilisĂ© pour accĂ©der Ă  la base. Pour cela, il faut utiliser la commande : ALTER ROLE toto SET paramètre TO valeur. L'utilisation la plus frĂ©quente est l'initialisation du chemin search_path.

La deuxième fonctionnalité est une nouveauté de la 8.1. Il est possible de limiter le nombre de connexions simultanées avec un même utilisateur. Il faut voir cela surtout comme une mesure de sécurité. Si vos utilisateurs correspondent réellement à des personnes physiques, il y a de fortes chances pour qu'elles ne se connectent qu'une fois à un moment donné sur la base. Limiter son nombre d'accès simultané permet de prévenir des attaques de type DDOS.

Nous terminerons sur une question frĂ©quemment posĂ©e : comment attribuer un droit Ă  un rĂ´le sur plusieurs objets en mĂŞme temps. Cela n'est pas possible en SQL avec PostgreSQL. Le mieux revient Ă  Ă©crire un script shell qui crĂ©era le script SQL Ă  exĂ©cuter. Disons que nous voulons donner un droit particulier Ă  un utilisateur pour toutes les tables de la base mĂ©tier. Pour cela, nous utilisons psql avec l'option -c :

$psql -c "\dt" metier
Liste des relations
Schéma | Nom | Type | Propriétaire
---------+-------------+-------+---------------
public | facture | table | postgres
public | fournisseur | table | postgres
public | client | table | postgres
(3 lignes)

Nous n'avons pas besoin de l'entĂŞte et du bas de page. Il faut utiliser l'option -t pour les supprimer :

$ psql -t -c "\dt" galette
public | facture | table | postgres
public | fournisseur | table | postgres
public | client | table | postgres

Le cĂ´tĂ© joliment affichĂ© et les caractères | nous posent problème... il serait prĂ©fĂ©rable d'avoir les diffĂ©rents champs sĂ©parĂ©s uniquement par un espace chacun :

$ psql -F " " -A -t -c "\dt" galette
public facture table postgres
public fournisseur table postgres
public client table postgres

Seul le nom de la table nous intĂ©resse sur chaque ligne, donc nous allons utiliser l'outil awk pour rĂ©cupĂ©rer le deuxième champ :

$ psql -F " " -A -t -c "\dt" galette | awk '{ print $2; }'
facture
fournisseur
client

Enfin, nous utiliserons une boucle pour afficher la commande SQL grant pour chaque table :

psql -c "\dt" -A -t -F " " ma_base | awk '{ print $2; }' | while read ma_table
do
echo "GRANT liste_droits ON $ma_table TO mon_role;"
done | psql ma_base

Il est nécessaire de remplacer ma_base par le nom de la base impactée, et mon_role par le rôle devant avoir les nouveaux droits faisant partie de liste_droits.

Voilà, j'espère que cet article vous a intéressé. D'autres devraient suivre sur les nouveautés de PostgreSQL 8.1.

Options d'affichage des commentaires

Sélectionnez la méthode d'affichage des commentaires que vous préférez, puis cliquez sur "Sauvegarder les paramètres" pour activer vos changements.

Merci pour cet article fort i

greg1/ = 2 DĂ©cembre, 2005 - 00:57

Merci pour cet article fort intéressant.

En ce qui concerne le superutilisateur, j'aurais juste ajouté qu'à la différence d'un utilisateur avec les options CREATEDB et CREATEROLE, il passe outre des droits et des propriétaires des objets et peut donc agir sur l'ensemble des objets et des bases.


Excellent

Alexandre T/ = 23 FĂ©vrier, 2007 - 20:26

Merci pour cet excellent exemple.

Je cherchais depuis un moment comment donner le droit de manipuler les données de toutes les tables (avec des * ou des *.* comme dans ls autres langages).

Au moins je sais désormais que c'est impossible sans une routine.

Merci.


© PostgreSQLFr, tous droits rĂ©servĂ©s.
Site déclaré à la CNIL sous le numéro 1074678, conformément à la Loi en vigueur.