Как создать пользователя только для чтения в PostgreSQL?


420

Я хотел бы создать пользователя в PostgreSQL, который может делать SELECT только из конкретной базы данных. В MySQL команда будет:

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

Что такое эквивалентная команда или серия команд в PostgreSQL?

Я старался...

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

Но, похоже, что в базе данных вы можете предоставить только CREATE, CONNECT, TEMPORARY и TEMP.

Ответы:


641

Предоставить использование / выбрать одну таблицу

Если вы предоставляете только CONNECT для базы данных, пользователь может подключиться, но не имеет других привилегий. Вы должны предоставить USAGE для пространств имен (схем) и SELECT для таблиц и представлений по отдельности следующим образом:

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;

Несколько таблиц / представлений (PostgreSQL 9.0+)

В последних версиях PostgreSQL вы можете предоставлять разрешения для всех таблиц / представлений / и т. Д. В схеме, используя одну команду, вместо того, чтобы вводить их по одному:

GRANT SELECT ON ALL TABLES IN SCHEMA public TO xxx;

Это влияет только на таблицы, которые уже были созданы. Более эффективно, вы можете автоматически назначать роли по умолчанию для новых объектов в будущем:

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

Обратите внимание, что по умолчанию это повлияет только на объекты (таблицы), созданные пользователем, который выполнил эту команду: хотя она также может быть установлена ​​для любой роли, членом которой является выдавший пользователь. Однако вы не выбираете привилегии по умолчанию для всех ролей, в которых вы участвуете, при создании новых объектов ... так что все еще есть некоторые недоработки. Если вы принимаете подход, согласно которому база данных играет роль-владелец, а изменения схемы выполняются в качестве этой роли-владельца, вам следует назначить привилегии по умолчанию для этой роли-владельца. ИМХО, все это немного сбивает с толку, и вам, возможно, придется поэкспериментировать, чтобы создать функциональный рабочий процесс.

Несколько таблиц / представлений (версии PostgreSQL до 9.0)

Чтобы избежать ошибок при длительных изменениях в нескольких таблицах, рекомендуется использовать следующий «автоматический» процесс для генерации требуемого GRANT SELECTдля каждой таблицы / представления:

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');

Это должно вывести соответствующие команды GRANT в GRANT SELECT для всех открытых таблиц, представлений и последовательностей, для копирования-n-paste. Естественно, это будет применяться только к таблицам, которые уже были созданы.


22
Вы должны поместить свои изменения относительно PG9 вверху поста.
Данило Барген

5
Ницца. Я бы добавил, что вам также может понадобиться разрешить чтение последовательностей этим пользователем; Итак: GRANT ВЫБРАТЬ НА ВСЕ ПОСЛЕДОВАТЕЛЬНОСТИ В СХЕМЕ public TO xxx;
JJC

26
Обратите внимание, что для того, чтобы этот пользователь не мог создавать новые таблицы, мне пришлось REVOKE CREATE ON SCHEMA public FROM PUBLIC;. Без этого пользователь «только для чтения» не может изменять существующие таблицы, но может создавать новые таблицы в схеме и добавлять / удалять данные из этих таблиц.
Ajedi32

3
@ Ajedi32 Это должно быть частью принятого ответа! Спасибо
Асфанд Кази

12
Для новичков, как я, я думаю, стоит упомянуть, что вы должны запустить консоль, используя в psql mydbпротивном случае большинство этих манипуляций не будет. Лично мне потребовалось немало времени, чтобы понять это самостоятельно. Надеюсь, это кому-нибудь поможет.
Анасс

41

Обратите внимание, что PostgreSQL 9.0 (сегодня в бета-тестировании) будет иметь простой способ сделать это :

test=> GRANT SELECT ON ALL TABLES IN SCHEMA public TO joeuser;

3
Я должен был быть в конкретной базе данных, чтобы это работало. Postgresql 9.5.
user1158559

8
Это работает только для существующих таблиц в схеме. Если пользователь записи позже создает или заменяет таблицы, пользователь только для чтения не будет иметь к ним доступа
anneb

33

Ссылка взята из этого блога:

Скрипт для создания пользователя только для чтения:

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

Назначьте разрешение этому пользователю только для чтения:

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;

Назначьте разрешения на чтение всех вновь созданных таблиц в будущем

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

6
Это очень хороший ответ, за исключением одного: ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO Read_Only_User; он также позволит читать все таблицы, созданные в одной и той же БД в будущем.
Равбакер

2
Необычно разрешать пользователю доступ только для чтения к последовательностям. Чтение последовательности обновляет ее, и они обычно нужны только для INSERTs.
jpmc26

Для полноты, возможно, добавьте:GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA schema_name TO Read_Only_User;
Фабьен Хаддади

@ jpmc26: значит ли это, что вы рекомендуете GRANT ALL ON ALL SEQUENCES IN SCHEMA schema_name TO Read_Only_User?
Фабьен Хаддади

@FabienHaddadi Это означает, что, если у вас нет каких-то необычных требований, я не вижу необходимости предоставлять какие-либо разрешения для последовательностей пользователю только для чтения.
jpmc26

24

Вот лучший способ, который я нашел, чтобы добавить пользователей только для чтения (используя PostgreSQL 9.0 или новее):

$ 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;

Затем войдите на все связанные машины (master + read-slave (s) / hot-standby (s) и т. Д.) И запустите:

$ 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

2
Мне нравится подход, но мне также нужно было предоставить GRANT CONNECT ON DATABASE [thedatabase] TO [theuser или role]; и ПРЕДОСТАВЛЯТЬ ИСПОЛЬЗОВАНИЕ В СХЕМЕ общественности [пользователь или роль];
Ян Коннор

1
Общедоступная схема все еще позволяет такому пользователю создавать таблицы. Кроме того, новые таблицы не рассматриваются, как и последовательности. К сожалению, все это немного сложнее, чем это. : - / Я опубликую то, что я закончил делать, как только я подтвердил это еще немного.
JJC

В приведенном выше сценарии вы пытаетесь создать роль дважды. Я подозреваю, что вы намеревались использовать «ALTER ROLE ...» при включении роли для входа в систему и установки пароля
Богдан

Если у вас уже есть пользователь, после создания роли только для чтения и предоставления разрешения выберите новую привилегию для пользователя: GRANT readonly TO <USER>
gonz

18

По умолчанию новые пользователи будут иметь разрешение на создание таблиц. Если вы планируете создать пользователя только для чтения, это, вероятно, не то, что вы хотите.

Чтобы создать истинного пользователя только для чтения с PostgreSQL 9.0+, выполните следующие шаги:

# 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;

Если ваш пользователь, доступный только для чтения, не имеет прав доступа к списку таблиц (т.е. не \dвозвращает результатов), возможно, это связано с тем, что у вас нет USAGEправ доступа к схеме. USAGEэто разрешение, которое позволяет пользователям фактически использовать назначенные им разрешения. какой в ​​этом смысл? Я не уверен. Исправить:

# 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;

8

Я создал удобный сценарий для этого; pg_grant_read_to_db.sh . Этот сценарий предоставляет привилегии только для чтения указанной роли для всех таблиц, представлений и последовательностей в схеме базы данных и устанавливает их по умолчанию.


4

Я прочитал все возможные решения, и все в порядке, если вы помните, чтобы подключиться к базе данных, прежде чем предоставить вещи;) В любом случае, спасибо всем остальным решениям !!!

user@server:~$ sudo su - postgres

создать пользователя 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

запустите psql cli и установите пароль для созданного пользователя:

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

подключиться к целевой базе данных:

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".

предоставить все необходимые привилегии:

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

изменить привилегии по умолчанию для целей db public shema:

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

3

Если ваша база данных находится в публичной схеме, это легко (предполагается, что вы уже создали 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

Если ваша база данных использует customschema, выполните вышеописанное, но добавьте еще одну команду:

db=> ALTER USER readonlyuser SET search_path=customschema, public;
ALTER ROLE

1

Непростой способ сделать это - предоставить select для каждой таблицы базы данных:

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

Вы можете автоматизировать это, генерируя ваши заявления о предоставлении грантов из метаданных базы данных.



0

Взятый по ссылке, размещенной в ответ на despesz ' ссылку .

Postgres 9.x, кажется, имеет возможность делать то, что запрашивается. См. Пункт «Предоставление объектов базы данных»:

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

Где написано: «Существует также возможность предоставления привилегий всем объектам одного типа в одной или нескольких схемах. В настоящее время эта функция поддерживается только для таблиц, последовательностей и функций (но учтите, что ВСЕ ТАБЛИЦЫ включают представления». и зарубежные столы).

На этой странице также обсуждается использование ролей и привилегии, называемой "все привилегии".

Также представлена ​​информация о том, как функции GRANT сравниваются со стандартами SQL.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.