Zajímalo by mě, proč nově vytvořený uživatel má povoleno vytvořit tabulku po připojení k databázi. Mám jednu databázi, 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)
Zatím je vše dobré. Nyní vytvořím uživatele:
postgres=# CREATE ROLE dietrich ENCRYPTED PASSWORD 'md5XXX' LOGIN NOCREATEROLE NOCREATEDB NOSUPERUSER
Dobře. Když se pokusím připojit k databázi, uživatel to nemá povoleno:
$ 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.
To jsem očekával. Nyní začnou podivné věci. Uděluji uživateli 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)
A bez dalších grantů může uživatel vytvořit tabulku:
$ 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)
Čekal bych, že uživatel nebude moci nic dělat, než explicitně provedu GRANT USAGE
Na schématu a poté GRANT SELECT
V tabulkách.
Kde je moje chyba? Co dělám špatně? Jak mohu dosáhnout toho, co chci (že nový uživatel nesmí nic dělat, než jí výslovně udělí příslušná práva.
Jsem ztracen a tvá pomoc je velmi ceněna :)
EDITOVAT V návaznosti na radu @ daniel-verite, nyní jsem vše vytvořil ihned po vytvoření databáze. Uživatel dietrich již nesmí vytvářet tabulku. Dobrý. ALE : Nyní také vlastník databáze project2 není povoleno vytvořit tabulku. I po vydání GRANT ALL PRIVILEGES ON DATABASE project2_core TO project2
A GRANT ALL PRIVILEGES ON SCHEMA public TO project2
Se mi zobrazí chyba CHYBA: Nebylo vybráno žádné schéma pro vytvoření , a když se konkrétně pokusím CREATE TABLE public.WHATEVER ();
, dostanu CHYBA: oprávnění odepřeno pro veřejné schéma . Co dělám špatně?
Při vytváření nové databáze může jakákoli role vytvářet objekty ve schématu public
. Chcete-li tuto možnost odebrat, můžete vydat ihned po vytvoření databáze:
REVOKE ALL ON schema public FROM public;
Upravit: po výše uvedeném příkazu může pouze superuživatel vytvořit nové objekty uvnitř schématu public
, což není praktické. Předpokládejme, že by toto oprávnění mělo být uděleno uživateli, který není superuživatelem foo_user
, Mělo by to být provedeno pomocí:
GRANT ALL ON schema public TO foo_user;
Abychom věděli, co pro schéma znamená ALL
, musíme odkazovat na GRANT v dokument , (v PG 9.2 neexistuje méně než 14 forem příkazů GRANT, které se vztahují na různé věci. ..). Zdá se, že pro schéma to znamená CREATE
a USAGE
.
Na druhé straně GRANT ALL PRIVILEGES ON DATABASE...
Udělí CONNECT
a CREATE
a TEMP
, ale CREATE
se v této souvislosti týká schémat, nikoli trvalých tabulky.
Pokud jde o tuto chybu: ERROR: no schema has been selected to create in
, Stává se, když se pokoušíte vytvořit objekt bez kvalifikace schématu (jako v create table foo(...)
), přičemž mu chybí oprávnění k jeho vytvoření v libovolném schématu search_path
.
Zásadní věcí, které je třeba pochopit, je to, že oprávnění nejsou heirachical a jsou nezděděna z obsahu objektů. ALL
znamená všechna oprávnění pro tento objekt ne všechna oprávnění pro tento objekt a všechny obsažené objekty.
Když udělíte ALL
v databázi, udělujete CREATE, CONNECT, TEMP
. Toto jsou akce na objektu databáze, který vlastní:
CONNECT
: Připojte se k DBCREATE
: Vytvořte schéma (ne tabulku)TEMP
: Vytváří dočasné objekty, včetně dočasných tabulekNyní má každá databáze PostgreSQL ve výchozím nastavení schéma public
, které je vytvořeno při vytvoření databáze. Toto schéma má všechna práva udělená roli public
, jejíž každý je implicitně členem. Pro schéma ALL
znamená CREATE, USAGE
:
CREATE
: Vytváření objektů (včetně tabulek) v tomto schématuUSAGE
: Seznam objektů ve schématu a přístup k nim, pokud to jejich oprávnění dovolíPokud neurčíte schéma pro vytvoření objektu, jako je tabulka, použije databázový stroj search_path
a ve výchozím nastavení je schéma public
první na search_path
, takže tam bude vytvořena tabulka. Každý má ve výchozím nastavení public
, takže vytváření je povoleno. Práva uživatelů na databázi jsou v tomto okamžiku irelevantní, protože uživatel se nesnaží udělat nic pro objekt databáze sám, pouze schéma uvnitř něj.
Nezáleží na tom, že jste uživateli neudělili žádná jiná práva než udělení CONNECT
v databázi, protože schéma public
umožňuje všem uživatelům ve výchozím nastavení vytvářet tabulky. Daniel již vysvětlil, jak toto právo v případě potřeby odvolat.
Pokud chcete delegovat všechna práva výslovně, zrušte vše z veřejné nebo jednoduše zrušte veřejné schéma. Pokud chcete, můžete vytvořit novou databázi šablon s touto změnou. Alternativně ji můžete použít na template1
, ale to pravděpodobně přeruší spoustu kódu třetí strany, který předpokládá, že public
existuje a je zapisovatelný.
To by mohlo mít větší smysl, pokud se podíváte na analogii souborového systému.
Pokud mám strukturu adresářů (režim zjednodušený tak, aby ukazoval pouze režim, který se vztahuje na aktuálního uživatele):
/dir1 mode=r-x
/dir1/dir2 mode=rwx
pak nemůžu vytvořit nic uvnitř /dir1
, protože nemám oprávnění k zápisu. Pokud tedy touch /dir1/somefile
Dostane se chyba odepření oprávnění.
Mám však do mám oprávnění nahlédnout dovnitř /dir1
a přístup k obsaženým souborům a adresářům, včetně /dir1/dir2
. Mám oprávnění k zápisu na dir2
. Tak touch /dir1/dir2/somefile
bude spět, i když nemám písemné oprávnění k dir1
.
Totéž s databázemi a schématy.
Pokud chcete pouze zabránit novým uživatelům ve vytváření tabulek, musíte spustit následující příkaz:
REVOKE CREATE ON SCHEMA public FROM public;
Jestli ty REVOKE ALL
(jak napovídají jiné odpovědi), zabráníte také uživatelům, aby měli oprávnění USAGE
. USAGE
znamená, že uživatelé mohou používat oprávnění, která jim byla přidělena, takže pokud je odeberete, nebudou vaši uživatelé moci zobrazit seznam nebo získat přístup k tabulkám, ke kterým mají přístup.
Případně můžete také REVOKE CREATE
pro konkrétního uživatele:
REVOKE CREATE ON schema public FROM myuser;
Viz také: Jak vytvořit uživatele jen pro čtení s PostgreSQL .