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:
SELECT country, count(*) AS users_cnt
FROM users
GROUP BY country
ORDER BY users_cnt DESC;
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)
);
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.
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
USAGEsobre el esquema. Sin el, el rol no vera ni una sola tabla dentro depublic, aunque los permisos a nivel de tabla esten concedidos.GRANT USAGE ON SCHEMA public TO readonly;USAGEabre 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 TABLESlas 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 TABLESes una foto unica: concede permisos solo sobre las tablas que existen en ese momento. Creaemployeesmaniana 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 automaticamenteSELECTa nuestro rol.ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO readonly;El orden correcto es: primero
ALTER DEFAULT PRIVILEGESpara las tablas futuras, luegoGRANT ... ON ALL TABLESpara 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
SELECTsobre 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
USAGE ON SCHEMAaparte. Un rol de solo lectura se construye asi:GRANT SELECT ON shop.* TO 'readonly'@'%';. El patronshop.*cubre las tablas futuras de forma automatica, asi que no hace falta un equivalente deALTER DEFAULT PRIVILEGES.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,
USAGEsobre el esquema,SELECTsobre las tablas existentes yALTER DEFAULT PRIVILEGESpara las futuras. Saltate el ultimo paso y el acceso se rompera en silencio en la proxima migracion.