Je me demande pourquoi un utilisateur nouvellement créé est autorisé à créer une table après s'être connecté à une base de données. J'ai une base de données project2_core
:
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
---------------+--------------+-----------+-------------+-------------+-------------------------------
postgres | postgres | SQL_ASCII | C | C |
project2_core | atm_project2 | UTF8 | de_DE.UTF-8 | de_DE.UTF-8 | project2=CTc/project2
template0 | postgres | SQL_ASCII | C | C | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | SQL_ASCII | C | C | =c/postgres +
| | | | | postgres=CTc/postgres
(5 rows)
Jusqu'ici tout va bien. Maintenant je crée un utilisateur:
postgres=# CREATE ROLE dietrich ENCRYPTED PASSWORD 'md5XXX' LOGIN NOCREATEROLE NOCREATEDB NOSUPERUSER
D'accord. Lorsque j'essaie de me connecter à la base de données, l'utilisateur n'est pas autorisé à le faire:
$ psql -h localhost -p 5432 -U dietrich -W project2_core
Password for user dietrich:
psql: FATAL: permission denied for database "project2_core"
DETAIL: User does not have CONNECT privilege.
C'est ce à quoi je m'attendais. Maintenant, les choses étranges commencent. J'accorde à l'utilisateur CONNECT
:
postgres=# GRANT CONNECT ON DATABASE project2_core TO dietrich;
GRANT
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
---------------+--------------+-----------+-------------+-------------+-------------------------------
postgres | postgres | SQL_ASCII | C | C |
project2_core | atm_project2 | UTF8 | de_DE.UTF-8 | de_DE.UTF-8 | project2=CTc/project2+
| | | | | dietrich=c/project2
template0 | postgres | SQL_ASCII | C | C | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | SQL_ASCII | C | C | =c/postgres +
| | | | | postgres=CTc/postgres
(5 rows)
Et sans autre subvention, l'utilisateur est autorisé à créer une table:
$ psql -h localhost -p 5432 -U dietrich -W project2_core
Password for user dietrich:
psql (9.2.3)
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)
Type "help" for help.
project2_core=> create table adsf ();
CREATE TABLE
project2_core=> \d
List of relations
Schema | Name | Type | Owner
--------+------+-------+----------
public | adsf | table | dietrich
(1 row)
Je me serais attendu à ce que l'utilisateur ne soit pas autorisé à faire quoi que ce soit avant que je ne GRANT USAGE
le fasse explicitement sur le schéma, puis GRANT SELECT
sur les tables.
Où est mon erreur? Qu'est-ce que je fais mal? Comment puis-je obtenir ce que je veux (qu'un nouvel utilisateur ne soit pas autorisé à faire quoi que ce soit avant de lui accorder explicitement les droits appropriés.
Je suis perdu et votre aide est grandement appréciée :)
EDITER Suite aux conseils de @ daniel-verite, je reprends tout immédiatement après la création de la base de données. L'utilisateur dietrich n'est plus autorisé à créer une table. Bien. MAIS : Maintenant, le propriétaire de la base de données, project2 , n'est pas autorisé à créer une table. Même après l’émission GRANT ALL PRIVILEGES ON DATABASE project2_core TO project2
et GRANT ALL PRIVILEGES ON SCHEMA public TO project2
, j’obtiens une erreur ERROR: aucun schéma n’a été sélectionné pour créer , et lorsque j’essaie précisément de le faire CREATE TABLE public.WHATEVER ();
, j’obtiens ERROR: permission refusée pour le schéma public . Qu'est-ce que je fais mal?
la source
REVOKE ALL ON DATABASE project2_core FROM PUBLIC;
. pourquoi cela n'a-t-il eu aucun effet?CREATE TABLE
. voir mon édition ci-dessus.La chose cruciale à comprendre ici est que les privilèges ne sont pas hérités et ne sont pas hérités des objets contenant .
ALL
signifie tous les privilèges pour cet objet, pas tous les privilèges pour cet objet et tous les objets qu'il contient .Lorsque vous accordez
ALL
une base de données, vous accordezCREATE, CONNECT, TEMP
. Ce sont des actions sur l'objet de base de données lui-même:CONNECT
: Se connecter à la base de donnéesCREATE
: Créer un schéma ( pas une table)TEMP
: Créer des objets temporaires, y compris, mais sans s'y limiter, des tables temporairesDésormais, chaque base de données PostgreSQL a un
public
schéma créé par défaut lors de la création de la base de données. Ce schéma a tous les droits accordés au rôlepublic
, dont tout le monde est implicitement membre. Pour un schéma,ALL
signifieCREATE, USAGE
:CREATE
: Créer des objets (y compris des tables) dans ce schémaUSAGE
: Liste les objets du schéma et y accède si leurs autorisations le permettentSi vous ne spécifiez pas le schéma pour créer un objet comme une table, le moteur de base de données utilise le
search_path
, et par défaut, lepublic
schéma est le premier sursearch_path
la table, de sorte que la table y est créée. Tout le monde a les droitspublic
par défaut, la création est donc autorisée. Les droits des utilisateurs sur la base de données ne sont pas pertinents à ce stade, car l'utilisateur n'essaie pas de faire quoi que ce soit à l'objet de base de données lui-même, mais seulement un schéma en son sein.Peu importe que vous n'ayez accordé à l'utilisateur aucun autre droit que celui accordé
CONNECT
à la base de données, car lepublic
schéma permet à tous les utilisateurs de créer des tables par défaut. Daniel a déjà expliqué comment révoquer ce droit s'il le souhaitait.Si vous souhaitez déléguer chaque droit explicitement, révoquer tout du public ou simplement supprimer le schéma public. Vous pouvez créer une nouvelle base de données de modèles avec cette modification appliquée si vous le souhaitez. Alternativement, vous pouvez l'appliquer à
template1
, mais cela cassera probablement beaucoup de code tiers qui suppose qu'ilpublic
existe et est inscriptible.Cela peut sembler plus logique si vous regardez une analogie avec un système de fichiers.
Si j'ai la structure de répertoire (mode simplifié pour afficher uniquement le mode qui s'applique à l'utilisateur actuel):
alors je ne peux rien créer à l'intérieur
/dir1
, car je n'ai pas de permission en écriture. Donc, si jetouch /dir1/somefile
vais obtenir une erreur d’autorisation refusée.Cependant, je n'ont la permission de regarder à l' intérieur et à l' accès contenu des fichiers et répertoires, y compris . J'ai l'autorisation d'écriture sur . Alors va réussir , même si je n'ai pas l'autorisation d'écrire pour .
/dir1
/dir1/dir2
dir2
touch /dir1/dir2/somefile
dir1
Même chose avec les bases de données et les schémas.
la source
Si vous souhaitez uniquement empêcher les nouveaux utilisateurs de créer des tables, vous devez exécuter la commande suivante:
Si vous
REVOKE ALL
(comme le suggèrent d’autres réponses), vous empêcherez également les utilisateurs d’avoir desUSAGE
autorisations.USAGE
Cela signifie que les utilisateurs peuvent utiliser les autorisations qui leur sont attribuées. Par conséquent, si vous les supprimez, vos utilisateurs ne pourront ni répertorier ni accéder aux tables auxquelles ils ont accès.Alternativement, vous pouvez aussi
REVOKE CREATE
pour un utilisateur spécifique:Voir aussi: Comment créer un utilisateur en lecture seule avec PostgreSQL .
la source