Como você cria um usuário somente leitura no PostgreSQL?

420

Eu gostaria de criar um usuário no PostgreSQL que só possa fazer SELECTs de um banco de dados específico. No MySQL, o comando seria:

GRANT SELECT ON mydb.* TO 'xxx'@'%' IDENTIFIED BY 'yyy';

Qual é o comando equivalente ou a série de comandos no PostgreSQL?

Eu tentei...

postgres=# CREATE ROLE xxx LOGIN PASSWORD 'yyy';
postgres=# GRANT SELECT ON DATABASE mydb TO xxx;

Mas parece que as únicas coisas que você pode conceder em um banco de dados são CREATE, CONNECT, TEMPORARY e TEMP.

Ethan
fonte

Respostas:

641

Conceder uso / selecionar a uma única tabela

Se você conceder apenas CONNECT a um banco de dados, o usuário poderá se conectar, mas não terá outros privilégios. Você deve conceder USAGE em namespaces (esquemas) e SELECT em tabelas e visualizações individualmente da seguinte forma:

GRANT CONNECT ON DATABASE mydb TO xxx;
-- This assumes you're actually connected to mydb..
GRANT USAGE ON SCHEMA public TO xxx;
GRANT SELECT ON mytable TO xxx;

Várias tabelas / visualizações (PostgreSQL 9.0+)

Nas versões mais recentes do PostgreSQL, você pode conceder permissões em todas as tabelas / visualizações / etc no esquema usando um único comando, em vez de digitá-las uma a uma:

GRANT SELECT ON ALL TABLES IN SCHEMA public TO xxx;

Isso afeta apenas tabelas que já foram criadas. Mais poderosamente, você pode automaticamente atribuir funções padrão a novos objetos no futuro:

ALTER DEFAULT PRIVILEGES IN SCHEMA public
   GRANT SELECT ON TABLES TO xxx;

Observe que, por padrão, isso afetará apenas objetos (tabelas) criados pelo usuário que emitiu este comando: embora também possa ser definido em qualquer função da qual o usuário emissor seja membro. No entanto, você não obtém privilégios padrão para todas as funções de que você é membro ao criar novos objetos ... então ainda há alguns problemas por aí. Se você adotar a abordagem de que um banco de dados tem uma função proprietária e as alterações de esquema são executadas como essa função proprietária, você deve atribuir privilégios padrão a essa função proprietária. IMHO, tudo isso é um pouco confuso e você pode precisar experimentar para criar um fluxo de trabalho funcional.

Várias tabelas / visualizações (versões do PostgreSQL anteriores à 9.0)

Para evitar erros em alterações longas e com várias tabelas, é recomendável usar o seguinte processo 'automático' para gerar o necessário GRANT SELECTpara cada tabela / exibição:

SELECT 'GRANT SELECT ON ' || relname || ' TO xxx;'
FROM pg_class JOIN pg_namespace ON pg_namespace.oid = pg_class.relnamespace
WHERE nspname = 'public' AND relkind IN ('r', 'v', 'S');

Isso deve gerar os comandos GRANT relevantes para GRANT SELECT em todas as tabelas, visualizações e sequências em público, para o amor de copiar e colar. Naturalmente, isso será aplicado apenas a tabelas que já foram criadas.

araqnid
fonte
22
Você deve colocar sua edição referente à PG9 no topo da postagem.
Danilo Bargen
5
Agradável. Uma coisa que eu acrescentaria é que você também pode precisar permitir que as sequências sejam lidas por esse usuário; so: GRANT SELECT EM TODAS AS SEQUÊNCIAS NO ESQUEMA public TO xxx;
JJC
26
Observe que, para impedir que esse usuário possa criar novas tabelas, eu precisava REVOKE CREATE ON SCHEMA public FROM PUBLIC;. Sem isso, o usuário "somente leitura" não pode modificar as tabelas existentes, mas pode criar novas tabelas no esquema e adicionar / remover dados dessas tabelas.
Ajedi32
3
@ Ajedi32 Isso deve fazer parte da resposta aceita! Obrigado
Asfand Qazi
12
Para os novatos como eu, acho que vale a pena mencionar que você deve iniciar o console usando psql mydboutras coisas que a maioria dessas manipulações não faria. Pessoalmente, levei um tempo considerável para descobrir sozinho. Espero que isso ajude alguém.
Anass
41

Observe que o PostgreSQL 9.0 (hoje em teste beta) terá uma maneira simples de fazer isso :

test=> GRANT SELECT ON ALL TABLES IN SCHEMA public TO joeuser;
bortzmeyer
fonte
3
Eu precisava estar no banco de dados específico para que isso funcionasse. Postgresql 9.5.
user1158559
8
Isso funciona apenas para tabelas existentes no esquema. Se o usuário escreve mais tarde cria ou substitui tabelas, o usuário somente leitura não terá acesso a eles
AnneB
33

Referência retirada deste blog:

Script para criar usuário somente leitura:

CREATE ROLE Read_Only_User WITH LOGIN PASSWORD 'Test1234' 
NOSUPERUSER INHERIT NOCREATEDB NOCREATEROLE NOREPLICATION VALID UNTIL 'infinity';

Atribua permissão a este usuário somente leitura:

GRANT CONNECT ON DATABASE YourDatabaseName TO Read_Only_User;
GRANT USAGE ON SCHEMA public TO Read_Only_User;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO Read_Only_User;
GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO Read_Only_User;

Atribua permissões para ler todas as novas tabelas criadas no futuro

ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO Read_Only_User;
Anvesh
fonte
6
Esta é uma resposta muito boa, exceto uma coisa que falta: o ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO Read_Only_User; que também permitiria ler todas as tabelas criadas no mesmo banco de dados no futuro.
Ravbaker 23/05
2
É incomum permitir que um usuário somente leitura acesse as seqüências. A leitura da sequência a atualiza e geralmente é necessária apenas para INSERTs.
Jpmc26 06/02/19
Para completar, possivelmente adicione: #GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA schema_name TO Read_Only_User;
Fabien Haddadi
@ jpmc26: isso significa que você recomenda GRANT ALL ON ALL SEQUENCES IN SCHEMA schema_name TO Read_Only_User:?
Fabien Haddadi
@FabienHaddadi Significa que, a menos que você tenha algum requisito fora do comum, não vejo necessidade de conceder permissões em sequências a um usuário somente leitura.
precisa saber é o seguinte
24

Aqui está a melhor maneira que eu encontrei para adicionar usuários somente leitura (usando o PostgreSQL 9.0 ou mais recente):

$ sudo -upostgres psql postgres
postgres=# CREATE ROLE readonly WITH LOGIN ENCRYPTED PASSWORD '<USE_A_NICE_STRONG_PASSWORD_PLEASE';
postgres=# GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;

Em seguida, efetue login em todas as máquinas relacionadas (master + read-slave (s) / hot-standby (s), etc.) e execute:

$ echo "hostssl <PUT_DBNAME_HERE> <PUT_READONLY_USERNAME_HERE> 0.0.0.0/0 md5" | sudo tee -a /etc/postgresql/9.2/main/pg_hba.conf
$ sudo service postgresql reload
Jay Taylor
fonte
2
Eu gosto da abordagem, mas também precisava CONCEDER CONNECT ON DATABASE [banco de dados] A [usuário ou função]; e CONCESSÃO DE USO NO ESQUEMA público a [usuário ou função];
31514 Ian McGregor #
1
O esquema público ainda permite que esse usuário crie tabelas. Além disso, novas tabelas não são cobertas, nem sequências. Infelizmente, tudo isso é um pouco mais complicado que isso. : - / Vou postar o que acabei fazendo depois de validar mais um pouco.
JJC
No script acima, você está tentando criar a função duas vezes. Eu suspeito que você pretendia usar "ALTER PAPEL ..." quando activar a função de login e configurar a senha
Bogdan
Se você já possui o usuário, depois de criar a função somente leitura e conceder permissões de seleção, conceda a nova função ao usuário: GRANT somente leitura para <USER>
gonz
18

Por padrão, novos usuários terão permissão para criar tabelas. Se você planeja criar um usuário somente leitura, provavelmente não é isso que você deseja.

Para criar um verdadeiro usuário somente leitura com o PostgreSQL 9.0+, execute as seguintes etapas:

# This will prevent default users from creating tables
REVOKE CREATE ON SCHEMA public FROM public;

# If you want to grant a write user permission to create tables
# note that superusers will always be able to create tables anyway
GRANT CREATE ON SCHEMA public to writeuser;

# Now create the read-only user
CREATE ROLE readonlyuser WITH LOGIN ENCRYPTED PASSWORD 'strongpassword';
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonlyuser;

Se o usuário somente leitura não tiver permissão para listar tabelas (ou seja, \dnão retorna resultados), provavelmente é porque você não tem USAGEpermissões para o esquema. USAGEé uma permissão que permite aos usuários realmente usar as permissões que foram atribuídas. Qual o sentido disso? Não tenho certeza. Consertar:

# You can either grant USAGE to everyone
GRANT USAGE ON SCHEMA public TO public;

# Or grant it just to your read only user
GRANT USAGE ON SCHEMA public TO readonlyuser;
Adrian Macneil
fonte
8

Eu criei um script conveniente para isso; pg_grant_read_to_db.sh . Esse script concede privilégios somente leitura a uma função especificada em todas as tabelas, visualizações e sequências em um esquema de banco de dados e os define como padrão.

Jakub Jirutka
fonte
4

Eu li através de todas as soluções possíveis, tudo bem, se você se lembrar de se conectar ao banco de dados antes de conceder as coisas;) De qualquer forma, obrigado por todas as outras soluções !!!

user@server:~$ sudo su - postgres

crie usuário psql:

postgres@server:~$ createuser --interactive 
Enter name of role to add: readonly
Shall the new role be a superuser? (y/n) n
Shall the new role be allowed to create databases? (y/n) n
Shall the new role be allowed to create more new roles? (y/n) n

inicie o psql cli e defina uma senha para o usuário criado:

postgres@server:~$ psql
psql (10.6 (Ubuntu 10.6-0ubuntu0.18.04.1), server 9.5.14)
Type "help" for help.

postgres=# alter user readonly with password 'readonly';
ALTER ROLE

conecte-se ao banco de dados de destino:

postgres=# \c target_database 
psql (10.6 (Ubuntu 10.6-0ubuntu0.18.04.1), server 9.5.14)
You are now connected to database "target_database" as user "postgres".

conceda todos os privilégios necessários:

target_database=# GRANT CONNECT ON DATABASE target_database TO readonly;
GRANT

target_database=# GRANT USAGE ON SCHEMA public TO readonly ;
GRANT

target_database=# GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly ;
GRANT

altere privilégios padrão para destinos db public shema:

target_database=# ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO readonly;
ALTER DEFAULT PRIVILEGES
thomi_ch
fonte
3

Se seu banco de dados estiver no esquema público, é fácil (isso pressupõe que você já criou o readonlyuser)

db=> GRANT SELECT ON ALL TABLES IN SCHEMA public to readonlyuser;
GRANT
db=> GRANT CONNECT ON DATABASE mydatabase to readonlyuser;
GRANT
db=> GRANT SELECT ON ALL SEQUENCES IN SCHEMA public to readonlyuser;
GRANT

Se seu banco de dados estiver usando customschema, execute o procedimento acima, mas adicione mais um comando:

db=> ALTER USER readonlyuser SET search_path=customschema, public;
ALTER ROLE
josephmisiti
fonte
1

A maneira não simples de fazer isso seria conceder a seleção em cada tabela do banco de dados:

postgres=# grant select on db_name.table_name to read_only_user;

Você pode automatizar isso gerando suas instruções de concessão a partir dos metadados do banco de dados.

Pablo Santa Cruz
fonte
1
CREATE USER username SUPERUSER  password 'userpass';
ALTER USER username set default_transaction_read_only = on;
Viktor Viktor
fonte
0

Retirado de um link publicado em resposta ao link despesz ' .

O Postgres 9.x parece ter a capacidade de fazer o que é solicitado. Consulte o parágrafo Conceder sobre objetos de banco de dados de:

http://www.postgresql.org/docs/current/interactive/sql-grant.html

Onde diz: "Também há uma opção para conceder privilégios em todos os objetos do mesmo tipo em um ou mais esquemas. Atualmente, essa funcionalidade é suportada apenas por tabelas, sequências e funções (mas observe que TODAS AS TABELAS são consideradas como exibições de exibição e tabelas estrangeiras) ".

Esta página também discute o uso de ROLEs e um PRIVILEGE chamado "ALL PRIVILEGES".

Também estão presentes informações sobre como as funcionalidades do GRANT se comparam aos padrões SQL.

Kbulgrien
fonte