postgres postgresql authorization
Todo objeto criado tem um dono, que é o papel que (inicialmente) pode fazer todas as ações sobre aquele objeto. Outros papéis que quiserem usar o objeto devem receber os privilégios corretos.
Privilégios são as características que permitem que uma ação seja executada sobre um objeto por um papel. Se o privilégio não existir, a ação vai ser impedida. A única exceção é que superusuários ignoram essa checagem.
O dono do objeto pode atribuir (GRANT
) ou revogar (REVOKE
) privilégios sobre
o objeto, assim como pode tornar outro papel o novo dono do objeto. Ele também
pode revogar alguns dos próprios privilégios.
Com os comandos GRANT
e REVOKE
é possível atribuir todos os privilégios
(ALL
) ou apenas privilégios específicos. Também é possível atribuí-los a todos
os papéis (PUBLIC
) ou apenas a papéis específicos.
Com o comando ALTER DEFAULT PRIVILEGES
é possível alterar os privilégios
padrão dos objetos, ou seja, aqueles que serão usados para objetos que serão
criados no futuro.
Cada privilégio é abreviado por uma letra e é usado por um conjunto de tipos de objetos, como na tabela:
Privilégio | Abreviação | Tipos de objeto | O que permite |
---|---|---|---|
SELECT | r ("read") | LARGE OBJECT, SEQUENCE, TABLE (e objetos similares), coluna de tabela | leitura de dados |
INSERT | a ("append") | TABLE, coluna de tabela | escrita de dados |
UPDATE | w ("write") | LARGE OBJECT, SEQUENCE, TABLE, coluna de tabela | alteração de dados |
DELETE | d | TABLE | deleção de dados |
TRUNCATE | D | TABLE | truncar tabelas |
REFERENCES | x | TABLE, coluna de tabela | referências entre tabelas |
TRIGGER | t | TABLE | gatilhos em tabelas |
CREATE | C | DATABASE, SCHEMA, TABLESPACE | criação de outros objetos dentro deste |
CONNECT | c | DATABASE | conectar ao banco de dados |
TEMPORARY | T | DATABASE | criação de tabelas temporárias |
EXECUTE | X | FUNCTION, PROCEDURE | execução |
USAGE | U | DOMAIN, FOREIGN DATA WRAPPER, FOREIGN SERVER, LANGUAGE, SCHEMA, SEQUENCE, TYPE | uso do objeto |
Cada tipo de objeto usa um conjunto de todos os privilégios que pode usar, um
conjunto de privilégios permitidos a todos (PUBLIC
) por padrão e um comando
psql
que permite listá-los, como na
tabela:
Tipo de objeto | Todos os privilégios | Privilégios PUBLIC padrão | Comando psql |
---|---|---|---|
DATABASE | CTc | Tc | \l |
DOMAIN | U | U | \dD+ |
FUNCTION or PROCEDURE | X | X | \df+ |
FOREIGN DATA WRAPPER | U | nenhum | \dew+ |
FOREIGN SERVER | U | nenhum | \des+ |
LANGUAGE | U | U | \dL+ |
LARGE OBJECT | rw | nenhum | |
SCHEMA | UC | nenhum | \dn+ |
SEQUENCE | rwU | nenhum | \dp |
TABLE (e objetos similares) | arwdDxt | nenhum | \dp |
Coluna de tabela | arwx | nenhum | \dp |
TABLESPACE | C | nenhum | \db+ |
TYPE | U | U | \dT+ |
[[local]:5432] app@app=# GRANT SELECT, INSERT ON logs TO PUBLIC;
Criamos um usuário da aplicação, um grupo para conter a permissões de leitura e um usuário comum que fará a leitura:
[[local]:5432] postgres@postgres=# CREATE USER app; [[local]:5432] postgres@postgres=# CREATE GROUP leitor; [[local]:5432] postgres@postgres=# CREATE USER auditor IN ROLE leitor;
Atribuímos as permissões sobre os objetos atuais:
[[local]:5432] postgres@template1=# GRANT USAGE ON SCHEMA public TO leitor;
Atribuímos as permissões sobre os objetos futuros criados pelo usuário app:
[[local]:5432] postgres@template1=# ALTER DEFAULT PRIVILEGES FOR ROLE app GRANT USAGE ON SCHEMAS to leitor; [[local]:5432] postgres@template1=# ALTER DEFAULT PRIVILEGES FOR ROLE app GRANT SELECT ON TABLES to leitor; [[local]:5432] postgres@template1=# ALTER DEFAULT PRIVILEGES FOR ROLE app GRANT SELECT ON SEQUENCES to leitor;
Após esse ponto, se um banco novo for criado e populado com objetos pelo usuário app, eles serão acessíveis pelo usuário auditor, com os privilégios de leitor:
[[local]:5432] postgres@postgres=# CREATE DATABASE app OWNER app TEMPLATE template1; [[local]:5432] postgres@postgres=# \c app app [[local]:5432] app@app=> CREATE TABLE dados (); [[local]:5432] app@app=> INSERT INTO dados DEFAULT VALUES; [[local]:5432] app@app=> \c app auditor [[local]:5432] auditor@app=> SELECT COUNT(*) FROM dados; ╔═══════╗ ║ count ║ ╠═══════╣ ║ 1 ║ ╚═══════╝ [[local]:5432] auditor@app=>
Vamos criar um grupo de permissões elevadas (superusuários) que precisam ser
invocadas explicitamente para serem usadas, similar a como um usuário comum do
sistema operacional pode executar um comando setuid
(sudo
ou su
) para se
tornar um outro usuário e posteriormente retornar ao usuário inicial. Esse
comportamento é definido no padrão SQL.
Grupo de DBAs, em que os membros são superusuários:
[[local]:5432] postgres@postgres=# CREATE GROUP dba SUPERUSER;
Os usuários serão criados sem herdar (NOINHERIT
) os privilégios de
superusuário automaticamente, ou seja, devem executar SET ROLE dba
para
usá-los:
[[local]:5432] postgres@postgres=# CREATE USER alice NOINHERIT; [[local]:5432] postgres@postgres=# CREATE USER bob NOINHERIT;
Alice é adicionada ao grupo, com a permissão de adicionar outros membros ao grupo:
[[local]:5432] postgres@postgres=# GRANT dba TO alice WITH ADMIN OPTION;
Bob é adicionado ao grupo, sem a permissão de adicionar outros membros ao grupo:
[[local]:5432] postgres@postgres=# GRANT dba TO bob;
A partir deste momento, tanto alice quanto bob podem usar os privilégios de superusuário explicitamente como:
[[local]:5432] bob@postgres=> SET ROLE dba; [[local]:5432] dba@postgres=# -- faz coisas como superusuário [[local]:5432] dba@postgres=# RESET ROLE; [[local]:5432] bob@postgres=> -- retorna ao usuário comum
E alice pode adicionar outros ao grupo, mas bob não pode:
[[local]:5432] alice@postgres=> GRANT dba TO charlie;
É importante não usar superusuários para atividades que não tenham necessidade.
Uma delas é monitoramento, para a qual existe um papel pg_monitor
que permite
a leitura de estatísticas e configurações.
[[local]:5432] postgres@postgres=# CREATE USER monitoramento IN GROUP pg_monitor;
Ou:
[[local]:5432] postgres@postgres=# CREATE USER monitoramento; [[local]:5432] postgres@postgres=# GRANT pg_monitor TO monitoramento;
Crie ao menos um grupo para dbas (superusuários), um para leitores de todos os dados para a equipe de BI, um para a equipe de monitoramento e um para a equipe da aplicação (com permissões de edição).
Crie um banco de dados para a aplicação (o dono será o grupo da equipe da aplicação), um usuário alice para a equipe de BI, um usuário bob para a equipe de monitoramento e um charlie para a equipe da aplicação.
Teste os seguintes pontos:
- Crie uma tabela usando charlie - deve funcionar
- Escreva na tabela com o usuário charlie - deve funcionar
- Escreva na tabela com o usuário bob - não deve funcionar
- Escreva na tabela com o usuário alice - não deve funcionar
- Leia a tabela com o usuário charlie - deve funcionar
- Leia a tabela com o usuário bob - não deve funcionar
- Leia a tabela com o usuário alice - deve funcionar
-
Execute a função
pg_ls_waldir()
(restrita a monitoramento) com o usuário charlie - não deve funcionar -
Execute a função
pg_ls_waldir()
com o usuário bob - deve funcionar -
Execute a função
pg_ls_waldir()
com o usuário alice - não deve funcionar