Como gerenciar privilégios padrão para usuários em um DATABASE vs SCHEMA?

48

Desejo migrar um aplicativo interno simples, orientado a banco de dados, do SQLite3 para o PostgreSQL 9.3 e aumentar as permissões no banco de dados à medida que for avançando.

Atualmente, o aplicativo consiste em um comando para atualizar os dados; e um para consultá-lo. Naturalmente, também precisarei manter o banco de dados de outras maneiras (crie novas tabelas, visualizações, gatilhos, etc.).

Embora esse aplicativo seja o único hospedado no servidor a princípio, eu preferiria assumir que ele pode estar hospedado em um servidor com outros bancos de dados no futuro, em vez de ter que embaralhar mais tarde, se necessário. o futuro.

Eu pensaria que esses seriam um conjunto de requisitos bastante comum, mas estou tendo problemas para encontrar um tutorial simples explicando como configurar um novo banco de dados no PostgreSQL, com esse tipo de separação de usuário / privilégio. As referências continuam extensivamente sobre grupos, usuários, funções, bancos de dados, esquemas e domínio; mas acho-os confusos.

Aqui está o que eu tentei até agora (de dentro psqlcomo 'postgres'):

CREATE DATABASE hostdb;
REVOKE ALL ON DATABASE hostdb FROM public;
\connect hostdb
CREATE SCHEMA hostdb;
CREATE USER hostdb_admin WITH PASSWORD 'youwish';
CREATE USER hostdb_mgr   WITH PASSWORD 'youwish2';
CREATE USER hostdb_usr WITH PASSWORD 'youwish3';

GRANT ALL PRIVILEGES ON DATABASE hostdb TO hostdb_admin;
GRANT CONNECT ON DATABASE hostdb TO hostdb_mgr, hostdb_usr;
ALTER DEFAULT PRIVILEGES IN SCHEMA hostdb GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO hostdb_mgr;
ALTER DEFAULT PRIVILEGES IN SCHEMA hostdb GRANT SELECT ON TABLES TO hostdb_usr;

Mas não estou obtendo a semântica pretendida. Eu quero tê-lo configurado para que apenas o hostdb_adminpossa criar (e soltar e alterar) tabelas; o hostdb_mgrpode ler, inserir, atualizar e excluir em todas as tabelas por padrão; e o hostdb_usrpode apenas ler todas as tabelas (e visualizações).

Quando tentei isso, descobri que era capaz de criar tabelas hostdbcomo qualquer um desses usuários; mas, para cada usuário, eu só podia ler ou modificar as tabelas criadas por esse usuário - a menos que eu use um explícito GRANT.

Eu estou supondo que há algo faltando entre CREATE DATABASEe CREATE SCHEMA, algo para aplicar SCHEMAao DATABASE?

(À medida que as coisas se tornam mais avançadas, também terei perguntas para aplicar restrições semelhantes TRIGGERS, procedimentos armazenados VIEWSe talvez outros objetos).

Onde posso encontrar um guia, tutorial ou série de vídeos decente sobre isso?

Jim Dennis
fonte
2
Eu acho que (pelo menos uma parte de) seu problema está no publicpseudorol. Pode ser considerado um papel do qual todos os outros papéis (usuário, grupo - todos são iguais) fazem parte. Tente remover os privilégios dele, por exemplo REVOKE CREATE ON SCHEMA hostdb FROM public,. A revogação de direitos no nível do banco de dados, como você fez, desativa apenas algumas permissões no nível do banco de dados, sem efeito em esquemas ou tabelas.
Dezso
@dezso: Pode haver um equívoco sobre os privilégios padrão dos esquemas. Apenas o esquema padrão publicacontece com privilégios para PUBLIC. Fora isso, não privilégios padrão para novos esquemas. Portanto, isso não afeta o caso de uso demonstrado. Veja o capítulo na minha resposta.
Erwin Brandstetter

Respostas:

86

Onde posso encontrar um guia, tutorial ou série de vídeos decente sobre isso?

Você encontrará tudo no manual. Links abaixo.
É verdade que o assunto não é trivial e, às vezes, confuso. Aqui está uma receita para o caso de uso:

Receita

Eu quero tê-lo configurado para que apenas o hostdb_adminpossa criar (e soltar e alterar) tabelas;
o hostdb_mgrpode ler, inserir, atualizar e excluir em todas as tabelas por padrão;
e o hostdb_usrpode apenas ler todas as tabelas (e visualizações).

Como superusuário postgres:

CREATE USER schma_admin WITH PASSWORD 'youwish';
-- CREATE USER schma_admin WITH PASSWORD 'youwish' CREATEDB CREATEROLE; -- see below
CREATE USER schma_mgr   WITH PASSWORD 'youwish2';
CREATE USER schma_usr   WITH PASSWORD 'youwish3';

Se você deseja um administrador mais poderoso que também possa gerenciar bancos de dados e funções, adicione os atributos de função CREATEDBeCREATEROLE acima.

Conceda cada função ao próximo nível superior, para que todos os níveis "herdam" pelo menos o conjunto de privilégios do próximo nível inferior (em cascata):

GRANT schma_usr TO schma_mgr;
GRANT schma_mgr TO schma_admin;

CREATE DATABASE hostdb;
REVOKE ALL ON DATABASE hostdb FROM public;  -- see notes below!

GRANT CONNECT ON DATABASE hostdb TO schma_usr;  -- others inherit

\connect hostdb  -- psql syntax

Estou nomeando o esquema schma(não o hostdbque seria confuso). Escolha qualquer nome. Opcionalmente, torne schma_admino proprietário do esquema:

CREATE SCHEMA schma AUTHORIZATION schma_admin;

SET search_path = schma;  -- see notes

ALTER ROLE schma_admin IN DATABASE hostdb SET search_path = schma; -- not inherited
ALTER ROLE schma_mgr   IN DATABASE hostdb SET search_path = schma;
ALTER ROLE schma_usr   IN DATABASE hostdb SET search_path = schma;

GRANT USAGE  ON SCHEMA schma TO schma_usr;
GRANT CREATE ON SCHEMA schma TO schma_admin;

ALTER DEFAULT PRIVILEGES FOR ROLE schma_admin
GRANT SELECT                           ON TABLES TO schma_usr;  -- only read

ALTER DEFAULT PRIVILEGES FOR ROLE schma_admin
GRANT INSERT, UPDATE, DELETE, TRUNCATE ON TABLES TO schma_mgr;  -- + write, TRUNCATE optional

ALTER DEFAULT PRIVILEGES FOR ROLE schma_admin
GRANT USAGE, SELECT, UPDATE ON SEQUENCES TO schma_mgr;  -- SELECT, UPDATE are optional 

Para and drop and alterver as notas abaixo.

À medida que as coisas se tornam mais avançadas, também terei perguntas para aplicar restrições semelhantes TRIGGERS, procedimentos armazenados VIEWSe talvez outros objetos.

As vistas são especiais. Para um:

... (mas note que ALL TABLESé considerado que inclui visualizações e tabelas estrangeiras).

E para visualizações atualizáveis :

Observe que o usuário que executa a inserção, atualização ou exclusão na exibição deve ter o privilégio correspondente de inserção, atualização ou exclusão na exibição. Além disso, o proprietário da exibição deve ter os privilégios relevantes nas relações de base subjacentes, mas o usuário que está executando a atualização não precisa de permissões nas relações de base subjacentes (consulte a Seção 38.5 ).

Os gatilhos também são especiais. Você precisa do TRIGGERprivilégio em cima da mesa e:

Mas já estamos expandindo demais o escopo desta pergunta ...

Anotações importantes

Propriedade

Se você deseja permitir schma_admin(sozinho) descartar e alterar tabelas, faça com que a função possua todos os objetos. A documentação:

O direito de descartar um objeto ou alterar sua definição de qualquer forma não é tratado como um privilégio concedido; é inerente ao proprietário e não pode ser concedido ou revogado. (No entanto, um efeito semelhante pode ser obtido concedendo ou revogando a participação na função que possui o objeto; veja abaixo.) O proprietário implicitamente também possui todas as opções de concessão para o objeto.

ALTER TABLE some_tbl OWNER TO schma_admin;

Ou crie todos os objetos com a funçãoschma_adminpara começar, para que você não precise definir explicitamente o proprietário. Ele também simplifica os privilégios padrão, que você só precisa definir para a única função:

Objetos pré-existentes

Os privilégios padrão se aplicam apenas aos objetos recém-criados e apenas à função específica com a qual eles são criados. Você também precisará adaptar permissões para objetos existentes :

O mesmo se aplica se você criar objetos com uma função que não foi DEFAULT PRIVILEGESdefinida, como o superusuário postgres. Propriedade Reassign para schma_admine privilégios definir manualmente - ou conjunto DEFAULT PRIVILEGESde postgresbem (enquanto conectado à DB certo!):

ALTER DEFAULT PRIVILEGES FOR ROLE postgres GRANT ...  -- etc.

Privilégios padrão

Você estava perdendo um aspecto importante do ALTER DEFAULT PRIVILEGEScomando. Aplica-se à função atual, a menos que seja especificado o contrário:

Os privilégios padrão se aplicam apenas ao banco de dados atual. Portanto, você não mexe com outros bancos de dados no cluster do banco de dados. A documentação:

para todos os objetos criados no banco de dados atual

Você também pode definir privilégios padrão para FUNCTIONSe TYPES(não apenas TABLESe SEQUENCES), mas esses podem não ser necessários.

Privilégios padrão para PUBLIC

Os privilégios padrão concedidos PUBLICsão rudimentares e superestimados por alguns. A documentação:

O PostgreSQL concede privilégios padrão em alguns tipos de objetos PUBLIC. Por padrão, não são concedidos privilégios PUBLICem tabelas, colunas, esquemas ou espaços de tabela. Para outros tipos, os privilégios padrão concedidos PUBLICsão os seguintes: CONNECTe CREATE TEMP TABLEpara bancos de dados; EXECUTEprivilégio para funções; e USAGE privilégio para idiomas.

Negrito ênfase minha. normalmente o único comando acima é suficiente para cobrir tudo:

REVOKE ALL ON DATABASE hostdb FROM public;

Em particular, nenhum privilégio padrão é concedido PUBLICpara novos esquemas. Pode ser confuso que o esquema padrão chamado "public" comece com ALLprivilégios para PUBLIC. Esse é apenas um recurso de conveniência para facilitar o início dos bancos de dados recém-criados. Não afeta outros esquemas de nenhuma maneira. Você pode revogar esses privilégios no banco de dados de modelos template1, e todos os bancos de dados criados recentemente neste cluster são iniciados sem eles:

\connect template1
REVOKE ALL ON SCHEMA public FROM public;

O privilégio TEMP

Como revogamos todos os privilégios hostdbde PUBLIC, usuários comuns não podem criar tabelas temporárias a menos que permitamos explicitamente. Você pode ou não querer adicionar isso:

GRANT TEMP ON DATABASE hostdb TO schma_mgr;

search_path

Não se esqueça de definir o search_path. Se você tiver apenas um banco de dados no cluster, poderá definir o padrão global em postgresql.conf. Caso contrário (mais provável), defina-a como propriedade do banco de dados, ou apenas para funções envolvidas ou mesmo a combinação de ambas. Detalhes:

Convém defini-lo como schma, publicse você usar o esquema público também, ou mesmo (menos provável) $user, schma, public...

Uma alternativa seria usar o esquema padrão "público", que deve funcionar com as configurações padrão, a search_pathmenos que você o tenha alterado. Lembre-se de revogar privilégios PUBLICneste caso.

Relacionado

Erwin Brandstetter
fonte
Eu estava procurando como adicionar privilégios de administrador padrão ao superusuário recém-criado, então não precisaria dar a ele direito adicional em todas as tabelas. E eu encontrei isso. E thisse parece com instruções para a nave espacial ...
Denis Matafonov
@DenisMatafonov: Os superusuários têm todos os privilégios automaticamente. Sugiro que você inicie uma nova pergunta com detalhes do seu caso. Comentários não são o lugar. Você sempre pode vincular perguntas / respostas relacionadas ao contexto.
Erwin Brandstetter
Sim, os superusuários têm todo o acesso, mas você não pode generalizar seus privilégios padrão. Seria muito bom definir privilégios padrão para uma função em um esquema e aplicar esses padrões a todos os membros da função à medida que eles criam tabelas no esquema. Por exemplo, para dizer "verifique se todas as tabelas criadas neste esquema por alguém da equipe de engenharia serão legíveis por qualquer pessoa da equipe de relatórios". Em resumo, quero que os membros de uma função de criação de tabela herdem seus privilégios padrão.
combinatorist