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)
Por enquanto, 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 outras concessões, o usuário pode 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 de eu explicitamente fazer GRANT USAGE
o esquema e depois GRANT SELECT
as tabelas.
Onde está 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 ela os direitos apropriados.
Estou perdido, e sua ajuda é muito apreciada :)
EDIT Seguindo o conselho de @ daniel-verite, agora revoco tudo imediatamente após a criação do banco de dados. O usuário dietrich não pode mais criar uma tabela. Boa. MAS : Agora, também o proprietário do banco de dados, projeto2 , não tem permissão para criar uma tabela. Mesmo após a emissão GRANT ALL PRIVILEGES ON DATABASE project2_core TO project2
e GRANT ALL PRIVILEGES ON SCHEMA public TO project2
, recebo um erro ERRO: nenhum esquema foi selecionado para criação e, quando tento especificamente CREATE TABLE public.WHATEVER ();
, recebo a permissão ERRO: negada para o público do esquema . O que estou fazendo errado?
fonte
REVOKE ALL ON DATABASE project2_core FROM PUBLIC;
. por que isso não teve nenhum efeito?CREATE TABLE
. veja minha edição acima.O ponto crucial a entender aqui é que os privilégios não são heiráquicos e não são herdados de objetos contidos .
ALL
significa todos os privilégios para esse objeto nem todos os privilégios para esse 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 objeto de banco de dados:CONNECT
: Conecte-se ao banco de dadosCREATE
: Criar um esquema ( não uma tabela)TEMP
: Criar objetos temporários, incluindo, entre outros, tabelas temporáriasAgora, cada banco de dados PostgreSQL, por padrão, possui um
public
esquema criado quando o banco de dados é criado. Esse esquema tem todos os direitos concedidos à funçãopublic
, dos quais todos são implicitamente membros. Para um esquema,ALL
significaCREATE, USAGE
:CREATE
: Criar objetos (incluindo tabelas) dentro deste esquemaUSAGE
: Lista objetos no esquema e acesse-os se suas permissões permitiremSe você não especificar o esquema para criar um objeto como uma tabela, o mecanismo de banco de dados utilizará o
search_path
e, por padrão, opublic
esquema será o primeirosearch_path
a ser criado para a tabela. Como todos têm direitospublic
por padrã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 de banco de dados, apenas um esquema dentro dele.Não importa que você não tenha concedido ao usuário outros direitos além da concessão
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 desejado.Se você deseja delegar todos os direitos explicitamente, revogue tudo de public, ou simplesmente elimine o esquema público. Você pode criar um novo banco de dados de modelos com essa alteração aplicada, se desejar. Como alternativa, você pode aplicá-lo
template1
, mas isso provavelmente quebrará muitos códigos de terceiros que supõem quepublic
exista e sejam graváveis.Isso pode fazer mais sentido se você olhar para 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
, porque não tenho permissão de gravação. Portanto, se eutouch /dir1/somefile
receber um erro de permissão negada.No entanto, eu faço tem permissão para olhar para dentro
/dir1
e para acesso continha arquivos e diretórios, inclusive/dir1/dir2
. Eu tenho permissão de gravaçãodir2
. Então,touch /dir1/dir2/somefile
terá sucesso , mesmo que eu não tenha permissão de gravaçãodir1
.A mesma coisa com bancos de dados e esquemas.
fonte
Se você deseja impedir apenas que novos usuários criem tabelas, execute 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 têm acesso.Como alternativa, você também pode
REVOKE CREATE
para um usuário específico:Veja também: Como criar um usuário somente leitura com o PostgreSQL .
fonte