Eu estou querendo saber por que um usuário recém-criado tem permissão para criar uma tabela depois de se conectar a um banco de dados. Eu tenho um banco de dados 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)
Até agora tudo bem. Agora eu crio um usuário:
postgres=# CREATE ROLE dietrich ENCRYPTED PASSWORD 'md5XXX' LOGIN NOCREATEROLE NOCREATEDB NOSUPERUSER
OK. Quando tento me conectar ao banco de dados, o usuário não tem permissão para fazer isso:
$ 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.
Isto é o que eu esperava. Agora as coisas estranhas começam. Eu concedo ao usuário 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)
E sem mais concessões, o usuário tem permissão para criar uma tabela:
$ 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)
Eu esperava que o usuário não tivesse permissão para fazer nada antes que eu fizesse explicitamente GRANT USAGE
no esquema e depois GRANT SELECT
nas tabelas.
Onde está o meu erro? O que estou fazendo errado? Como posso conseguir o que quero (que um novo usuário não tenha permissão para fazer nada antes de conceder explicitamente a ele os direitos apropriados.
Estou perdido, e sua ajuda é muito apreciada :)
EDITAR Seguindo o conselho de @daniel-verite, agora revogo tudo imediatamente após criar o banco de dados. O usuário dietrich não tem mais permissão para criar uma tabela. Bom. MAS : Agora, também o proprietário do banco de dados, project2 , não tem permissão para criar uma tabela. Mesmo depois de emitir GRANT ALL PRIVILEGES ON DATABASE project2_core TO project2
e GRANT ALL PRIVILEGES ON SCHEMA public TO project2
, recebo um erro ERROR: nenhum esquema foi selecionado para criar em , e quando tento especificamente CREATE TABLE public.WHATEVER ();
, recebo ERROR: permission denied for schema public . O que estou fazendo errado?
Quando você cria um novo banco de dados, qualquer função tem permissão para criar objetos no
public
esquema. Para remover essa possibilidade, você pode emitir imediatamente após a criação do banco de dados:Edit: após o comando acima, apenas um superusuário pode criar novos objetos dentro do
public
esquema, o que não é prático. Supondo que um não superusuáriofoo_user
deva receber esse privilégio, isso deve ser feito com:Para saber o que
ALL
significa para um esquema, devemos nos referir a GRANT no doc , (no PG 9.2 existem nada menos que 14 formas de instruções GRANT que se aplicam a coisas diferentes...). Parece que para um esquema significaCREATE
eUSAGE
.Por outro lado,
GRANT ALL PRIVILEGES ON DATABASE...
concederáCONNECT
eCREATE
eTEMP
, masCREATE
neste contexto se refere a esquemas, não a tabelas permanentes.Com relação a este erro:
ERROR: no schema has been selected to create in
, ocorre ao tentar criar um objeto sem qualificação de esquema (como emcreate table foo(...)
) sem a permissão para criá-lo em qualquer esquema dosearch_path
.A coisa crucial a entender aqui é que os privilégios não são hierárquicos e não são herdados de objetos que contêm .
ALL
significa todos os privilégios para este objeto nem todos os privilégios para este objeto e todos os objetos contidos .Quando você concede
ALL
em um banco de dados, está concedendoCREATE, CONNECT, TEMP
. Estas são ações no próprio objeto de banco de dados:CONNECT
: Conecte-se ao banco de dadosCREATE
: Crie um esquema ( não uma tabela)TEMP
: Crie objetos temporários, incluindo mas não limitado a tabelas temporáriasAgora, cada banco de dados PostgreSQL por padrão tem um
public
esquema que é criado quando o banco de dados é criado. Esse esquema tem todos os direitos concedidos ao rolepublic
, do qual todos são membros implicitamente. Para um esquema,ALL
significaCREATE, USAGE
:CREATE
: Crie objetos (incluindo tabelas) dentro deste esquemaUSAGE
: Listar objetos no esquema e acessá-los se suas permissões permitiremSe você não especificar o esquema para criar um objeto como uma tabela, o mecanismo de banco de dados usará o
search_path
, e por padrão opublic
esquema será o primeiro asearch_path
ser criado lá. Todos têm direitospublic
por padrão, então a criação é permitida. Os direitos dos usuários no banco de dados são irrelevantes neste momento, pois o usuário não está tentando fazer nada com o objeto do banco de dados, apenas um esquema dentro dele.Não importa se você não concedeu ao usuário nenhum direito além de conceder
CONNECT
no banco de dados, porque opublic
esquema permite que todos os usuários criem tabelas nele por padrão. Daniel já explicou como revogar esse direito, se desejar.Se você deseja delegar todos os direitos explicitamente, revogue todos de public ou simplesmente elimine o esquema público. Você pode criar um novo banco de dados de modelo com essa alteração aplicada, se desejar. Como alternativa, você pode aplicá-lo a
template1
, mas isso provavelmente quebrará muitos códigos de terceiros que assumem quepublic
existem e são graváveis.Isso pode fazer mais sentido se você observar uma analogia do sistema de arquivos.
Se eu tiver a estrutura de diretórios (modo simplificado para mostrar apenas o modo que se aplica ao usuário atual):
então não posso criar nada dentro
/dir1
do , porque não tenho permissão de gravação. Então, se eutouch /dir1/somefile
receber um erro de permissão negada.No entanto, tenho permissão para olhar dentro
/dir1
e acessar arquivos e diretórios contidos, incluindo/dir1/dir2
. Eu tenho permissão de gravação emdir2
. Entãotouch /dir1/dir2/somefile
terá sucesso , mesmo que eu não tenha permissão de gravação paradir1
.Mesma coisa com bancos de dados e esquemas.
Se você deseja apenas impedir que novos usuários criem tabelas, você precisa executar o seguinte comando:
Se você
REVOKE ALL
(como outras respostas sugerem), também impedirá que os usuários tenhamUSAGE
permissões.USAGE
significa que os usuários podem usar as permissões atribuídas a eles, portanto, se você remover isso, seus usuários não poderão listar ou acessar as tabelas às quais eles têm acesso.Alternativamente, você também pode
REVOKE CREATE
para um usuário específico:Veja também: Como criar um usuário somente leitura com PostgreSQL .