Чому новому користувачеві дозволено створювати таблицю?


41

Мені цікаво, чому новоствореному користувачеві дозволяється створювати таблицю після підключення до бази даних. У мене є одна база даних 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)

Все йде нормально. Тепер я створюю користувача:

postgres=# CREATE ROLE dietrich ENCRYPTED PASSWORD 'md5XXX' LOGIN NOCREATEROLE NOCREATEDB NOSUPERUSER

Гаразд. Коли я намагаюся підключитися до бази даних, користувачеві це заборонено:

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

Це я очікував. Зараз починаються дивні речі. Я надаю користувачеві 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)

І без будь-яких додаткових грантів користувачеві дозволяється створювати таблицю:

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

Я б очікував, що користувачеві не дозволяється робити нічого, перш ніж явно робити це GRANT USAGEна схемі, а потім GRANT SELECTна таблицях.

Де моя помилка? Що я роблю неправильно? Як я можу досягти того, що хочу (щоб новий користувач нічого не мав робити, перш ніж явно надавати їй відповідні права.

Я загубився, і ваша допомога дуже цінується :)

РЕДАКЦІЯ Дотримуючись поради @ daniel-verite, я відкликаю все одразу після створення бази даних. Користувачеві дієтич більше не дозволяється створювати таблицю. Добре. АЛЕ : Тепер також власнику бази даних project2 заборонено створювати таблицю. Навіть після видачі GRANT ALL PRIVILEGES ON DATABASE project2_core TO project2і GRANT ALL PRIVILEGES ON SCHEMA public TO project2, я отримую помилку ПОМИЛКА: для створення в ньому не обрано жодної схеми , і коли я спеціально намагаюся CREATE TABLE public.WHATEVER ();, я отримую ERROR: дозволу відмовлено для загальнодоступних схем . Що я роблю неправильно?

Відповіді:


38

Під час створення нової бази даних будь-яка роль дозволена для створення об'єктів у publicсхемі. Щоб усунути таку можливість, ви можете опублікувати одразу після створення бази даних:

REVOKE ALL ON schema public FROM public;

Редагувати: після вищевказаної команди лише суперрусер може створювати нові об'єкти всередині publicсхеми, що не є практичним. Якщо припустити, що не foo_userможе бути надано цю пільгу, це має бути зроблено з:

GRANT ALL ON schema public TO foo_user;

Щоб знати, що ALLозначає для схеми, ми повинні звернутися до GRANT в документі , (в PG 9.2 є не менше 14 форм операторів GRANT, які стосуються різних речей ...). Здається, що для схеми це означає CREATEі USAGE.

З іншого боку, GRANT ALL PRIVILEGES ON DATABASE...надаватиме CONNECTі CREATEта TEMP, але CREATEв даному контексті відноситься до схем, а не постійною таблиці.

Щодо цієї помилки: ERROR: no schema has been selected to create inце трапляється при спробі створити об'єкт без кваліфікації схеми (як у create table foo(...)), не маючи дозволу на створення його в будь-якій схемі search_path.


працює :) Але я все одно не розумію: я вже намагався REVOKE ALL ON DATABASE project2_core FROM PUBLIC;. чому це не мало жодного ефекту?
andreas-h

mhh. тепер власника бази більше не дозволяють CREATE TABLE. дивіться мою редакцію вище.
andreas-h

@ andreas-h: відредагував відповідь з більш детальною інформацією
Daniel Vérité

Щодо помилки, її можна легко відтворити, видаючи команди із запитання та ваш ЗАМОВИТИ в порядку :)
dezso

@ DanielVérité Я розробив поняття, що стоять за цим, у новій відповіді, щоб доповнити вашу. Буде оцінено санітарна перевірка.
Крейг Рінгер

19

Тут важливо зрозуміти, що привілеї не є герахічними та не успадковуються від об'єктів, що містять . ALLозначає всі привілеї для цього об'єкта, не всі привілеї для цього об'єкта та всі об'єкти, що містяться .

Коли ви надаєте ALLбазу даних, ви надаєте грант CREATE, CONNECT, TEMP. Це дії над самим об'єктом бази даних:

  • CONNECT: Підключіться до БД
  • CREATE: Створіть схему ( не таблицю)
  • TEMP: Створюйте тимчасові об’єкти, включаючи, але не обмежуючись тимчасовими таблицями

Тепер кожна база даних PostgreSQL за замовчуванням має publicсхему, що створюється при створенні бази даних. Ця схема має всі права, надані ролі public, членами якої є явно всі. Для схеми ALLозначає CREATE, USAGE:

  • CREATE: Створіть об'єкти (включаючи таблиці) у цій схемі
  • USAGE: Список об'єктів у схемі та доступ до них, якщо вони дозволяють

Якщо ви не вказуєте схему для створення об’єкта, як таблиця в, двигун бази даних використовує search_path, і за замовчуванням publicсхема спочатку є, search_pathтому таблиця створюється там. Кожна людина має publicза замовчуванням права, тому створення дозволено. Права користувачів на базу даних на даний момент не мають значення, оскільки користувач не намагається зробити що-небудь з об'єктом бази даних, а лише схемою всередині нього.

Не має значення, що ви не надали користувачеві жодних прав, крім надання CONNECTбазі даних, оскільки publicсхема дозволяє всім користувачам створювати таблиці в ній за замовчуванням. Даніель вже пояснив, як за бажанням відкликати це право.

Якщо ви хочете чітко делегувати кожне право, скасуйте все з загальнодоступних або просто відмовтесь від публічної схеми. Ви можете створити нову базу даних шаблонів із застосуванням цієї зміни, якщо ви хочете. Ви також можете застосувати його template1, але це, ймовірно, порушить безліч сторонніх кодів, який передбачає, що publicіснує і підлягає запису.


Це може мати більше сенсу, якщо ви подивитеся на аналогію файлової системи.

Якщо у мене є структура каталогів (режим спрощений, щоб показувати лише режим, який стосується поточного користувача):

/dir1           mode=r-x
/dir1/dir2      mode=rwx

тоді я нічого не можу створити всередині /dir1, тому що не маю дозволу на запис. Тож якщо я touch /dir1/somefileотримаю дозвіл, який відхилив помилку.

Тим НЕ менше, я робити дозволу заглянути всередину /dir1і доступу містяться файли і каталоги, в тому числі /dir1/dir2. У мене є дозвіл на написання dir2. Так touch /dir1/dir2/somefileце вдасться , хоча я не маю дозволу на написання dir1.

Те ж саме з базами даних та схемами.


7

Якщо ви хочете лише завадити новим користувачам створювати таблиці, вам потрібно виконати таку команду:

REVOKE CREATE ON SCHEMA public FROM public;

Якщо ви REVOKE ALL(як це підказують інші відповіді), ви також не дасте користувачам мати USAGEдозволи. USAGEозначає, що користувачі можуть використовувати призначені їм дозволи, тому якщо ви видалите їх, то ваші користувачі не зможуть перелічити та не отримати доступ до таблиць, до яких вони мають доступ.

Можна також REVOKE CREATEвказати конкретного користувача:

REVOKE CREATE ON schema public FROM myuser;

Дивіться також: Як створити користувача лише для читання за допомогою PostgreSQL .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.