PostgreSQL: Usuários, Roles e Gerenciamento de Privilégios…
Última atualização: 2026-08-26
1. O Que Você Vai Aprender
- CREATE ROLE / CREATE USER (no PG, USER = uma role com LOGIN)
- Gerenciamento de privilégios GRANT / REVOKE
- Hierarquia de privilégios: banco de dados / esquema / tabela / coluna / função / sequence
- DEFAULT PRIVILEGES
- Políticas de Segurança em Nível de Linha (RLS / Row Security Policies, recurso do PG)
- Controle de privilégios de SCHEMA
- Herança de roles (INHERIT / NOINHERIT)
- Views de sistema: pg_roles / pg_auth_members
2. A História
Charlie é o DBA de uma plataforma SaaS de e-commerce e precisa configurar privilégios de banco de dados para 5 equipes:
| Equipe | Privilégios necessários |
|---|---|
| dev (desenvolvimento) | Leitura/escrita em todas as tabelas de negócio, criar tabelas de teste |
| analytics (analítica) | Somente leitura em todas as tabelas de negócio, criar views materializadas |
| ops (operações) | Gerenciar usuários, monitorar o banco de dados |
| audit (auditoria) | Ler apenas logs de auditoria, não dados de negócio |
| app (serviço de aplicação) | Leitura/escrita em tabelas de negócio, sem DDL |
Charlie usa herança de roles e RLS para implementar o princípio do menor privilégio.
3. Conceito: Roles e Usuários
(1) CREATE ROLE vs CREATE USER
| Comando | Privilégio LOGIN | Forma equivalente |
|---|---|---|
CREATE ROLE r1; |
Nenhum (não pode fazer login) | — |
CREATE USER u1; |
Sim (pode fazer login) | CREATE ROLE u1 LOGIN; |
No PG, usuários e roles são o mesmo conceito; USER é apenas uma ROLE com o atributo LOGIN.
(2) Atributos de Role em Resumo
| Atributo | Descrição | Sintaxe de criação |
|---|---|---|
| LOGIN | Permitir conexão ao banco de dados | LOGIN / NOLOGIN |
| SUPERUSER | Superusuário, ignora todos os privilégios | SUPERUSER |
| CREATEDB | Pode criar bancos de dados | CREATEDB |
| CREATEROLE | Pode criar/gerenciar roles | CREATEROLE |
| INHERIT | Herda automaticamente privilégios das roles possuídas | INHERIT (padrão) |
| NOINHERIT | Não herda automaticamente; precisa de SET ROLE | NOINHERIT |
| PASSWORD | Definir senha | PASSWORD 'xxx' |
| VALID UNTIL | Data de expiração da senha | VALID UNTIL 'timestamp' |
▶ Exemplo: Criar Roles e Usuários
-- Roles de grupo (não podem fazer login)
CREATE ROLE dev_team NOINHERIT;
CREATE ROLE analytics_team NOINHERIT;
CREATE ROLE ops_team NOINHERIT;
CREATE ROLE audit_team NOINHERIT;
-- Usuários de login
-- ⚠️ Não codifique senhas em produção; use variáveis de ambiente ou um gerenciador de segredos
CREATE USER alice_dev PASSWORD 'SecureP@ss1' IN ROLE dev_team;
CREATE USER bob_dev PASSWORD 'SecureP@ss2' IN ROLE dev_team;
CREATE USER charlie_analyst PASSWORD 'SecureP@ss3' IN ROLE analytics_team;
CREATE USER diana_ops PASSWORD 'SecureP@ss4' IN ROLE ops_team INHERIT;
Output:
CREATE TABLE
▶ Exemplo: Modificar Atributos de Role
-- Adicionar privilégio CREATEDB ao líder de operações
ALTER ROLE diana_ops CREATEDB;
-- Definir expiração de senha
ALTER ROLE charlie_analyst VALID UNTIL '2025-12-31';
-- Renomear uma role
ALTER ROLE dev_team RENAME TO engineering_team;
-- Desabilitar login temporariamente
ALTER ROLE bob_dev NOLOGIN;
Output:
CREATE TABLE
4. Conceito: Privilégios GRANT / REVOKE
(1) Hierarquia de Privilégios
flowchart TD
A[Banco de Dados<br/>CONNECT / CREATE / TEMP] --> B[Esquema<br/>CREATE / USAGE]
B --> C[Tabela<br/>SELECT / INSERT / UPDATE / DELETE / TRUNCATE / REFERENCES / TRIGGER]
C --> D[Coluna<br/>SELECT / INSERT / UPDATE / REFERENCES]
B --> E[Função<br/>EXECUTE]
B --> F[Sequence<br/>USAGE / SELECT / UPDATE]
A --> G[Role<br/>MEMBER / SET]
style A fill:#e1f5fe
style B fill:#bbdefb
style C fill:#c8e6c9
style D fill:#fff9c4
(2) Palavras-Chave de Privilégios Comuns
| Objeto | Privilégios concedíveis | Descrição |
|---|---|---|
| DATABASE | CONNECT, CREATE, TEMP | Conectar, criar esquema, tabelas temporárias |
| SCHEMA | CREATE, USAGE | Criar objetos, acessar objetos |
| TABLE | SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER | CRUD completo + referência de chave estrangeira |
| COLUMN | SELECT, INSERT, UPDATE, REFERENCES | Controle em nível de coluna |
| FUNCTION | EXECUTE | Chamar função |
| SEQUENCE | USAGE, SELECT, UPDATE | Usar sequence |
▶ Exemplo: GRANT de Privilégios em Nível de Tabela
-- Equipe dev: CRUD completo nas tabelas de negócio
GRANT SELECT, INSERT, UPDATE, DELETE ON products TO dev_team;
GRANT SELECT, INSERT, UPDATE, DELETE ON orders TO dev_team;
GRANT SELECT, INSERT, UPDATE, DELETE ON customers TO dev_team;
GRANT SELECT, INSERT, UPDATE, DELETE ON order_items TO dev_team;
-- Equipe analytics: somente leitura
GRANT SELECT ON products TO analytics_team;
GRANT SELECT ON orders TO analytics_team;
GRANT SELECT ON customers TO analytics_team;
-- Equipe audit: apenas logs de auditoria
GRANT SELECT ON price_audit_log TO audit_team;
GRANT SELECT ON ddl_audit_log TO audit_team;
Output:
INSERT 0 1
▶ Exemplo: GRANT de Privilégios de Esquema e Banco de Dados
-- Equipe dev pode criar objetos no esquema dev
GRANT CREATE, USAGE ON SCHEMA dev TO dev_team;
-- Equipe analytics pode usar mas não criar no esquema public
GRANT USAGE ON SCHEMA public TO analytics_team;
-- Permitir analytics criar views materializadas em seu próprio esquema
GRANT CREATE, USAGE ON SCHEMA analytics TO analytics_team;
-- Serviço de aplicação conecta ao banco de dados
GRANT CONNECT ON DATABASE shop_db TO app_service;
Output:
CREATE TABLE
▶ Exemplo: REVOKE de Privilégios
-- Revogar DELETE da equipe dev em products
REVOKE DELETE ON products FROM dev_team;
-- Revogar todos os privilégios em uma tabela
REVOKE ALL PRIVILEGES ON orders FROM public;
-- Revogar direito de criação de esquema
REVOKE CREATE ON SCHEMA dev FROM dev_team;
-- Cascata: revogar e concessões dependentes
REVOKE SELECT ON products FROM analytics_team CASCADE;
Output:
DELETE 2
(3) GRANT ALL e GRANT SELECT ALL TABLES
| Comando | Efeito |
|---|---|
GRANT ALL ON t TO r; |
Conceder todos os privilégios na tabela t |
GRANT ALL ON SCHEMA s TO r; |
Conceder todos os privilégios no esquema s |
GRANT SELECT ON ALL TABLES IN SCHEMA s TO r; |
Conceder SELECT em todas as tabelas no esquema s |
GRANT USAGE ON ALL SEQUENCES IN SCHEMA s TO r; |
Conceder USAGE em todas as sequences |
5. Conceito: DEFAULT PRIVILEGES
(1) Por que Privilégios Padrão São Necessários
Um GRANT simples afeta apenas objetos já existentes. Tabelas criadas no futuro não receberão privilégios automaticamente. DEFAULT PRIVILEGES resolve isso.
| Comando | Efeito |
|---|---|
ALTER DEFAULT PRIVILEGES IN SCHEMA s GRANT SELECT ON TABLES TO r; |
Novas tabelas em s recebem concessão automática |
ALTER DEFAULT PRIVILEGES FOR ROLE owner GRANT ... |
Privilégios padrão para um criador específico |
▶ Exemplo: Definir Privilégios Padrão
-- Todas as tabelas futuras no esquema public são legíveis por analytics_team
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT ON TABLES TO analytics_team;
-- Todas as tabelas futuras criadas por app_service são graváveis por dev_team
ALTER DEFAULT PRIVILEGES FOR ROLE app_service IN SCHEMA public
GRANT SELECT, INSERT, UPDATE ON TABLES TO dev_team;
-- Todas as sequences futuras no esquema public
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT USAGE, SELECT ON SEQUENCES TO dev_team;
-- Todas as funções futuras
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT EXECUTE ON FUNCTIONS TO analytics_team;
Output:
INSERT 0 1
▶ Exemplo: Visualizar Privilégios Padrão Atuais
SELECT
pg_get_userbyid(defaclrole) AS grantor,
pg_get_userbyid(defaclnamespace) AS namespace_owner,
n.nspname AS schema,
defaclobjtype AS object_type,
defaclacl AS acl
FROM pg_default_acl d
JOIN pg_namespace n ON n.oid = d.defaclnamespace;
Output:
id | name | value
----+----------+-------
1 | example | 42
(1 row)
6. Conceito: Políticas de Segurança em Nível de Linha (RLS)
(1) Como o RLS Funciona (Recurso do PG)
RLS permite controlar o acesso a dados no nível da linha—diferentes roles veem linhas diferentes na mesma tabela.
| Passo | Comando | Descrição |
|---|---|---|
| 1. Habilitar RLS | ALTER TABLE t ENABLE ROW LEVEL SECURITY; |
Habilitar segurança em nível de linha na tabela |
| 2. Criar política | CREATE POLICY ... ON t ...; |
Definir a regra de nível de linha |
| 3. SUPERUSER ignora | — | SUPERUSER não está sujeito a RLS por padrão |
| 4. Proprietário da tabela ignora | — | O proprietário da tabela não está sujeito por padrão; use FORCE para impor |
(2) Tipos de Política
| Tipo de política | Palavra-chave | Descrição |
|---|---|---|
| SELECT | FOR SELECT |
Controla linhas visíveis |
| INSERT | FOR INSERT |
Controla linhas inseríveis |
| UPDATE | FOR UPDATE |
Controla linhas atualizáveis (inclui BEFORE/AFTER) |
| DELETE | FOR DELETE |
Controla linhas excluíveis |
| ALL | FOR ALL |
Compartilhado em todas as operações |
▶ Exemplo: Habilitar RLS e Criar uma Política
-- Habilitar RLS na tabela orders
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
-- Analistas só podem ver pedidos concluídos
CREATE POLICY pol_analytics_completed
ON orders FOR SELECT
TO analytics_team
USING (order_status = 'completed');
-- Equipe dev pode ver todas as linhas
CREATE POLICY pol_dev_all
ON orders FOR ALL
TO dev_team
USING (true)
WITH CHECK (true);
Output:
CREATE TABLE
▶ Exemplo: RLS Baseado no Usuário Atual
-- Habilitar RLS na tabela customers
ALTER TABLE customers ENABLE ROW LEVEL SECURITY;
-- Cada usuário de atendimento vê apenas sua região atribuída
CREATE POLICY pol_region_access
ON customers FOR SELECT
USING (region = current_setting('app.region', true));
-- Forçar o proprietário da tabela a também cumprir RLS
ALTER TABLE orders FORCE ROW LEVEL SECURITY;
Output:
CREATE TABLE
▶ Exemplo: WITH CHECK para INSERT/UPDATE
-- Equipe de vendas só pode inserir pedidos em sua região
CREATE POLICY pol_sales_insert
ON orders FOR INSERT
TO dev_team
WITH CHECK (region = current_setting('app.region', true));
-- Equipe de vendas só pode atualizar pedidos em sua região
CREATE POLICY pol_sales_update
ON orders FOR UPDATE
TO dev_team
USING (region = current_setting('app.region', true))
WITH CHECK (region = current_setting('app.region', true));
Output:
INSERT 0 1
(3) USING vs WITH CHECK
| Cláusula | Papel | Aplica-se a |
|---|---|---|
| USING | Filtra linhas visíveis (o WHERE de SELECT/UPDATE/DELETE) | SELECT/UPDATE/DELETE |
| WITH CHECK | Valida se a nova linha é permitida (novos valores de INSERT/UPDATE) | INSERT/UPDATE |
7. Conceito: Herança de Roles e Views de Sistema
(1) INHERIT vs NOINHERIT
| Atributo | Comportamento | Cenário |
|---|---|---|
| INHERIT (padrão) | Obtém automaticamente privilégios das roles possuídas | Usuários regulares |
| NOINHERIT | Precisa de SET ROLE r para usar privilégios |
Elevação temporária de privilégio, separação de auditoria |
▶ Exemplo: NOINHERIT e SET ROLE
-- Criar uma role poderosa com NOINHERIT
CREATE ROLE admin_role NOINHERIT;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO admin_role;
-- Diana está em admin_role mas não pode usar privilégios de admin automaticamente
CREATE USER diana PASSWORD 'SecureP@ss5' IN ROLE admin_role NOINHERIT;
-- Diana deve alternar explicitamente para usar direitos de admin
SET ROLE admin_role;
-- Agora diana pode realizar operações de admin
RESET ROLE;
-- De volta aos privilégios normais
Output:
CREATE TABLE
(2) Views de Sistema
| View | Conteúdo |
|---|---|
pg_roles |
Todas as roles e seus atributos |
pg_auth_members |
Relacionamentos role–membro |
information_schema.role_table_grants |
Privilégios em nível de tabela |
information_schema.role_usage_grants |
Privilégios de esquema/função |
▶ Exemplo: Consultar Roles e Privilégios
-- Listar todas as roles e seus atributos
SELECT rolname, rolsuper, rolcreatedb, rolcanlogin, rolinherit
FROM pg_roles
WHERE rolname NOT LIKE 'pg_%'
ORDER BY rolname;
-- Listar associação de roles
SELECT
r1.rolname AS member,
r2.rolname AS role
FROM pg_auth_members m
JOIN pg_roles r1 ON r1.oid = m.member
JOIN pg_roles r2 ON r2.oid = m.roleid
ORDER BY r2.rolname, r1.rolname;
-- Verificar privilégios de tabela para uma role
SELECT table_name, privilege_type
FROM information_schema.role_table_grants
WHERE grantee = 'analytics_team'
ORDER BY table_name, privilege_type;
Output:
CREATE TABLE
8. Fluxograma: Decisão de Configuração de Privilégios
flowchart TD
A[Configurar privilégios] --> B{Precisa de controle em nível de linha?}
B -->|Sim| C[Habilitar RLS<br/>CREATE POLICY]
B -->|Não| D{Granularidade do privilégio?}
D -->|Tabela inteira| E[GRANT ON TABLE]
D -->|Coluna específica| F[GRANT nome_coluna ON TABLE]
D -->|Todas as tabelas no esquema| G[GRANT ALL TABLES IN SCHEMA]
E --> H{Precisa de concessão automática em novas tabelas?}
G --> H
H -->|Sim| I[ALTER DEFAULT PRIVILEGES]
H -->|Não| J[GRANT manual]
C --> K{Precisa restringir o proprietário da tabela também?}
K -->|Sim| L[FORCE ROW LEVEL SECURITY]
K -->|Não| M[Proprietário ignora RLS por padrão]
I --> N{Usuário precisa de elevação temporária?}
J --> N
N -->|Sim| O[NOINHERIT + SET ROLE]
N -->|Não| P[INHERIT por padrão]
style C fill:#fff9c4
style I fill:#c8e6c9
style O fill:#ffcdd2
9. Exemplo Completo
Charlie configura um sistema de privilégios completo para as 5 equipes:
-- Passo 1: Criar roles de grupo
CREATE ROLE dev_team NOINHERIT;
CREATE ROLE analytics_team NOINHERIT;
CREATE ROLE ops_team INHERIT;
CREATE ROLE audit_team NOINHERIT;
CREATE ROLE app_service LOGIN PASSWORD 'AppSecRet!';
-- Passo 2: Conceder permissões de esquema
GRANT CREATE, USAGE ON SCHEMA public TO dev_team;
GRANT USAGE ON SCHEMA public TO analytics_team;
GRANT CREATE, USAGE ON SCHEMA analytics TO analytics_team;
GRANT USAGE ON SCHEMA public TO ops_team;
GRANT USAGE ON SCHEMA audit TO audit_team;
-- Passo 3: Conceder permissões de tabela
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO dev_team;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO analytics_team;
GRANT SELECT ON ALL TABLES IN SCHEMA audit TO audit_team;
GRANT SELECT, INSERT, UPDATE, DELETE ON products, orders, order_items, customers TO app_service;
-- Passo 4: Privilégios padrão para tabelas futuras
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT ON TABLES TO analytics_team;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO dev_team;
ALTER DEFAULT PRIVILEGES IN SCHEMA audit
GRANT SELECT ON TABLES TO audit_team;
-- Passo 5: Permissões de sequence e função
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO dev_team;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO app_service;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT USAGE, SELECT ON SEQUENCES TO dev_team;
-- Passo 6: RLS - analistas só veem pedidos concluídos
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
CREATE POLICY pol_analytics_orders
ON orders FOR SELECT
TO analytics_team
USING (order_status = 'completed');
-- Passo 7: RLS - equipe de auditoria só vê o esquema audit
ALTER TABLE price_audit_log ENABLE ROW LEVEL SECURITY;
CREATE POLICY pol_audit_read
ON price_audit_log FOR SELECT
TO audit_team
USING (true);
-- Passo 8: Criar usuários de login e atribuir roles
CREATE USER alice_dev PASSWORD 'DevP@ss1' IN ROLE dev_team;
CREATE USER bob_dev PASSWORD 'DevP@ss2' IN ROLE dev_team;
CREATE USER charlie_analyst PASSWORD 'AnlP@ss3' IN ROLE analytics_team;
CREATE USER diana_ops PASSWORD 'OpsP@ss4' IN ROLE ops_team CREATEROLE;
CREATE USER eve_audit PASSWORD 'AudP@ss5' IN ROLE audit_team;
❓ Perguntas Frequentes
P: Qual a diferença entre CREATE USER e CREATE ROLE? R: CREATE USER é equivalente a CREATE ROLE ... LOGIN. No PG, usuários e roles são o mesmo conceito; USER é apenas uma role que carrega o atributo LOGIN por padrão.
P: GRANT SELECT ON ALL TABLES inclui tabelas criadas no futuro? R: Não. ALL TABLES concede apenas para tabelas atualmente existentes. Tabelas futuras precisam de ALTER DEFAULT PRIVILEGES para concessão automática ou um GRANT manual.
P: RLS afeta superusuários? R: Não por padrão. SUPERUSER ignora todas as políticas RLS. Para forçar, use ALTER TABLE ... FORCE ROW LEVEL SECURITY, mas isso só se aplica ao proprietário da tabela—SUPERUSER ainda ignora.
P: Como uma role NOINHERIT obtém privilégios temporariamente? R: Use SET ROLE role_alvo para alternar para a role alvo e obter seus privilégios; após terminar, RESET ROLE restaura os privilégios originais. SET ROLE afeta apenas a sessão atual.
P: REVOKE precisa de CASCADE? R: Se o privilégio revogado foi por sua vez concedido a outra role (uma concessão dependente), você precisa de CASCADE para revogar tudo de uma vez. O RESTRICT padrão gerará erro quando houver dependência.
P: Como visualizar quais privilégios um usuário realmente tem? R: Consulte a view information_schema.role_table_grants ou use os comandos
\dpe\du+do psql. Note que roles INHERIT obtêm automaticamente os privilégios das roles às quais pertencem.
P: USING e WITH CHECK do RLS podem ser escritos separadamente? R: Sim. Se apenas USING for escrito, WITH CHECK assume o mesmo valor de USING. Para uma política ALL, recomenda-se escrever ambos explicitamente para tornar o controle claro.
P: E se USAGE em um esquema não for suficiente para acessar uma tabela? R: USAGE apenas permite "entrar" no esquema e ver a lista de objetos; você também precisa de um privilégio como SELECT na tabela específica. Ambas as camadas de privilégio devem ser satisfeitas.
📖 Resumo
- No PG, USER = LOGIN ROLE; a role é a unidade central de gerenciamento de privilégios
- Atributos de role: LOGIN/SUPERUSER/CREATEDB/CREATEROLE/INHERIT controlam diferentes capacidades
- GRANT/REVOKE gerenciam privilégios; a hierarquia é: banco de dados → esquema → tabela → coluna
- DEFAULT PRIVILEGES resolve o problema de concessão automática para objetos recém-criados
- RLS (recurso do PG) implementa controle de acesso em nível de linha; USING filtra linhas visíveis, WITH CHECK valida novas linhas
- INHERIT herda privilégios automaticamente; NOINHERIT precisa de SET ROLE para elevação temporária
- pg_roles / pg_auth_members / views information_schema consultam a configuração de privilégios
- Princípio do menor privilégio: conceda sob demanda, evite excesso de privilégios
📝 Exercícios
-
⭐ Crie uma role
readonlye um usuárioreport_user, conceda areadonlySELECT em todas as tabelas no esquema public e defina privilégios padrão para que tabelas recém-criadas também recebam concessão automática. -
⭐⭐ Habilite RLS na tabela
orderse crie políticas:sales_teamsó pode ver pedidos em sua própria região (region = current_setting('app.region'));audit_teamsó pode ver pedidos comorder_status = 'completed'. -
⭐⭐⭐ Projete um sistema de privilégios completo: crie 3 roles de grupo (
backend_dev,data_analyst,db_admin), concedendo a cada uma diferentes níveis de privilégio (esquema/tabela/coluna/função/sequence), configure DEFAULT PRIVILEGES, conceda a colunasalaryseparadamente (analista não pode vê-la) e usepg_roleseinformation_schemapara consultar e verificar o resultado da configuração.