Eu quero migrar um aplicativo bastante simples, interno e orientado a banco de dados do SQLite3 para o PostgreSQL 9.3 e apertar as permissões no banco de dados à medida que eu for.
O aplicativo atualmente 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 (criar novas tabelas, visualizações, gatilhos, etc).
Embora este aplicativo seja o único hospedado no servidor a princípio, prefiro assumir que ele pode ser hospedado em um servidor com outros bancos de dados no futuro, em vez de ter que embaralhar mais tarde se isso for necessário em o futuro.
Eu acho 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 usuário/privilégio. As referências são extensas 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 psql
como '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 eu não estou recebendo a semântica pretendida. Eu quero tê-lo configurado para que apenas as hostdb_admin
tabelas possam criar (e descartar e alterar); o hostdb_mgr
pode ler, inserir, atualizar e excluir em todas as tabelas por padrão; e hostdb_usr
só pode ler todas as tabelas (e visualizações).
Quando tentei isso, descobri que era capaz de criar tabelas hostdb
como qualquer um desses usuários; mas, para cada usuário, eu só poderia ler ou modificar tabelas criadas por esse usuário - a menos que eu use um GRANT
.
Eu estou supondo que há algo faltando entre CREATE DATABASE
e CREATE SCHEMA
, algo para aplicar SCHEMA
ao DATABASE
?
(À medida que as coisas ficarem mais avançadas, também terei perguntas para aplicar restrições semelhantes em TRIGGERS
, procedimentos armazenados VIEWS
e talvez outros objetos).
Onde posso encontrar um guia decente, tutorial ou série de vídeos sobre isso?
O Postgres 14 adiciona os papéis predefinidos
pg_read_all_data
epg_write_all_data
, que permitem atalhos para os propósitos implícitos nos nomes.Você encontrará tudo no manual. Links abaixo.
Concedido, o assunto não é trivial e às vezes confuso. Aqui está uma receita para o caso de uso:
Receita
Como superusuário
postgres
:Se você deseja um administrador mais poderoso que também possa gerenciar bancos de dados e funções, adicione os atributos de função
CREATEDB
eCREATEROLE
acima.Conceda cada função ao próximo nível superior, para que todos os níveis "herdem" pelo menos o conjunto de privilégios do próximo nível inferior (em cascata):
Estou nomeando o esquema
schma
(ohostdb
que não seria confuso). Escolha qualquer nome. Opcionalmente , torneschma_admin
o proprietário do esquema:Para
and drop and alter
ver notas abaixo.O Postgres 14 adiciona as funções pré-definidas, sem login
pg_read_all_data
epg_write_all_data
para fornecer acesso somente leitura/gravação a todos os objetos em todos os esquemas. Isso vai além do que está sendo perguntado aqui, mas pode ser útil. Ver:As vistas são especiais.
O manual:
E para visualizações atualizáveis :
Os gatilhos também são especiais. Você precisa do
TRIGGER
privilégio na mesa e:Anotações importantes
Propriedade
Se você deseja permitir
schma_admin
(sozinho) eliminar e alterar tabelas, faça com que a função possua todos os objetos. A documentação:Ou crie todos os objetos com a função
schma_admin
para começar, então você não precisa definir o proprietário explicitamente. Ele também simplifica os privilégios padrão, que você só precisa definir para uma função:Objetos pré-existentes
Os privilégios padrão se aplicam apenas a objetos recém-criados e apenas à função específica com a qual foram criados. Você também vai querer adaptar as permissões para objetos existentes :
O mesmo se aplica se você criar objetos com uma função que não tenha
DEFAULT PRIVILEGES
definido, como o superusuáriopostgres
. Reatribua a propriedadeschma_admin
e defina os privilégios manualmente - ou defina também (enquanto estiver conectado ao banco de dados correto!)DEFAULT PRIVILEGES
:postgres
Privilégios padrão
Você estava perdendo um aspecto importante do
ALTER DEFAULT PRIVILEGES
comando. Aplica-se à função atual, a menos que especificado de outra forma:Os privilégios padrão se aplicam apenas ao banco de dados atual. Assim você não mexe com outros bancos de dados no cluster de banco de dados. A documentação:
Você também pode querer definir privilégios padrão para
FUNCTIONS
eTYPES
(não apenasTABLES
eSEQUENCES
), mas esses podem não ser necessários.Privilégios padrão para
PUBLIC
Os privilégios padrão concedidos a
PUBLIC
são rudimentares e superestimados por alguns. A documentação:Minha ênfase em negrito. Normalmente, este comando (incluído na parte superior) é tudo o que você precisa:
Em particular, nenhum privilégio padrão é concedido
PUBLIC
para novos esquemas. Pode ser confuso que o esquema padrão chamado "public" comece comALL
privilégios paraPUBLIC
. Esse é apenas um recurso de conveniência para facilitar o início com bancos de dados recém-criados. Não afeta outros esquemas de forma alguma. Você pode revogar esses privilégios no banco de dadostemplate1
de modelo e todos os bancos de dados recém-criados neste cluster iniciarão sem eles:O privilégio
TEMP
Como revogamos todos os privilégios
hostdb
dePUBLIC
, usuários comuns não podem criar tabelas temporárias, a menos que permitamos explicitamente. Você pode ou não querer adicionar isso:search_path
Não se esqueça de definir o
search_path
. Se você tiver apenas um banco de dados no cluster, basta definir o padrão global empostgresql.conf
. Caso contrário (mais provável) defina-o como propriedade do banco de dados, ou apenas para funções envolvidas ou mesmo a combinação de ambos. Detalhes:Você pode querer configurá-lo
schma, public
se 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_path
menos que você altere isso. Lembre-se de revogar privilégios paraPUBLIC
neste caso.Relacionado