Comment créer un utilisateur en lecture seule dans PostgreSQL?

420

J'aimerais créer un utilisateur dans PostgreSQL qui ne peut faire que des SELECT à partir d'une base de données particulière. Dans MySQL, la commande serait:

GRANT SELECT ON mydb.* TO 'xxx'@'%' IDENTIFIED BY 'yyy';

Quelle est la commande ou la série de commandes équivalente dans PostgreSQL?

J'ai essayé...

postgres=# CREATE ROLE xxx LOGIN PASSWORD 'yyy';
postgres=# GRANT SELECT ON DATABASE mydb TO xxx;

Mais il semble que les seules choses que vous pouvez accorder sur une base de données sont CREATE, CONNECT, TEMPORARY et TEMP.

Ethan
la source

Réponses:

641

Accorder l'utilisation / sélectionner à une seule table

Si vous accordez uniquement CONNECT à une base de données, l'utilisateur peut se connecter mais ne dispose d'aucun autre privilège. Vous devez accorder USAGE sur les espaces de noms (schémas) et SELECT sur les tables et les vues individuellement comme suit:

GRANT CONNECT ON DATABASE mydb TO xxx;
-- This assumes you're actually connected to mydb..
GRANT USAGE ON SCHEMA public TO xxx;
GRANT SELECT ON mytable TO xxx;

Tables / vues multiples (PostgreSQL 9.0+)

Dans les dernières versions de PostgreSQL, vous pouvez accorder des autorisations sur toutes les tables / vues / etc du schéma à l'aide d'une seule commande plutôt que d'avoir à les taper une par une:

GRANT SELECT ON ALL TABLES IN SCHEMA public TO xxx;

Cela n'affecte que les tables qui ont déjà été créées. Plus puissamment, vous pouvez automatiquement attribuer des rôles par défaut à de nouveaux objets à l'avenir:

ALTER DEFAULT PRIVILEGES IN SCHEMA public
   GRANT SELECT ON TABLES TO xxx;

Notez que par défaut, cela n'affectera que les objets (tables) créés par l'utilisateur qui a émis cette commande: bien qu'elle puisse également être définie sur n'importe quel rôle dont l'utilisateur émetteur est membre. Cependant, vous ne récupérez pas les privilèges par défaut pour tous les rôles dont vous êtes membre lors de la création de nouveaux objets ... il y a donc toujours quelques faffings. Si vous adoptez l'approche selon laquelle une base de données a un rôle propriétaire et que les modifications de schéma sont effectuées en tant que rôle propriétaire, vous devez attribuer des privilèges par défaut à ce rôle propriétaire. À mon humble avis, tout cela est un peu déroutant et vous devrez peut-être expérimenter pour trouver un flux de travail fonctionnel.

Tables / vues multiples (versions PostgreSQL antérieures à 9.0)

Pour éviter les erreurs dans les modifications longues et multi-tables, il est recommandé d'utiliser le processus «automatique» suivant pour générer le nécessaire GRANT SELECTpour chaque table / vue:

SELECT 'GRANT SELECT ON ' || relname || ' TO xxx;'
FROM pg_class JOIN pg_namespace ON pg_namespace.oid = pg_class.relnamespace
WHERE nspname = 'public' AND relkind IN ('r', 'v', 'S');

Cela devrait générer les commandes GRANT pertinentes sur GRANT SELECT sur toutes les tables, vues et séquences en public, pour un copier-coller. Naturellement, cela ne sera appliqué qu'aux tables déjà créées.

araqnid
la source
22
Vous devriez mettre votre montage concernant PG9 en haut de l'article.
Danilo Bargen
5
Agréable. Une chose que j'ajouterais est que vous devrez peut-être également autoriser la lecture des séquences par cet utilisateur; donc: GRANT SELECT SUR TOUTES LES SÉQUENCES DANS SCHEMA public TO xxx;
JJC
26
Notez que pour empêcher cet utilisateur de pouvoir créer de nouvelles tables, je devais le faire REVOKE CREATE ON SCHEMA public FROM PUBLIC;. Sans cela, l'utilisateur "en lecture seule" ne pourrait pas modifier les tables existantes, mais pourrait créer de nouvelles tables dans le schéma et ajouter / supprimer des données de ces tables.
Ajedi32
3
@ Ajedi32 Cela devrait faire partie de la réponse acceptée! Merci
Asfand Qazi
12
Pour les débutants comme moi, je pense qu'il vaut la peine de mentionner que vous devriez démarrer la console en utilisant psql mydbsinon la plupart de ces manipulations ne feraient pas. Personnellement, il m'a fallu beaucoup de temps pour le découvrir par moi-même. J'espère que cela aide quelqu'un.
Anass
41

Notez que PostgreSQL 9.0 (aujourd'hui en test bêta) aura un moyen simple de le faire :

test=> GRANT SELECT ON ALL TABLES IN SCHEMA public TO joeuser;
bortzmeyer
la source
3
Je devais être dans la base de données spécifique pour que cela fonctionne. Postgresql 9.5.
user1158559
8
Cela ne fonctionne que pour les tables existantes dans le schéma. Si l'utilisateur en écriture crée ou remplace des tables ultérieurement, l'utilisateur en lecture seule n'y aura pas accès
anneb
33

Référence tirée de ce blog:

Script pour créer un utilisateur en lecture seule:

CREATE ROLE Read_Only_User WITH LOGIN PASSWORD 'Test1234' 
NOSUPERUSER INHERIT NOCREATEDB NOCREATEROLE NOREPLICATION VALID UNTIL 'infinity';

Attribuez l'autorisation à cet utilisateur en lecture seule:

GRANT CONNECT ON DATABASE YourDatabaseName TO Read_Only_User;
GRANT USAGE ON SCHEMA public TO Read_Only_User;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO Read_Only_User;
GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO Read_Only_User;

Attribuer des autorisations pour lire toutes les nouvelles tables créées à l'avenir

ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO Read_Only_User;
Anvesh
la source
6
C'est une très bonne réponse, sauf une chose qui manque: ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO Read_Only_User; qui permettrait également de lire toutes les tables créées dans la même base de données à l'avenir.
Ravbaker
2
Il est inhabituel d'autoriser un utilisateur en lecture seule à accéder aux séquences. La lecture de la séquence la met à jour, et elles ne sont généralement nécessaires que pour l' INSERTart.
jpmc26
Pour être complet, ajoutez éventuellement:GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA schema_name TO Read_Only_User;
Fabien Haddadi
@ jpmc26: est - ce que cela signifie que vous recommandez: GRANT ALL ON ALL SEQUENCES IN SCHEMA schema_name TO Read_Only_User?
Fabien Haddadi
@FabienHaddadi Cela signifie qu'à moins que vous n'ayez des exigences inhabituelles, je ne vois pas la nécessité d'accorder des autorisations sur les séquences à un utilisateur en lecture seule.
jpmc26
24

Voici le meilleur moyen que j'ai trouvé pour ajouter des utilisateurs en lecture seule (en utilisant PostgreSQL 9.0 ou plus récent):

$ sudo -upostgres psql postgres
postgres=# CREATE ROLE readonly WITH LOGIN ENCRYPTED PASSWORD '<USE_A_NICE_STRONG_PASSWORD_PLEASE';
postgres=# GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;

Connectez-vous ensuite à toutes les machines associées (maître + esclave (s) de lecture / redondance d'UC, etc.) et exécutez:

$ echo "hostssl <PUT_DBNAME_HERE> <PUT_READONLY_USERNAME_HERE> 0.0.0.0/0 md5" | sudo tee -a /etc/postgresql/9.2/main/pg_hba.conf
$ sudo service postgresql reload
Jay Taylor
la source
2
J'aime l'approche, mais j'avais également besoin de GRANT CONNECTER SUR LA BASE DE DONNÉES [la base de données] À [l'utilisateur ou le rôle]; et DONNER L'UTILISATION SUR SCHEMA public À [l'utilisateur ou le rôle];
Ian Connor,
1
Le schéma public permet toujours à un tel utilisateur de créer des tables. De plus, les nouvelles tables ne sont pas couvertes, ni les séquences. Malheureusement, tout cela est un peu plus compliqué que cela. : - / Je posterai ce que j'ai fini de faire après l'avoir validé un peu plus.
JJC
Dans votre script ci-dessus, vous essayez de créer le rôle deux fois. Je soupçonne que vous aviez l'intention d'utiliser "ALTER ROLE ..." lors de l'activation du rôle de connexion et de la définition du mot de passe
Bogdan
Si vous avez déjà l'utilisateur, après avoir créé le rôle en lecture seule et accordé des autorisations de sélection, accordez le nouveau rôle à l'utilisateur: GRANT en lecture seule à <USER>
gonz
18

Par défaut, les nouveaux utilisateurs seront autorisés à créer des tables. Si vous prévoyez de créer un utilisateur en lecture seule, ce n'est probablement pas ce que vous voulez.

Pour créer un véritable utilisateur en lecture seule avec PostgreSQL 9.0+, exécutez les étapes suivantes:

# This will prevent default users from creating tables
REVOKE CREATE ON SCHEMA public FROM public;

# If you want to grant a write user permission to create tables
# note that superusers will always be able to create tables anyway
GRANT CREATE ON SCHEMA public to writeuser;

# Now create the read-only user
CREATE ROLE readonlyuser WITH LOGIN ENCRYPTED PASSWORD 'strongpassword';
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonlyuser;

Si votre utilisateur en lecture seule n'a pas l'autorisation de lister les tables (c'est-à-dire qu'il \dne renvoie aucun résultat), c'est probablement parce que vous n'avez pas d' USAGEautorisations pour le schéma. USAGEest une autorisation qui permet aux utilisateurs d'utiliser réellement les autorisations qui leur ont été attribuées. À quoi ça sert? Je ne suis pas sûr. Pour corriger:

# You can either grant USAGE to everyone
GRANT USAGE ON SCHEMA public TO public;

# Or grant it just to your read only user
GRANT USAGE ON SCHEMA public TO readonlyuser;
Adrian Macneil
la source
8

J'ai créé un script pratique pour cela; pg_grant_read_to_db.sh . Ce script accorde des privilèges en lecture seule à un rôle spécifié sur toutes les tables, vues et séquences d'un schéma de base de données et les définit par défaut.

Jakub Jirutka
la source
4

J'ai lu toutes les solutions possibles, qui sont très bien, si vous vous souvenez de vous connecter à la base de données avant d'accorder les choses;) Merci quand même à toutes les autres solutions !!!

user@server:~$ sudo su - postgres

créer un utilisateur psql:

postgres@server:~$ createuser --interactive 
Enter name of role to add: readonly
Shall the new role be a superuser? (y/n) n
Shall the new role be allowed to create databases? (y/n) n
Shall the new role be allowed to create more new roles? (y/n) n

démarrez psql cli et définissez un mot de passe pour l'utilisateur créé:

postgres@server:~$ psql
psql (10.6 (Ubuntu 10.6-0ubuntu0.18.04.1), server 9.5.14)
Type "help" for help.

postgres=# alter user readonly with password 'readonly';
ALTER ROLE

se connecter à la base de données cible:

postgres=# \c target_database 
psql (10.6 (Ubuntu 10.6-0ubuntu0.18.04.1), server 9.5.14)
You are now connected to database "target_database" as user "postgres".

accordez tous les privilèges nécessaires:

target_database=# GRANT CONNECT ON DATABASE target_database TO readonly;
GRANT

target_database=# GRANT USAGE ON SCHEMA public TO readonly ;
GRANT

target_database=# GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly ;
GRANT

modifier les privilèges par défaut pour les cibles db shema public:

target_database=# ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO readonly;
ALTER DEFAULT PRIVILEGES
thomi_ch
la source
3

Si votre base de données est dans le schéma public, c'est facile (cela suppose que vous avez déjà créé le readonlyuser)

db=> GRANT SELECT ON ALL TABLES IN SCHEMA public to readonlyuser;
GRANT
db=> GRANT CONNECT ON DATABASE mydatabase to readonlyuser;
GRANT
db=> GRANT SELECT ON ALL SEQUENCES IN SCHEMA public to readonlyuser;
GRANT

Si votre base de données utilise customschema, exécutez ce qui précède mais ajoutez une autre commande:

db=> ALTER USER readonlyuser SET search_path=customschema, public;
ALTER ROLE
josephmisiti
la source
1

La manière pas simple de le faire serait d'accorder select sur chaque table de la base de données:

postgres=# grant select on db_name.table_name to read_only_user;

Vous pouvez automatiser cela en générant vos relevés de droits à partir des métadonnées de la base de données.

Pablo Santa Cruz
la source
1
CREATE USER username SUPERUSER  password 'userpass';
ALTER USER username set default_transaction_read_only = on;
Viktor Viktor
la source
0

Tiré d'un lien publié en réponse au lien de despesz .

Postgres 9.x semble avoir la capacité de faire ce qui est demandé. Voir le paragraphe Grant On Database Objects de:

http://www.postgresql.org/docs/current/interactive/sql-grant.html

Où il est indiqué: "Il existe également une option pour accorder des privilèges sur tous les objets du même type dans un ou plusieurs schémas. Cette fonctionnalité n'est actuellement prise en charge que pour les tables, les séquences et les fonctions (mais notez que TOUS LES TABLEAUX sont considérés comme incluant des vues et tables étrangères). "

Cette page traite également de l'utilisation des ROLE et d'un PRIVILEGE appelé "TOUS PRIVILÈGES".

Des informations sur la façon dont les fonctionnalités GRANT se comparent aux normes SQL sont également présentes.

kbulgrien
la source