ОШИБКА: отказано в разрешении для отношения tablename в Postgres при попытке SELECT в качестве пользователя только для чтения

89
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;

Пользователь только для чтения может подключиться, просмотреть таблицы, но когда он попытается сделать простой выбор, он получит:

ERROR: permission denied for relation mytable
SQL state: 42501

Это происходит в PostgreSQL 9.1.

Что я сделал не так?

Сорин
источник
1
Не могли бы вы рассказать подробнее о «моей таблице отношений»? Схема, это "настоящая" таблица (или представление / функция), триггеры ...
Игорь Романченко

Ответы:

162

Вот полное решение для PostgreSQL 9+, недавно обновленное.

CREATE USER readonly  WITH ENCRYPTED PASSWORD 'readonly';
GRANT USAGE ON SCHEMA public to readonly;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO readonly;

-- repeat code below for each database:

GRANT CONNECT ON DATABASE foo to readonly;
\c foo
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO readonly; --- this grants privileges on new tables generated in new database "foo"
GRANT USAGE ON SCHEMA public to readonly; 
GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO readonly;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;

Спасибо https://jamie.curle.io/creating-a-read-only-user-in-postgres/ за несколько важных аспектов.

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

Сорин
источник
6
включает ли это просмотры?
Фрэнк Конри
9
Почему вы GRANT ALLпо умолчанию даете разрешение пользователю только для чтения?
Слава Фомин II
1
Я дал именно то, что определено, но все же ошибка sam
Аниш Гопинатх
может подтвердить права, предоставленные с помощью \ddp. Должен отображаться так же, =r/как granting_user=r/readonly_userдля доступа только для чтения.
Грег Брей
Это дословный SQL из вопроса. Я не понимаю, как это дает решение.
r351574nc3
12

Попробуй добавить

GRANT USAGE ON SCHEMA public to readonly;

Вы, вероятно, не знали, что для использования объектов в схеме необходимо иметь необходимые разрешения для схемы.

суфлер
источник
Происходит что-то странное, я запускаю эти команды на сервере, используя psqlкак postgresпользователь, и получаю правильный ответ GRANT. Тем не менее, когда я смотрю на ACL в таблицах, я вижу только две другие учетные записи, одна из которых является владельцем базы данных, jirauserа другая - учетной записью с именем только для чтения qauser. Но моего readonlyтам нет. Postgres - это версия 9.1, и я даже перезапустил сервер, но ничего не произошло.
sorin
2
что / был вывод \ du в консоли psql? Можете ли вы дать этот результат или он уже исправлен, как в вашем ответе?
sufleR
Я действительно не знаю, что произошло, так как вывод был правильным (GRANT). Вчера это не сработало, а сегодня заработало после запуска, опять же, всех 3 команд.
sorin
3
Примечание: ожидаемый ответ на это просто «ГРАНТ». Если вы видите «ПРЕДУПРЕЖДЕНИЕ: для« общедоступных »привилегий не было предоставлено, то это НЕ РАБОТАЕТ. Пользователь только для чтения не может предоставить себе дополнительные разрешения. Это может сделать только пользователь с правами GRANT, поэтому вам, вероятно, потребуется войти в систему как суперпользователь.
PeterVermont
Привет, когда я пытаюсь ПРЕДОСТАВИТЬ ВЫБОР ДЛЯ ВСЕХ ТАБЛИЦ В СХЕМЕ общедоступной для postgres; он отвечает: ОШИБКА: отказано в разрешении для отношения databasechangeloglock. Вы знаете, что я делаю не так? Спасибо (это происходит на GAppEngine Posgres9.6 с использованием публичного адреса и доступа через терминал)
Майк,
-5

Это сработало для меня:

Проверьте текущую роль, в которую вы вошли, используя: SELECT CURRENT_USER, SESSION_USER;

Примечание : он должен совпадать с владельцем схемы.

Схема | Имя | Тип | Владелец
-------- + -------- + ------- + ----------

Если владелец другой, то предоставьте все права текущей роли пользователя из роли администратора:

GRANT 'ROLE_OWNER' в 'CURRENT ROLENAME';

Затем попробуйте выполнить запрос, он выдаст результат, поскольку теперь у него есть доступ ко всем отношениям.

Дхвани Шах
источник
5
Смена владельца на пользователя с именем readonly вряд ли кажется правильным решением.
Анна
В зависимости от вашего случая причиной действительно может быть неправильный владелец таблицы (это был мой противник). Правильный способ таблицы изменений ownershiip в PostgreSQL: см stackoverflow.com/a/13535184
tanius
-6

убедитесь, что у вашего пользователя есть атрибуты для его роли. например:

postgres=# \du
                             List of roles
 Role name |                   Attributes                   | Member of 
-----------+------------------------------------------------+-----------
 flux      |                                                | {}
 postgres  | Superuser, Create role, Create DB, Replication | {}

после выполнения следующей команды:

postgres=# ALTER ROLE flux WITH Superuser;
ALTER ROLE
postgres=# \du
                             List of roles
 Role name |                   Attributes                   | Member of 
-----------+------------------------------------------------+-----------
 flux      | Superuser                                      | {}
postgres  | Superuser, Create role, Create DB, Replication | {}

это устранило проблему.

см. руководство по ролям и так далее: https://www.digitalocean.com/community/tutorials/how-to-use-roles-and-manage-grant-permissions-in-postgresql-on-a-vps--2

ПуН1ш3р
источник
18
Нет! Предоставление роли суперпользователя пользователю с именем «только чтение» для выполнения «выбора» не является правильным решением.
Анна
@Anna Это не то, что здесь происходит. Этот поток не о предоставлении доступа только для чтения. Этот поток предназначен для предоставления пользователю доступа, чтобы предоставить другому пользователю доступ только для чтения. ИМХО, это правильно. Если ваш пользователь не является суперпользователем, вы не можете создать пользователя только для чтения. Ошибка возникает из-за возможности создать пользователя только для чтенияERROR: permission denied for relation mytable
r351574nc3
-7

Вам следует выполнить следующий запрос:

GRANT ALL ON TABLE mytable TO myuser;

Или, если ваша ошибка находится в представлении, возможно, таблица не имеет разрешения, поэтому вам следует выполнить следующий запрос:

GRANT ALL ON TABLE tbm_grupo TO myuser;
да у
источник
5
Пользователь называется "только для чтения". Сомнительно, что целью является предоставление пользователю всех разрешений. Он просто хочет сделать выбор.
Анна
Это ALTER DROP DELETEлишает пользователя имени ReadOnly, если вы используете Ect.
Этому