Que fait exactement l'utilisation des subventions sur le schéma?

121

J'essaye de créer pour la première fois une base de données Postgres, c'est donc probablement une question stupide. J'ai attribué des autorisations de base en lecture seule au rôle db qui doit accéder à la base de données à partir de mes scripts php, et j'ai une curiosité: si j'exécute

GRANT some_or_all_privileges ON ALL TABLES IN SCHEMA schema TO role;

est-il nécessaire d'exécuter aussi

GRANT USAGE ON SCHEMA schema TO role;

?

De la documentation :

UTILISATION: pour les schémas, autorise l'accès aux objets contenus dans le schéma spécifié (en supposant que les exigences de privilège propres aux objets sont également satisfaites). Cela permet essentiellement au bénéficiaire de «rechercher» des objets dans le schéma.

Je pense que si je peux sélectionner ou manipuler des données contenues dans le schéma, je peux accéder à tous les objets du schéma lui-même. Ai-je tort? Sinon, à quoi GRANT USAGE ON SCHEMAsert-il? Et que signifie exactement la documentation avec «en supposant que les propres conditions de privilège des objets sont également satisfaites»?

Marco Sulla
la source

Réponses:

126

GRANTs sur différents objets sont séparés. GRANTsur une base de données n'a pas de GRANTdroits sur le schéma à l'intérieur. De la même manière, l'ingénierie GRANTsur un schéma n'accorde pas de droits sur les tables à l'intérieur.

Si vous avez des droits sur SELECTune table, mais pas le droit de la voir dans le schéma qui la contient, vous ne pouvez pas accéder à la table.

Les tests de droits sont effectués dans l'ordre:

Do you have `USAGE` on the schema? 
    No:  Reject access. 
    Yes: Do you also have the appropriate rights on the table? 
        No:  Reject access. 
        Yes: Check column privileges.

Votre confusion peut provenir du fait que le publicschéma a par défaut GRANTtous les droits sur le rôle public, dont chaque utilisateur / groupe est membre. Donc, tout le monde a déjà une utilisation sur ce schéma.

La phrase:

(en supposant que les propres conditions de privilège des objets sont également satisfaites)

C'est dire que vous devez avoir USAGEsur un schéma pour utiliser des objets à l'intérieur, mais avoirUSAGE sur un schéma n'est pas en soi suffisant pour utiliser les objets dans le schéma, vous devez également avoir des droits sur les objets eux-mêmes.

C'est comme une arborescence de répertoires. Si vous créez un répertoire somedircontenant un fichier, somefiledéfinissez-le pour que seul votre propre utilisateur puisse accéder au répertoire ou au fichier (mode rwx------sur le répertoire , mode rw-------sur le fichier), personne d'autre ne peut répertorier le répertoire pour voir que le fichier existe.

Si vous accordiez des droits de lecture universelle sur le fichier (mode rw-r--r--) sans modifier les autorisations de répertoire, cela ne ferait aucune différence. Personne ne pouvait voir le fichier pour le lire, car ils n'ont pas le droit de lister le répertoire.

Si vous définissez rwx-r-xr-xà la place le répertoire, en le définissant pour que les utilisateurs puissent le répertorier et le parcourir sans modifier les autorisations du fichier, les utilisateurs pourraient répertorier le fichier mais ne pourraient pas le lire car ils n'auraient pas accès au fichier.

Vous devez définir les deux autorisations pour que les utilisateurs puissent réellement afficher le fichier.

Même chose en Pg. Vous avez besoin à la fois des USAGEdroits de schéma et des droits d'objet pour effectuer une action sur un objet, comme à SELECTpartir d'une table.

(L'analogie tombe un peu en ce sens que PostgreSQL n'a pas encore de sécurité au niveau des lignes, donc l'utilisateur peut toujours "voir" que la table existe dans le schéma SELECTen provenant pg_classdirectement. Ils ne peuvent en aucun cas interagir avec elle. , cependant, c'est juste la partie "liste" qui n'est pas tout à fait la même.)

Craig Ringer
la source
2
Maintenant c'est très clair avec l'exemple de répertoire :) Je dois dire que c'est un problème si vous insérez une table ou une ligne avec un superutilisateur, par exemple lorsque vous ajoutez postGIS en utilisant CREATE EXTENSION. C'est plus ou moins le même problème avec les fichiers créés sous Linux pendant que vous êtes su. Ce sera bien s'il y a une sorte d' sudo -einstructions for dans pqsl.
Marco Sulla
Quoi qu'il en soit maintenant j'ai réalisé que les GRANTdéclarations non spécifiques aux tables ne sont pas ce que je veux, puisqu'elles affectent toutes les bases de données ...: s
Marco Sulla
1
@LucasMalor Euh ... non, ils ne le font pas. GRANTsur un schéma affecte ce schéma. GRANT ... ON ALL TABLES IN SCHEMA ...affecte toutes les tables d'un schéma dans une base de données particulière. Il n'y a aucun GRANTs qui affecte toutes les bases de données (ok, sauf l' GRANTappartenance à un rôle à un utilisateur).
Craig Ringer
Ah excusez-moi, j'ai exécuté les déclarations lorsque j'étais connecté en tant que superutilisateur "postgres", et elles ont affecté la base de données "postgres". Je pensais que si vous exécutiez psqlsans -d dbque vous n'opériez "en dehors" d'aucune base de données, mais que vous êtes toujours connecté à une base de données et par défaut vous êtes connecté à la base de données avec le même nom de votre rôle. db = role = user = group ... c'est un peu déroutant: D
Marco Sulla
@LucasMalor Pensez-y de cette façon. Par défaut, vous vous connectez à une base de données avec le même nom que le rôle de connexion ("utilisateur") sous lequel vous vous connectez. Les «utilisateurs» ne sont que des rôles qui ont WITH LOGIN; essentiellement, tout peut être un groupe et les groupes peuvent être définis pour pouvoir se connecter.
Craig Ringer
72

Pour un système de production, vous pouvez utiliser cette configuration:

--ACCESS DB
REVOKE CONNECT ON DATABASE nova FROM PUBLIC;
GRANT  CONNECT ON DATABASE nova  TO user;

--ACCESS SCHEMA
REVOKE ALL     ON SCHEMA public FROM PUBLIC;
GRANT  USAGE   ON SCHEMA public  TO user;

--ACCESS TABLES
REVOKE ALL ON ALL TABLES IN SCHEMA public FROM PUBLIC ;
GRANT SELECT                         ON ALL TABLES IN SCHEMA public TO read_only ;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO read_write ;
GRANT ALL                            ON ALL TABLES IN SCHEMA public TO admin ;
bilelovitch
la source
Ne devrait-il pas adminégalement être accordé CREATEsur le schéma?
Dan
2
Les accès sont attribués selon un modèle hiérarchique: BD -> SCHEMA -> TABLES . Avec GRANT USAGE ON SCHEMA, l'utilisateur administrateur ne peut pas créer de table mais il peut le faire avec ALL GRANT ALL ON SCHEMA....
bilelovitch
@bilelovitch: tu veux dire grant all on schema public to admin? PS: j'ai ajouté aussi grant usage, select on all sequences in schema public to read_only/read_write; grant execute on all functions in schema public to read_only/read_write;
Marco Sulla
2

Eh bien, voici ma solution finale pour une simple base de données, pour Linux:

# Read this before!
#
# * roles in postgres are users, and can be used also as group of users
# * $ROLE_LOCAL will be the user that access the db for maintenance and
#   administration. $ROLE_REMOTE will be the user that access the db from the webapp
# * you have to change '$ROLE_LOCAL', '$ROLE_REMOTE' and '$DB'
#   strings with your desired names
# * it's preferable that $ROLE_LOCAL == $DB

#-------------------------------------------------------------------------------

//----------- SKIP THIS PART UNTIL POSTGRES JDBC ADDS SCRAM - START ----------//

cd /etc/postgresql/$VERSION/main
sudo cp pg_hba.conf pg_hba.conf_bak
sudo -e pg_hba.conf

# change all `md5` with `scram-sha-256`
# save and exit

//------------ SKIP THIS PART UNTIL POSTGRES JDBC ADDS SCRAM - END -----------//

sudo -u postgres psql

# in psql:
create role $ROLE_LOCAL login createdb;
\password $ROLE_LOCAL
create role $ROLE_REMOTE login;
\password $ROLE_REMOTE

create database $DB owner $ROLE_LOCAL encoding "utf8";
\connect $DB $ROLE_LOCAL

# Create all tables and objects, and after that:

\connect $DB postgres

revoke connect on database $DB from public;
revoke all on schema public from public;
revoke all on all tables in schema public from public;

grant connect on database $DB to $ROLE_LOCAL;
grant all on schema public to $ROLE_LOCAL;
grant all on all tables in schema public to $ROLE_LOCAL;
grant all on all sequences in schema public to $ROLE_LOCAL;
grant all on all functions in schema public to $ROLE_LOCAL;

grant connect on database $DB to $ROLE_REMOTE;
grant usage on schema public to $ROLE_REMOTE;
grant select, insert, update, delete on all tables in schema public to $ROLE_REMOTE;
grant usage, select on all sequences in schema public to $ROLE_REMOTE;
grant execute on all functions in schema public to $ROLE_REMOTE;

alter default privileges for role $ROLE_LOCAL in schema public
    grant all on tables to $ROLE_LOCAL;

alter default privileges for role $ROLE_LOCAL in schema public
    grant all on sequences to $ROLE_LOCAL;

alter default privileges for role $ROLE_LOCAL in schema public
    grant all on functions to $ROLE_LOCAL;

alter default privileges for role $ROLE_REMOTE in schema public
    grant select, insert, update, delete on tables to $ROLE_REMOTE;

alter default privileges for role $ROLE_REMOTE in schema public
    grant usage, select on sequences to $ROLE_REMOTE;

alter default privileges for role $ROLE_REMOTE in schema public
    grant execute on functions to $ROLE_REMOTE;

# CTRL+D
Marco Sulla
la source
1
Quel utilisateur doit être utilisé pour le "# Créer toutes les tables et objets, et après cela:"? Qui est le propriétaire des tables et autres objets dans votre cas?
Christophe Furmaniak
@ChristopheFurmaniak vous avez raison, j'ai corrigé le processus. Le propriétaire de la base de données et de ses objets est $ ROLE_LOCAL et, après avoir créé la structure de la base de données, nous devons retourner au superutilisateur postgres.
Marco Sulla
Je crois que vous avez un problème dans vos commandes "ALTER DEFAULT PRIVILEGES ...". Cette commande est utilisée pour déclencher l'octroi de privilèges à un utilisateur (rôle) lorsqu'un utilisateur différent (rôle) crée un objet. Voir page 11, section 7.1, de ce document pour plus de précisions. Actuellement, votre ROLE_REMOTE n'aura accès à aucun objet que ROLE_LOCAL créerait. Les commandes ROLE_LOCAL ne donnent que les privilèges que le rôle a déjà en tant que propriétaire de ces objets. Il en va de même pour les commandes ROLE_REMOTE.
emispowder