sqlpostgresqlsecuritygrant

Rol de solo lectura en PostgreSQL: permisos correctos para analitica y BI

Como crear un rol de solo lectura para analistas: USAGE sobre el esquema, SELECT sobre las tablas y ALTER DEFAULT PRIVILEGES para las tablas futuras.

3 min de lecturaReferencesql · postgresql · security · grant · roles · bi

Los analistas y las herramientas de BI necesitan leer tus datos sin poder modificarlos. En PostgreSQL la respuesta limpia es un rol dedicado de solo lectura. Aqui tienes una receta que funciona y el error tipico con el que casi todos tropiezan.

Crear el rol y dar acceso al esquema

Un rol de solo lectura suele ser un rol de grupo (sin login) al que se aniaden los usuarios reales. Los privilegios viven en el grupo; tu solo agregas y quitas personas una a una.

CREATE ROLE readonly NOLOGIN;

CREATE ROLE analyst_anna LOGIN PASSWORD 'change_me';
GRANT readonly TO analyst_anna;

El primer paso poco evidente es USAGE sobre el esquema. Sin el, el rol no vera ni una sola tabla dentro de public, aunque los permisos a nivel de tabla esten concedidos.

GRANT USAGE ON SCHEMA public TO readonly;

USAGE abre el esquema para que su contenido sea visible, pero todavia no permite hacer nada con las tablas. Eso es el siguiente grant.

SELECT sobre las tablas existentes

Ahora concede acceso de lectura a todas las tablas que ya viven en el esquema. Un solo comando con ALL TABLES las cubre todas.

GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;

Despues de esto, el rol puede leer datos pero no puede escribir nada:

-- works for readonly
SELECT country, count(*) AS users_cnt
FROM users
GROUP BY country
ORDER BY users_cnt DESC;

-- fails: permission denied
UPDATE orders SET status = 'cancelled' WHERE amount < 0;

Si el esquema tiene secuencias que tus informes necesitan inspeccionar, concedelas por separado:

GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO readonly;

El error: las tablas nuevas no son legibles

Aqui es donde se rompe la mayoria de las configuraciones. GRANT ... ON ALL TABLES es una foto unica: concede permisos solo sobre las tablas que existen en ese momento. Crea employees maniana y el analista recibira un error de permisos.

CREATE TABLE employees (
  id         bigint PRIMARY KEY,
  name       text NOT NULL,
  manager_id bigint,
  dept       text,
  salary     numeric(12,2)
);

-- readonly gets: permission denied for table employees
SELECT dept, avg(salary) FROM employees GROUP BY dept;

La solucion es ALTER DEFAULT PRIVILEGES. Es una regla orientada al futuro: cualquier tabla creada de ahora en adelante concede automaticamente SELECT a nuestro rol.

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

Importante: los privilegios por defecto estan atados al rol que crea los objetos. La regla anterior se aplica a las tablas creadas por el rol actual. Si las migraciones corren como otro usuario (por ejemplo app_owner), definela de forma explicita: ALTER DEFAULT PRIVILEGES FOR ROLE app_owner IN SCHEMA public GRANT SELECT ON TABLES TO readonly;. De lo contrario las tablas nuevas vuelven a quedar fuera del acceso.

El orden correcto es: primero ALTER DEFAULT PRIVILEGES para las tablas futuras, luego GRANT ... ON ALL TABLES para las existentes. Juntos cubren pasado y futuro.

Acceso para analitica y BI

Las herramientas de BI (Metabase, Superset, Looker) se conectan con este rol y construyen dashboards sin problema; fisicamente no pueden escribir en la base de datos. Para limitar la carga, define un tiempo maximo por sentencia:

ALTER ROLE readonly SET statement_timeout = '30s';

Si el acceso debe ser parcial, no expongas las tablas crudas completas. Entrega una vista y concede SELECT sobre ella:

CREATE VIEW orders_public AS
SELECT id, user_id, amount, status, created_at
FROM orders
WHERE status <> 'fraud';

GRANT SELECT ON orders_public TO readonly;

Diferencias en otras bases de datos

  • MySQL: los esquemas y las bases de datos son lo mismo, asi que no hay un USAGE ON SCHEMA aparte. Un rol de solo lectura se construye asi: GRANT SELECT ON shop.* TO 'readonly'@'%';. El patron shop.* cubre las tablas futuras de forma automatica, asi que no hace falta un equivalente de ALTER DEFAULT PRIVILEGES.
  • ClickHouse: usa GRANT SELECT ON shop.* TO readonly;, mientras que las restricciones suelen expresarse mediante perfiles y cuotas (readonly = 1) en lugar de permisos por objeto.

Recuerda lo esencial: un rol de grupo sin login, USAGE sobre el esquema, SELECT sobre las tablas existentes y ALTER DEFAULT PRIVILEGES para las futuras. Saltate el ultimo paso y el acceso se rompera en silencio en la proxima migracion.

Practica con ejercicios reales

Resuelve ejercicios en el entrenador de SQL con corrección instantánea y pistas.

Abrir el entrenador