V této kapitole se podíváme na to, jak je to s přístupovými právy. Databáze sytému PostgreSQL mohou současně využívat různí uživatelé, kteří mohou mít právo vytvářet nové databáze a tabulky. Určitě by se vám nelíbilo, kdyby bylo možné, aby každý uživatel v systému mohl pracovat s databázemi, které jste vytvořili a někdy určitě nebudete chtít ani aby mohli číst data v nich uložená. Na druhou stranu existují situace, kdy budete naopak požadovat, aby měli uživatelé možnost s vámi vytvořenými tabulkami pracovat. Z toho co je zde napsáno vyplívají dva zásadní problémy - kdo je to uživatel a jaká může mít práva.
Uživatel systému PostgreSQL není to samé jako uživatel Linuxu, ačkoliv se mnohdy jejich jména (login) schodují a tudíš jsou to ti samí. Avšak pro jednoduchost výkladu použijeme dva uživatele jménem rimmer a group06, kteří jsou linuxovými uživateli a vytvoříme pro ně uživatelská jména.
Řekněme, že jste právě po čerstvé instalaci postgresu a tak chcete vytvořit prvního uživatele tohoto systému, uživatele rimmer. Protože zatím jediný linuxový uživatel, který k tomu má práva, je postgres, musíte se připojit k (libovolné) databázi pod tímto uživatelským kontem. Protože neznáte heslo k přístupu k uživatelskému kontu postgres, musíte se k jeho kontu dostat přes superuživatelský účet root (už to začíná připomínat telenovelu, že? :-).
Pokud jste se dostali úspěšně až sem, můžete vytvořit prvního uživatele pomocí příkazu CREATE USER. Teď vytvoříme uživatele rimmer s právy vytváření nových databází a s právy vytváření nových uživatelů. Předpokládám, že už exituje linuxové konto uživatele rimmer, nyní vytváříme jeho databázové konto. Samozřejmě mu můžete dát právo jen vytvářet databáze, nebo jen vytvářet uživatele. (Pokud mu dáte právo vytvářet uživatele, má právo i měnit práva uživatelů (pomocí ALTER USER), takže si může sám sobě dát právo vytvářet databáze :-)).$ su - Password: root:~# su - postgres postgres:~$ psql template1 # nebo psql libovolna_database
Teď už se můžete přihlásit do linuxu jako uživatel rimmer, vytvořit databázi (pokus), přihlásit se do databáze a vytvořit uživatele group06.template1=# CREATE USER rimmer WITH CREATEDB CREATEUSER; CREATE USER
rimmer $ createdb pokus
CREATE DATABASE
rimmer $ psql pokus
Welcome to psql, the PostgreSQL interactive terminal.
Type: \copyright for distribution terms
\h for help with SQL commands
\? for help on internal slash commands
\g or terminate with semicolon to execute query
\q to quit
pokus=#
POZOR! Každý uživatel s právy vytváření dalších uživatelů
může neomezeně pracovat s cizými tabulkami (číst je, upravovat,
mazat ...)!!
Všimněte si, že v databázi již není prompt ukončen špičatou závorkou >, ale znakem #. Uživatel rimmer totiž získal jakási superuživatelská práva, díky kterým může nakládat s právy ostatních uživatelů. Hned toho využijeme k vytvoření běžného uživatele group06.
template1=# CREATE USER group06; CREATE USER
rimmer $ psql rimmer Welcome to psql, the PostgreSQL interactive terminal. ...
V tuto chvíli může uživatel group06 (kdybychom ho nesmazali příkazem DROP USER) vytvářet (a mazat) databáze i uživatele postgresu. Pokud by jste mu chtěli tyto práva odebrat, pak použijte ALTER TABLE WITH NOCREATEDB NOCREATEUSER;.rimmer=# ALTER USER group06 WITH CREATEDB; ALTER USER rimmer=# ALTER USER group06 WITH CREATEUSER; ALTER USER rimmer=# DROP USER group06; DROP USER
A nakonec slíbené smazání databáze pokus.
rimmer $ dropdb pokus DROP DATABASE
V předchozí části jsme si vytvořili dva uživatele: rimmer a group06. (Mimochem, kromě uživatelů lze vytvářet v postgresu i uživatelské skupiny, ale o tom tu není a nebude řeč). V příkladech si uživatel rimmer vytvoří tabulku seznam, ke které bude dávat přístupová práva uživateli group06.
rimmer $ psql rimmer Welcome to psql, the PostgreSQL interactive terminal. ...
Přístupová práva můžete přidvat buďto jednomu uživateli (za druhým), nebo jej zpřístupnit všem uživatelům (PUBLIC). Pokud předáváte práva konkrétnímu uživateli, musí tento uživatel existovat. Možnosti příkazu GRANT samozřejmě zjistíte pomocí metapříkazu \h GRANT. Uvidíte tak, jaká všechna práva je možné přidělovat. Zajímavá je například volba ALL, která přidělí uživateli všechna práva. Spojením PUBLIC a ALL povolíte všechno všem :-).rimmer=# CREATE TABLE seznam (id SERIAL, nazev VARCHAR(20), cena NUMERIC(5,2)); NOTICE: CREATE TABLE will create implicit sequence 'seznam_id_seq' for SERIAL column 'seznam.id' NOTICE: CREATE TABLE / UNIQUE will create implicit index 'seznam_id_key' for table 'seznam' CREATE
V našem příkladě teď přidělíme práva uživateli group06 na čtení
tabulky (SELECT) seznam a vkládání záznamu (INSERT). Než tak
ale učiníme, ještě se musím zmínit o jednom důležitém metapříkazu
\z. Tento metapříkaz dokáže vypsat přístupová práva k
objektům v databázi. Přístupová práva jsou za jménem uživatele, ke
kterému se vztahují a rovnítkem. Jsou označeny jednopísmennými
zkratkami, viz. následující tabulka. Z ní se také dozvíte jaká že
to práva lze nastavovat.
| Zkratka | Práva | Uživatel může ... |
|---|---|---|
| r | SELECT ("read") | použít příkaz SELECT, a také COPY FROM. |
| w | UPDATE ("write") | použít příkaz UPDATE. Toto právo je třeba k použití sekvencí (nextval, currval, setval) |
| a | INSERT ("append") | použít příkaz UPDATE, a také COPY TO |
| d | DELETE | mazat data příkazem DELETE |
| R | RULE | použít příkaz CREATE RULE |
| x | REFERENCES | vytvořit novou tabulku s referencí na tuto tabulku |
| t | TRIGGER | použít příkaz CREATE TRIGGER |
| arwdRxt | Všechny práva | Může všechno víše zmíněné. |
rimmer=# \z seznam
Access privileges for database "rimmer"
Table | Access privileges
---------------+-------------------
seznam |
seznam_id_seq |
(2 rows)
rimmer=# GRANT SELECT,INSERT ON seznam TO group06;
GRANT
rimmer=# \z seznam
Access privileges for database "rimmer"
Table | Access privileges
---------------+-------------------------------
seznam | {=,rimmer=arwdRxt,group06=ar}
seznam_id_seq |
(2 rows)
Z příkladu vidíte, že nejdřív nebyla nastavena žádná práva
(vlastníkova práva byla postgresem chápána implicitne jako ALL). Po
nastavení práv uživateli group06 s již zobrazují jednak jeho práva
a také práva vlastníka tabulky - uživtatele rimmer. Za prvním
rovnítkem se ukazují práva nastavená pro všechny (PUBLIC), ale
momentálně tam žádná nejsou.
Teď se k databázi rimmer přihlásím jako uživatel group06 a pokusím se z tabulkou pracovat. Znovu upozorňuji, že poku bude mít uživatel právo vytvářet další uživatele (viz. ALTER USER), všechna zde popisovaná přístupová práva se budou míjet účinkem.
Uživatel group06:
rimmer=> SELECT * FROM seznam;
id | nazev | cena
----+-------+------
(0 rows)
rimmer=> INSERT INTO seznam (nazev,cena) VALUES ('abcd',25.2);
ERROR: seznam_id_seq.nextval: you don't have permissions to set sequence
seznam_id_seq
Poznámka: To slovíčko rimmer, které je v příkladu, označuje
(trochu nešťastně zvolený) název databáze, nikoliv uživatele.
Jak vidíte, vložení záznamu do tabulky selhalo, neboť nemáme přístup k sekvenci seznam_id_seq, která se mění při každém vložení záznamu v tabulce (kvůli sloupci s typem SERIAL). Uživatel rimmer tak musí ještě přidat právo úpravy k této sekvenci pro uživatele group06. Teď už to půjde rychle.
Uživatel rimmer:
Uživatel group06:rimmer=# GRANT UPDATE ON seznam_id_seq TO group06; GRANT
rimmer=> INSERT INTO seznam (nazev,cena) VALUES ('abcd',25.2);
INSERT 43100 1
rimmer=> UPDATE seznam SET cena=0;
ERROR: seznam: Permission denied.
Skusíme si nastavení práva úpravy pro všechny.
Uživatel rimmer:
rimmer=# GRANT UPDATE ON seznam TO PUBLIC;
GRANT
rimmer=# \z seznam
Access privileges for database "rimmer"
Table | Access privileges
---------------+--------------------------------
seznam | {=w,rimmer=arwdRxt,group06=ar}
seznam_id_seq | {=,rimmer=arwdRxt,group06=w}
(2 rows)
Uživatel group06:
rimmer=> UPDATE seznam SET cena=0; UPDATE 1
Uživatel rimmer:
rimmer=# \z seznam
Access privileges for database "rimmer"
Table | Access privileges
---------------+--------------------------------
seznam | {=w,rimmer=arwdRxt,group06=ar}
seznam_id_seq | {=,rimmer=arwdRxt,group06=w}
(2 rows)
rimmer=# REVOKE ALL ON seznam FROM group06;
REVOKE
rimmer=# \z seznam
Access privileges for database "rimmer"
Table | Access privileges
---------------+------------------------------
seznam | {=w,rimmer=arwdRxt}
seznam_id_seq | {=,rimmer=arwdRxt,group06=w}
(2 rows)
rimmer=# REVOKE UPDATE ON seznam FROM PUBLIC;
REVOKE
rimmer=# \z seznam
Access privileges for database "rimmer"
Table | Access privileges
---------------+------------------------------
seznam | {=,rimmer=arwdRxt}
seznam_id_seq | {=,rimmer=arwdRxt,group06=w}
(2 rows)
