it-swarm-eu.dev

Proč může nový uživatel vytvořit tabulku?

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ě?

44
andreas-h

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.

41
Daniel Vérité

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 DB
  • CREATE: Vytvořte schéma (ne tabulku)
  • TEMP: Vytváří dočasné objekty, včetně dočasných tabulek

Nyní 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ématu
  • USAGE: 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.

19
Craig Ringer

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 .

7
Adrian Macneil