web-dev-qa-db-fra.com

Accorder des privilèges pour une base de données particulière dans PostgreSQL

Je passe de MySQL à PostgreSQL et j'ai heurté un mur avec des privilèges utilisateur. J'ai l'habitude d'attribuer à un utilisateur tous les privilèges sur toutes les tables d'une base de données avec la commande suivante:

# MySQL
grant all privileges on mydatabase.* to 'myuser'@'localhost' identified by 'mypassword';

Il me semble que la solution PostgreSQL 9.x implique l'attribution de privilèges à un "schéma", mais l'effort requis de moi pour comprendre exactement ce que SQL à émettre s'avère excessif. Je sais que quelques heures de recherche supplémentaires donneront une réponse, mais je pense que tout le monde passant de MySQL à PostgreSQL pourrait bénéficier d'avoir au moins une page sur le Web qui fournit une recette simple et complète. C'est la seule commande que j'ai jamais eu besoin d'émettre pour les utilisateurs. Je préfère ne pas avoir à émettre de commande pour chaque nouvelle table.

Je ne sais pas quels scénarios doivent être traités différemment dans PostgreSQL, donc je vais énumérer certains des scénarios que j'ai généralement dû gérer par le passé. Supposons que nous voulons seulement modifier les privilèges sur une seule base de données qui a déjà été créée.

(1a) Toutes les tables n'ont pas encore été créées, ou (1b) les tables ont déjà été créées.

(2a) L'utilisateur n'a pas encore été créé, ou (2b) l'utilisateur a déjà été créé.

(3a) Les privilèges n'ont pas encore été attribués à l'utilisateur, ou (3b) les privilèges ont été précédemment attribués à l'utilisateur.

(4a) L'utilisateur doit uniquement insérer, mettre à jour, sélectionner et supprimer des lignes, ou (4b) l'utilisateur doit également pouvoir créer et supprimer des tableaux.

J'ai vu des réponses qui accordent tous les privilèges à toutes les bases de données, mais ce n'est pas ce que je veux ici. S'il vous plaît, je cherche une recette simple, même si cela ne me dérangerait pas non plus d'explication.

Je ne veux pas accorder de droits à tous les utilisateurs et à toutes les bases de données, comme cela semble être le raccourci conventionnel, car cette approche compromet toutes les bases de données lorsqu'un utilisateur est compromis. J'héberge plusieurs clients de base de données et attribue à chaque client une connexion différente.

Il semble que j'ai également besoin du privilège USAGE pour obtenir les valeurs croissantes d'une colonne serial, mais je dois l'accorder sur une sorte de séquence. Mon problème est devenu plus complexe.

23
Joe Lapp

Concept de base dans Postgres

Les rôles sont des objets globaux qui peuvent accéder à toutes les bases de données d'un cluster db - compte tenu des privilèges requis.

Un cluster contient de nombreuses bases de données , qui en contiennent plusieurs schémas . Les schémas (même avec le même nom) dans différentes bases de données ne sont pas liés. L'octroi de privilèges pour un schéma s'applique uniquement à ce schéma particulier dans la base de données actuelle (la base de données actuelle au moment de l'octroi).

Chaque base de données commence par un schéma public par défaut. C'est une convention, et de nombreux paramètres commencent par elle. À part cela, le schéma public n'est qu'un schéma comme les autres.

En venant de MySQL, vous voudrez peut-être commencer avec un seul schéma public, ignorant efficacement la couche de schéma. J'utilise régulièrement des dizaines de schémas par base de données.
Les schémas sont un peu (mais pas complètement) comme les répertoires du système de fichiers.

Une fois que vous utilisez plusieurs schémas, assurez-vous de comprendre search_path réglage:

Privilèges par défaut

Par documentation sur GRANT:

PostgreSQL accorde des privilèges par défaut sur certains types d'objets à PUBLIC. Aucun privilège n'est accordé à PUBLIC par défaut sur les tables, colonnes, schémas ou espaces de table. Pour les autres types, les privilèges par défaut accordés à PUBLIC sont les suivants: CONNECT et CREATE TEMP TABLE pour les bases de données; EXECUTE privilège pour les fonctions; et USAGE privilège pour les langues.

Tous ces paramètres par défaut peuvent être modifiés avec ALTER DEFAULT PRIVILEGES :

Rôle de groupe

Comme @Craig a commenté , il est préférable de GRANT privilèges sur un rôle de groupe, puis de faire un utilisateur spécifique de ce rôle (GRANT le rôle de groupe sur le rôle d'utilisateur ). de cette façon, il est plus simple de traiter et de révoquer les ensembles de privilèges nécessaires pour certaines tâches.

Un rôle de groupe est juste un autre rôle sans connexion. Ajoutez un identifiant pour le transformer en rôle d'utilisateur. Plus:

Recette

Disons, nous avons une nouvelle base de données mydb, un groupe mygrp et un utilisateur myusr ...

En étant connecté à la base de données en question en tant que superutilisateur (postgres par exemple):

REVOKE ALL ON DATABASE mydb FROM public;  -- shut out the general public
GRANT CONNECT ON DATABASE mydb TO mygrp;  -- since we revoked from public

GRANT USAGE ON SCHEMA public TO mygrp;

Assigner a user all privileges to all tables comme vous l'avez écrit (je pourrais être plus restrictif):

GRANT ALL ON ALL TABLES IN SCHEMA public TO mygrp;
GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO mygrp; -- don't forget those

Pour définir les privilèges par défaut pour les objets futurs, exécutez pour chaque rôle qui crée des objets dans ce schéma:

ALTER DEFAULT PRIVILEGES FOR ROLE myusr IN SCHEMA public
GRANT ALL ON TABLES TO mygrp;

ALTER DEFAULT PRIVILEGES FOR ROLE myusr IN SCHEMA public
GRANT ALL ON SEQUENCES TO mygrp;

-- more roles?

Maintenant, accordez le groupe à l'utilisateur:

GRANT mygrp TO myusr;

Réponse connexe:

Réglage alternatif (non standard)

Venant de MySQL, et puisque vous souhaitez conserver les privilèges sur les bases de données séparées, vous aimerez peut-être ce paramètre non standard db_user_namespace. Par documentation:

Ce paramètre active les noms d'utilisateurs par base de données. C'est désactivé par défaut.

Lisez attentivement le manuel. Je n'utilise pas ce paramètre. Cela n'annule pas ce qui précède.

58
Erwin Brandstetter

Peut-être pourriez-vous me donner un exemple qui accorde à un utilisateur spécifique la sélection/insertion/mise à jour/suppression sur toutes les tables - celles existantes et non encore créées - d'une base de données spécifique?

Ce que vous appelez une base de données dans MySQL ressemble plus à un schéma PostgreSQL qu'à une base de données PostgreSQL.

Connectez-vous à la base de données "test" en tant que superutilisateur. Ici c'est

$ psql -U postgres test

Modifier les privilèges par défaut pour l'utilisateur "testeur" existant.

ALTER DEFAULT PRIVILEGES IN SCHEMA public
    GRANT INSERT, SELECT, UPDATE, DELETE ON TABLES
    TO tester;

La modification des privilèges par défaut n'a aucun effet sur les tables existantes. C'est par conception. Pour les tables existantes, utilisez la syntaxe standard GRANT et REVOKE.

Vous ne pouvez pas attribuer de privilèges à un utilisateur qui n'existe pas.

Je ne veux pas accorder de droits à tous les utilisateurs et à toutes les bases de données, comme cela semble être le raccourci conventionnel, car cette approche compromet toutes les bases de données lorsqu'un utilisateur est compromis. J'héberge plusieurs clients de base de données et attribue à chaque client une connexion différente.

OK. Lorsque vous affectez des tables au rôle correct, les privilèges accordés seront spécifiques au rôle et non à tous les utilisateurs! Ensuite, vous pourrez décider à qui donner roles.

  1. Créez un role pour chaque base de données. Un rôle peut contenir de nombreux utilisateurs.
  2. Attribuez ensuite un client-username au rôle correct.
  3. Attribuez également your-username à chaque rôle si nécessaire.


(1a) Toutes les tables n'ont pas encore été créées, ou (1b) les tables ont déjà été créées.

OK. Vous pouvez créer des tableaux plus tard.
Lorsque vous êtes prêt, affectez des tables au bon client role.

CREATE TABLE tablename();
CREATE ROLE rolename;
ALTER TABLE tablename OWNER TO rolename;


(2a) L'utilisateur n'a pas encore été créé, ou (2b) l'utilisateur a déjà été créé.

OK. Créez des noms d'utilisateur lorsque vous êtes prêt. Si votre client a besoin de plus d'un nom d'utilisateur, créez simplement un second client-username.

CREATE USER username1;
CREATE USER username2;


(3a) Les privilèges n'ont pas encore été attribués à l'utilisateur, ou (3b) les privilèges ont été précédemment attribués à l'utilisateur.

OK. Lorsque vous êtes prêt à accorder des privilèges, créez l'utilisateur et attribuez-lui le rôle approprié.
Utilisez la commande GRANT-TO pour attribuer des rôles aux utilisateurs.

GRANT rolename TO username1;
GRANT rolename TO username2;


(4a) L'utilisateur doit uniquement insérer, mettre à jour, sélectionner et supprimer des lignes, ou (4b) l'utilisateur doit également pouvoir créer et supprimer des tableaux.

OK. Vous exécutez ces commandes pour ajouter des autorisations à vos utilisateurs.

GRANT SELECT, UPDATE, INSERT, DELETE ON dbname TO role-or-user-name;
ALTER USER username1 CREATEDB;
1
Red

Vous pouvez oublier le schéma si vous utilisez uniquement PUBLIC. Ensuite, vous faites quelque chose comme ça: ( voir doc ici )

GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
    [, ...] | ALL [ PRIVILEGES ] }
    ON { [ TABLE ] table_name [, ...]
         | ALL TABLES IN SCHEMA schema_name [, ...] }
    TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ]
0
Str.