Para um servidor de produção, eu queria separar as funções de superusuário, administrador e aplicativo para limitar o escopo dos erros.
Então, criei uma conta que nosso aplicativo usa para acessar o banco de dados e uma conta de administrador. A conta admin também é usada para executar migrações para criar tabelas.
Achei que tinha resolvido todos os problemas, o usuário do aplicativo pode acessar todas as tabelas existentes (que foram criadas pelo superusuário), porém agora tendo executado uma migração que cria uma tabela, o aplicativo não tem acesso a essa tabela.
Os usuários receberam acesso com os seguintes comandos:
GRANT CREATE, CONNECT ON DATABASE test TO admin;
GRANT SELECT, INSERT, UPDATE, DELETE, REFERENCES ON ALL TABLES IN SCHEMA public
TO admin;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO admin;
GRANT CONNECT ON DATABASE test TO api;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public
TO api;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO api;
Então o usuário admin executou CREATE TABLE new_table;
e tentando acessar aquela tabela, o app ficapermission denied for relation new_table
1) Qual grant está faltando para permitir o acesso da api à nova tabela 2) Por curiosidade, se eu não tivesse um registro das grants anteriores, como eu examinaria as grants dos usuários e descobriria o privilégio que está faltando
ALL TABLES
/ALL SEQUENCES
nesse contexto significa todas as tabelas/sequências que existem agora , no momento em que a concessão é emitida. Não inclui tabelas/sequências criadas após a emissão da concessão.Sua primeira opção é incluir as concessões explicitamente nos scripts de migração. Toda vez que você criar uma tabela/sequência também emita as respectivas concessões para
api
.Ou você pode alterar os privilégios padrão. No Postgres podem ser armazenados privilégios padrão, que serão aplicados a um objeto recém-criado automaticamente. Você pode alterá-los com
ALTER DEFAULT PRIVILEGES
.No seu caso, provavelmente depois
e
Observe que os scripts de migração precisam ser executados no mesmo usuário, que fez isso
ALTER DEFAULT PRIVILEGES
para que eles entrem em vigor.Os privilégios sobre os objetos podem ser obtidos através da
pg_class
tabela de catálogo. Por exemplo, se você quisesse consultar todas as tabelas regulares no esquemapublic
, você poderia fazer:Para sequências o
relkind
éS
em vez der
, entãolhe daria as sequências em
public
.A coluna
relname
exibe o nome do objeto erelacl
contém uma matriz de privilégios no objeto na forma de um arquivoaclitem
. Uma ACL é representada por uma string no formato<grantee>=<privileges>/<grantor>
.<grantee>
pode ficar vazio se os privilégios forem concedidos a public.<privileges>
codifica os privilégios na forma de uma sequência de letras. No seu caso, você deseja verapi=arwd/admin
uma tabela regular eapi=rU/admin
sequências.a
é para "anexar" (INSERT
),r
para "ler" (SELECT
),w
para "escrever" (UPDATE
),d
paraDELETE
eU
paraUSAGE
.Mais detalhes sobre as ACLs podem ser encontrados no manual em
GRANT
A concessão explícita é mais "segura" no sentido de que você não "esquece" que os privilégios padrão estão em vigor um dia quando a criação de uma tabela
api
não deve ser acessada. Você teria que revogar explicitamente os privilégios após a criação do objeto nesse caso.O uso de privilégios padrão é mais conveniente, é claro.