Comment gérer DEFAUT PRIVILEGES pour les utilisateurs sur une base de données vs SCHEMA?

48

Je souhaite migrer une application assez simple, interne, pilotée par une base de données, de SQLite3 vers PostgreSQL 9.3 et renforcer les autorisations dans la base de données au fur et à mesure.

L'application consiste actuellement en une commande permettant de mettre à jour les données; et un pour l'interroger. Naturellement, je devrai également gérer la base de données de différentes manières (créer de nouvelles tables, vues, déclencheurs, etc.).

Bien que cette application soit la seule hébergée sur le serveur au début, je préférerais partir du principe qu’elle pourrait être hébergée sur un serveur avec d’autres bases de données, plutôt que de devoir se débrouiller plus tard si cela devenait nécessaire. l'avenir.

Je pense que cela correspond à un ensemble d’exigences assez commun, mais j’ai du mal à trouver un tutoriel simple expliquant comment configurer une nouvelle base de données dans PostgreSQL, avec ce type de séparation utilisateur / privilège. Les références sont détaillées sur les groupes, les utilisateurs, les rôles, les bases de données, les schémas et le domaine; mais je les trouve déroutant.

Voici ce que j'ai essayé jusqu'à présent (de l'intérieur en psqltant que "postgres"):

CREATE DATABASE hostdb;
REVOKE ALL ON DATABASE hostdb FROM public;
\connect hostdb
CREATE SCHEMA hostdb;
CREATE USER hostdb_admin WITH PASSWORD 'youwish';
CREATE USER hostdb_mgr   WITH PASSWORD 'youwish2';
CREATE USER hostdb_usr WITH PASSWORD 'youwish3';

GRANT ALL PRIVILEGES ON DATABASE hostdb TO hostdb_admin;
GRANT CONNECT ON DATABASE hostdb TO hostdb_mgr, hostdb_usr;
ALTER DEFAULT PRIVILEGES IN SCHEMA hostdb GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO hostdb_mgr;
ALTER DEFAULT PRIVILEGES IN SCHEMA hostdb GRANT SELECT ON TABLES TO hostdb_usr;

Mais je ne reçois pas la sémantique voulue. Je veux que ce soit configuré de sorte que seul le hostdb_adminpeut créer (et supprimer et modifier) ​​des tables; le hostdb_mgrpeut lire, insérer, mettre à jour et supprimer sur toutes les tables par défaut; et le hostdb_usrne peut lire que toutes les tables (et les vues).

Lorsque j'ai essayé cela, j'ai découvert que j'étais capable de créer des tables dans hostdbn'importe lequel de ces utilisateurs; mais, pour chaque utilisateur, je ne pouvais que lire ou modifier les tables créées par cet utilisateur - à moins d'utiliser un fichier explicite GRANT.

Je suppose qu'il manque quelque chose entre CREATE DATABASEet CREATE SCHEMA, quelque chose à appliquer SCHEMAà la DATABASE?

(Au fur et à mesure que les choses avancent, j'ai aussi des questions pour appliquer des restrictions similaires sur TRIGGERSles procédures stockées VIEWSet peut-être d'autres objets)

Où puis-je trouver un guide, une série de tutoriels ou de vidéos sur ce sujet?

Jim Dennis
la source
2
Je pense (au moins une partie de) votre problème réside dans le publicpseudorole. On peut penser à un rôle dont tous les autres rôles (utilisateur, groupe - ils sont tous identiques) sont membres de. Essayez de supprimer les privilèges de celui-ci, par exemple REVOKE CREATE ON SCHEMA hostdb FROM public. La révocation des droits au niveau de la base de données, comme vous l'avez fait, ne désactive que certaines autorisations au niveau de la base de données, aucun effet sur les schémas ou les tables.
dezso
@dezso: il peut y avoir une idée fausse concernant les privilèges par défaut pour les schémas. Seul le schéma par défaut publicarrive avec des privilèges pour PUBLIC. En dehors de cela, il n'y a pas de privilèges par défaut pour les nouveaux schémas. Donc, cela n’affecte pas le cas d’utilisation démontré. Voir le chapitre dans ma réponse.
Erwin Brandstetter

Réponses:

86

Où puis-je trouver un guide, une série de tutoriels ou de vidéos sur ce sujet?

Vous trouverez tout dans le manuel. Liens ci-dessous.
Certes, l’affaire n’est pas anodine et parfois source de confusion. Voici une recette pour le cas d'utilisation:

Recette

Je veux que ce soit configuré de sorte que seul le hostdb_adminpeut créer (et supprimer et modifier) ​​des tables;
le hostdb_mgrpeut lire, insérer, mettre à jour et supprimer sur toutes les tables par défaut;
et le hostdb_usrne peut lire que toutes les tables (et les vues).

En tant que superutilisateur postgres:

CREATE USER schma_admin WITH PASSWORD 'youwish';
-- CREATE USER schma_admin WITH PASSWORD 'youwish' CREATEDB CREATEROLE; -- see below
CREATE USER schma_mgr   WITH PASSWORD 'youwish2';
CREATE USER schma_usr   WITH PASSWORD 'youwish3';

Si vous souhaitez un administrateur plus puissant pouvant également gérer des bases de données et des rôles, ajoutez les attributs de rôle CREATEDBet les optionsCREATEROLE ci - dessus.

Attribuez chaque rôle au niveau immédiatement supérieur, afin que tous les niveaux "héritent" au moins de l'ensemble des privilèges du niveau inférieur suivant (en cascade):

GRANT schma_usr TO schma_mgr;
GRANT schma_mgr TO schma_admin;

CREATE DATABASE hostdb;
REVOKE ALL ON DATABASE hostdb FROM public;  -- see notes below!

GRANT CONNECT ON DATABASE hostdb TO schma_usr;  -- others inherit

\connect hostdb  -- psql syntax

Je nomme le schéma schma( hostdbce qui ne serait pas déroutant). Choisissez n'importe quel nom. En option rendre schma_adminle propriétaire du schéma:

CREATE SCHEMA schma AUTHORIZATION schma_admin;

SET search_path = schma;  -- see notes

ALTER ROLE schma_admin IN DATABASE hostdb SET search_path = schma; -- not inherited
ALTER ROLE schma_mgr   IN DATABASE hostdb SET search_path = schma;
ALTER ROLE schma_usr   IN DATABASE hostdb SET search_path = schma;

GRANT USAGE  ON SCHEMA schma TO schma_usr;
GRANT CREATE ON SCHEMA schma TO schma_admin;

ALTER DEFAULT PRIVILEGES FOR ROLE schma_admin
GRANT SELECT                           ON TABLES TO schma_usr;  -- only read

ALTER DEFAULT PRIVILEGES FOR ROLE schma_admin
GRANT INSERT, UPDATE, DELETE, TRUNCATE ON TABLES TO schma_mgr;  -- + write, TRUNCATE optional

ALTER DEFAULT PRIVILEGES FOR ROLE schma_admin
GRANT USAGE, SELECT, UPDATE ON SEQUENCES TO schma_mgr;  -- SELECT, UPDATE are optional 

Pour and drop and altervoir les notes ci-dessous.

Au fur et à mesure que les choses avancent, j'aurai aussi des questions pour appliquer des restrictions similaires aux TRIGGERSprocédures stockées VIEWSet peut-être à d'autres objets.

Les vues sont spéciales. Pour un:

... (mais notez que cela ALL TABLESinclut les vues et les tables étrangères).

Et pour les vues pouvant être mises à jour :

Notez que l'utilisateur effectuant l'insertion, la mise à jour ou la suppression dans la vue doit disposer du privilège correspondant pour l'insertion, la mise à jour ou la suppression de la vue. De plus, le propriétaire de la vue doit disposer des privilèges appropriés sur les relations de base sous-jacentes, mais l'utilisateur effectuant la mise à jour n'a besoin d'aucune autorisation sur les relations de base sous-jacentes (voir la section 38.5 ).

Les déclencheurs sont aussi spéciaux. Vous avez besoin du TRIGGERprivilège sur la table et:

Mais nous élargissons déjà trop le champ de cette question ...

Notes IMPORTANTES

La possession

Si vous voulez autoriser schma_admin(seul) de laisser tomber et tables alter, faire le rôle posséder tous les objets. La documentation:

Le droit de supprimer un objet, ou de modifier sa définition de quelque manière que ce soit, n'est pas traité comme un privilège pouvant être attribué. il est inhérent au propriétaire et ne peut être accordé ou révoqué. (Cependant, vous pouvez obtenir un effet similaire en accordant ou en révoquant l'appartenance au rôle qui détient l'objet; voir ci-dessous.) Le propriétaire dispose implicitement de toutes les options d'octroi pour l'objet.

ALTER TABLE some_tbl OWNER TO schma_admin;

Ou créez tous les objets avec le rôleschma_adminpour commencer, vous n'avez pas besoin de définir explicitement le propriétaire. Cela simplifie également les privilèges par défaut, que vous ne devez ensuite définir que pour un seul rôle:

Objets préexistants

Les privilèges par défaut ne s'appliquent qu'aux objets nouvellement créés et uniquement au rôle particulier avec lequel ils ont été créés. Vous voudrez également adapter les autorisations pour les objets existants :

Il en va de même si vous créez des objets avec un rôle non DEFAULT PRIVILEGESdéfini, comme le superutilisateur postgres. Réaffectez la propriété schma_adminet définissez les privilèges manuellement - ou définissez DEFAULT PRIVILEGES- postgresles également (tout en étant connecté au bon DB!):

ALTER DEFAULT PRIVILEGES FOR ROLE postgres GRANT ...  -- etc.

Privilèges par défaut

Il vous manquait un aspect important de la ALTER DEFAULT PRIVILEGEScommande. Il s'applique au rôle actuel, sauf indication contraire:

Les privilèges par défaut s'appliquent uniquement à la base de données actuelle. Donc, vous ne plaisantez pas avec les autres bases de données du cluster de base de données. La documentation:

pour tous les objets créés dans la base de données actuelle

Vous pouvez également définir des privilèges par défaut pour FUNCTIONSet TYPES(pas seulement TABLESet SEQUENCES), mais ils ne sont peut-être pas nécessaires.

Privilèges par défaut pour PUBLIC

Les privilèges par défaut accordés à PUBLICsont rudimentaires et surestimés par certains. La documentation:

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

Gras accent mien. typiquement la commande ci-dessus est suffisante pour tout couvrir:

REVOKE ALL ON DATABASE hostdb FROM public;

En particulier, aucun privilège par défaut n'est accordé aux PUBLICnouveaux schémas. Il peut être déroutant que le schéma par défaut nommé "public" commence par des ALLprivilèges pour PUBLIC. Ceci est juste une fonctionnalité pratique pour faciliter le démarrage avec les bases de données nouvellement créées. Cela n'affecte en aucun cas les autres schémas. Vous pouvez révoquer ces privilèges dans la base de données de modèles template1, puis toutes les bases de données nouvellement créées dans ce cluster démarrent sans elles:

\connect template1
REVOKE ALL ON SCHEMA public FROM public;

Le privilège TEMP

Étant donné que nous avons révoqué tous les privilèges hostdbde PUBLIC, les utilisateurs normaux ne peuvent pas créer de tables temporaires à moins que nous ne le permettions explicitement. Vous pouvez ou non vouloir ajouter ceci:

GRANT TEMP ON DATABASE hostdb TO schma_mgr;

search_path

N'oubliez pas de définir le search_path. Si vous ne possédez que la base de données du cluster, vous pouvez simplement définir la valeur par défaut globale dans postgresql.conf. Sinon (plus probablement), définissez-le comme propriété de la base de données, ou simplement pour les rôles impliqués ou même la combinaison des deux. Détails:

Vous voudrez peut-être le définir sur schma, publicsi vous utilisez également le schéma public, ou même (moins probable) $user, schma, public...

Une alternative serait d'utiliser le schéma par défaut "public" qui devrait fonctionner avec les paramètres par défaut search_pathsauf si vous le modifiez. N'oubliez pas de révoquer les privilèges PUBLICdans ce cas.

Apparenté, relié, connexe

Erwin Brandstetter
la source
Je cherchais comment ajouter des privilèges d’administrateur par défaut au super-utilisateur nouvellement créé. Je n’aurais donc pas besoin de lui donner le droit adddiotional sur chaque table. Anf j'ai trouvé ça. Et thisça ressemble à des instructions pour le vaisseau spatial ...
Denis Matafonov
@DenisMatafonov: Les superutilisateurs ont automatiquement tous les privilèges. Je vous suggère de commencer une nouvelle question avec des détails de votre cas. Les commentaires ne sont pas la place. Vous pouvez toujours créer un lien vers des questions / réponses connexes pour le contexte.
Erwin Brandstetter
Oui, les super-utilisateurs ont tous les accès, mais vous ne pouvez pas généraliser leurs privilèges par défaut. Il serait très utile de définir les privilèges par défaut pour un rôle dans un schéma et de les appliquer par défaut à tous les membres du rôle lors de la création des tables dans le schéma. Par exemple, pour dire "assurez-vous que toutes les tables créées dans ce schéma par un membre de l'équipe d'ingénierie seront lisibles par tout membre de l'équipe de génération de rapports". En bref, je veux que les membres d'un rôle créateur de table héritent de ses privilèges par défaut.
combinatorist le