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?
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:
Je veux le configurer, donc seul le
hostdb_admin
peut créer (et supprimer et modifier) des tables;
lehostdb_mgr
peut lire, insérer, mettre à jour et supprimer sur toutes les tables par défaut;
et lehostdb_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.
... (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 ...
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:
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.
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.
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
etCREATE TEMP TABLE
pour les bases de données;EXECUTE
privilège pour les fonctions; etUSAGE
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;
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.