web-dev-qa-db-fra.com

Comment gérer les PRIVILEGES PAR DEFAUT pour les UTILISATEURS sur une BASE DE DONNEES vs SCHEMA?

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

L'application se compose actuellement d'une commande pour mettre à jour les données; et un pour l'interroger. Naturellement, je devrai également maintenir la base de données par d'autres moyens (créer de nouvelles tables, vues, déclencheurs, etc.).

Bien que cette application soit la seule hébergée sur le serveur dans un premier temps, je préférerais cuire dans l'hypothèse qu'elle pourrait être hébergée sur un serveur avec d'autres bases de données à l'avenir, plutôt que d'avoir à brouiller plus tard si cela devient nécessaire dans l'avenir.

Je pense que ce serait un ensemble d'exigences assez courant, mais j'ai du mal à trouver un didacticiel 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 se prolongent sur les groupes, les utilisateurs, les rôles, les bases de données, les schémas et le domaine; mais je les trouve déroutants.

Voici ce que j'ai essayé jusqu'à présent (depuis psql en tant 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 n'obtiens pas la sémantique voulue. Je veux le configurer, donc seul le hostdb_admin peut créer (et supprimer et modifier) ​​des tables; le hostdb_mgr peut lire, insérer, mettre à jour et supprimer sur toutes les tables par défaut; et le hostdb_usr ne peut lire que toutes les tables (et vues).

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

Je suppose qu'il manque quelque chose entre CREATE DATABASE et CREATE SCHEMA, quelque chose pour appliquer le SCHEMA au DATABASE?

(À mesure que les choses avancent, j'aurai également des questions pour appliquer des restrictions similaires sur TRIGGERS, les procédures stockées, VIEWS et peut-être d'autres objets).

Où puis-je trouver un guide, un tutoriel ou une série de vidéos décents à ce sujet?

56
Jim Dennis

Où puis-je trouver un guide, un tutoriel ou une série de vidéos décents à ce sujet?

Vous trouverez tout dans le manuel. Liens ci-dessous.
Certes, la question n'est pas anodine et parfois déroutante. Voici une recette pour le cas d'utilisation:

Recette

Je veux le configurer, donc seul le hostdb_admin peut créer (et supprimer et modifier) ​​des tables;
le hostdb_mgr peut lire, insérer, mettre à jour et supprimer sur toutes les tables par défaut;
et le hostdb_usr ne peut lire que toutes les tables (et 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 qui peut également gérer les bases de données et les rôles, ajoutez les attributs de rôle CREATEDB et CREATEROLE ci-dessus.

Accordez chaque rôle au niveau supérieur suivant, afin que tous les niveaux "héritent" au moins de l'ensemble de 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 (pas hostdb ce qui serait déroutant). Choisissez n'importe quel nom. En option make schma_admin le 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 alter voir les notes ci-dessous.

Au fur et à mesure que les choses avancent, j'aurai également des questions pour appliquer des restrictions similaires sur TRIGGERS, les procédures stockées, VIEWS et peut-être d'autres objets.

Les vues sont spéciales. Pour l'un:

... (mais notez que ALL TABLES est considéré comme incluant les vues et les tables étrangères).

Et pour vues actualisables :

Notez que l'utilisateur effectuant l'insertion, la mise à jour ou la suppression sur la vue doit avoir le privilège d'insertion, de mise à jour ou de suppression correspondant sur 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 Section 38.5 ).

Les déclencheurs sont également spéciaux. Vous avez besoin du privilège TRIGGER sur la table et:

Mais nous élargissons déjà la portée de cette question ...

Notes IMPORTANTES

La possession

Si vous souhaitez autoriser schma_admin (seul) pour supprimer et modifier des tables, créez le rôle propre tous les objets. La documentation:

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

ALTER TABLE some_tbl OWNER TO schma_admin;

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

Objets préexistants

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

La même chose s'applique si vous créez des objets avec un rôle qui n'a pas DEFAULT PRIVILEGES set, comme le superutilisateur postgres. Réattribuer la propriété à schma_admin et définissez les privilèges manuellement - ou définissez DEFAULT PRIVILEGES pour postgres également (lorsqu'il est connecté à la bonne base de données!):

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

Privilèges par défaut

Il vous manquait un aspect important du ALTER DEFAULT PRIVILEGES commande. 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. Vous ne jouez donc pas avec d'autres bases de données du cluster DB. La documentation:

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

Vous mai souhaitez également définir des privilèges par défaut pour FUNCTIONS et TYPES (pas seulement TABLES et SEQUENCES), mais ceux-ci pourraient ne pas être nécessaires.

Privilèges par défaut pour PUBLIC

Les privilèges par défaut accordés à PUBLIC sont 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é à 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.

Accentuation sur moi. généralement, la seule commande ci-dessus suffit pour tout couvrir:

REVOKE ALL ON DATABASE hostdb FROM public;

En particulier, aucun privilège par défaut n'est accordé à PUBLIC pour les nouveaux schémas. Il peut être déroutant que le schéma par défaut nommé "public" commence avec les privilèges ALL pour PUBLIC. C'est juste une fonctionnalité pratique pour faciliter le démarrage avec les bases de données nouvellement créées. Cela n'affecte en rien les autres schémas. Vous pouvez révoquez ces privilèges dans la base de données de modèles template1, alors toutes les bases de données nouvellement créées dans ce cluster commencent sans elles:

\connect template1
REVOKE ALL ON SCHEMA public FROM public;

Le privilège TEMP

Puisque nous avons révoqué tous les privilèges sur hostdb de PUBLIC, les utilisateurs réguliers ne peuvent pas créer de tables temporaires à moins que nous ne l'autorisions explicitement. Vous pouvez ou non vouloir ajouter ceci:

GRANT TEMP ON DATABASE hostdb TO schma_mgr;

search_path

N'oubliez pas de régler le search_path. Si vous n'avez qu'une seule base de données dans le 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 pouvez le définir sur schma, public si 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 pour search_path sauf si vous avez changé cela. N'oubliez pas de révoquer les privilèges pour PUBLIC dans ce cas.

En relation

97
Erwin Brandstetter