Roles y Permisos en Vivo
Otra vez PostgreSQL de verdad, compilado a WebAssembly, corriendo enteramente en tu navegador. Esta vez vas a crear tus propios roles, otorgarles y quitarles permisos con GRANT y REVOKE, y comprobar con tus propios ojos el error real de PostgreSQL —"permission denied"— cuando un rol intenta tocar algo que no le corresponde.
Bienvenido
Este taller es la práctica de laboratorio de roles, GRANT y REVOKE en PostgreSQL. No vuelve a explicar la teoría desde cero —asume que ya viste la guía— y en cambio te da un PostgreSQL real donde vas a crear roles, intentar cosas que van a fallar a propósito, y después corregirlas con el permiso correcto.
Si todavía no viste la teoría, repasa primero Seguridad: Roles, GRANT y REVOKE antes de continuar. Este taller usa una única tabla, productos, y una segunda tabla, log_accesos, que vas a crear en el reto final.
Esta página corre su propia base de datos, independiente de cualquier otro taller que hayas abierto antes. Existe solo mientras esta pestaña siga abierta: si recargas la página, la cierras, o navegas a otra guía, se pierde todo y hay que empezar de nuevo desde "Prepara tu base de datos". Si te equivocás y querés reiniciar sin recargar, usa el botón "Reiniciar base de datos" de abajo.
✍️ Lo escribís vos
Cada bloque parte vacío. El enunciado te dice qué tenés que lograr — el código SQL lo escribís de cero.
⛔ Algunos errores son a propósito
Varios ejercicios te piden intentar algo que debería fallar —eso confirma que el permiso todavía no existe. Es la mejor forma de comprobar que GRANT y REVOKE hacen lo que dicen.
🔁 Una misma sesión, distintas identidades
SET ROLE y RESET ROLE te dejan cambiar de identidad dentro de la misma conexión, sin cerrar nada — así podés comprobar en el momento qué puede y qué no puede hacer cada rol.
Zona de pruebas libres
Este bloque queda disponible durante toda la guía. Usalo en cualquier momento para probar una idea propia, revisar el estado de una tabla con SELECT * FROM tabla;, o comprobar con qué rol estás corriendo con SELECT current_user; — sin desordenar los bloques guiados.
Si en algún momento un bloque te da errores raros de permiso que no esperabas, probablemente quedaste con un SET ROLE activo de un ejercicio anterior. Ejecutá RESET ROLE; acá mismo para volver a tu identidad original antes de seguir.
Prepara tu base de datos
Escribe el CREATE TABLE y los INSERT para productos, con las columnas id, nombre, precio y stock. Cargale estas 5 filas exactas (los ejercicios de todo el taller asumen estos datos):
| nombre | precio | stock |
|---|---|---|
| Mesa | 100.00 | 15 |
| Silla | 40.00 | 5 |
| Lámpara | 25.00 | 0 |
| Estante | 80.00 | 8 |
| Escritorio | 150.00 | 3 |
El SELECT final debería mostrarte 5 filas, en el mismo orden de la tabla de arriba. Si algo no coincide, usa "🔄 Reiniciar base de datos" y volvé a intentar — el resto del taller asume exactamente estos precios y este stock.
1. Crea tus roles
Vas a necesitar dos roles a lo largo del taller: uno de solo lectura, y uno que además pueda escribir.
Crea un rol llamado lector, sin ninguna cláusula extra — todavía no puede conectarse a nada, ni tiene ningún permiso.
Crea un segundo rol llamado editor, esta vez con WITH LOGIN PASSWORD '...' (cualquier contraseña que elijas).
Confirma la diferencia entre ambos: SELECT rolname, rolcanlogin FROM pg_roles WHERE rolname IN ('lector', 'editor');
editor debería mostrar rolcanlogin = true; lector, false.
2. GRANT: dar permisos
Un rol recién creado no puede tocar ninguna tabla. Vas a comprobarlo primero, y después arreglarlo con GRANT.
Cambiá tu identidad a lector y probá leer productos: SET ROLE lector; seguido de SELECT * FROM productos; — debería fallar. Al final, volvé a tu identidad original con RESET ROLE;.
Deberías ver permission denied for table productos. No es un bug — es exactamente lo que tiene que pasar: lector todavía no tiene ningún permiso sobre esa tabla.
Otorgá el permiso de lectura: GRANT SELECT ON productos TO lector; Después repetí el mismo SET ROLE + SELECT del ejercicio anterior, y confirmá que ahora sí funciona. Terminá con RESET ROLE;
El mismo SELECT que falló en 2.1 ahora te devuelve las 5 filas de productos. Lo único que cambió fue el GRANT.
Todavía como lector, intentá insertar una fila nueva — debería fallar, porque solo le diste SELECT: SET ROLE lector; INSERT INTO productos (nombre, precio, stock) VALUES ('Ropero', 200, 2); RESET ROLE;
Otra vez permission denied for table productos — pero esta vez es un error distinto en el fondo: lector sí puede leer, pero INSERT es un privilegio aparte que nunca se le otorgó.
3. El detalle que todos olvidan la primera vez
GRANT INSERT no siempre alcanza para insertar — si la tabla tiene una columna SERIAL, hace falta un permiso más.
Otorgá GRANT INSERT ON productos TO editor;. Después, como editor, intentá INSERT INTO productos (nombre, precio, stock) VALUES ('Ropero', 200, 2); — debería fallar igual, con un mensaje distinto al de 2.3. Terminá con RESET ROLE;
Esta vez el error es permission denied for sequence productos_id_seq — no "for table". La columna id es SERIAL, y por dentro eso usa una secuencia aparte para generar cada número. INSERT sobre la tabla no alcanza: hace falta USAGE sobre esa secuencia también.
Otorgá GRANT USAGE, SELECT ON SEQUENCE productos_id_seq TO editor;. Repetí el mismo INSERT de 3.1 como editor — ahora sí debería funcionar. Terminá con RESET ROLE;
Confirmá con SELECT COUNT(*) FROM productos; en la zona de pruebas libres — debería mostrarte 6 (las 5 originales más "Ropero").
4. REVOKE: quitar permisos
GRANT y REVOKE son simétricos: lo que uno otorga, el otro lo retira, sin afectar a ningún otro rol.
Retirale a lector el permiso de lectura que le diste en 2.2: REVOKE SELECT ON productos FROM lector; Después, como lector, repetí el mismo SELECT * FROM productos; de siempre — debería volver a fallar. Terminá con RESET ROLE;
El mismo error de 2.1, permission denied for table productos — REVOKE deshizo exactamente lo que había hecho GRANT en 2.2, sin tocar los permisos de editor.
5. Membresía de roles
Un rol puede volverse miembro de otro y heredar automáticamente todos sus privilegios — sin repetir cada GRANT a mano.
Otorgale a editor también SELECT y UPDATE: GRANT SELECT, UPDATE ON productos TO editor; Creá un rol nuevo, admins, y hacelo miembro de editor: CREATE ROLE admins; GRANT editor TO admins;
Como admins, probá leer y modificar productos —sin haberle otorgado ningún permiso a admins directamente—: SET ROLE admins; SELECT nombre FROM productos ORDER BY id; UPDATE productos SET precio = 45 WHERE nombre = 'Silla'; RESET ROLE;
admins nunca recibió un GRANT directo sobre productos — pero como es miembro de editor, hereda automáticamente todo lo que editor tenga en cualquier momento. Confirmá el nuevo precio de Silla con SELECT nombre, precio FROM productos WHERE nombre = 'Silla'; en la zona de pruebas libres.
Reto final: un rol con acceso a una tabla, y a ninguna otra
Cierra el taller mostrando que los permisos son siempre por objeto: tener acceso a una tabla no da acceso a ninguna otra.
- 1. Crea una tabla nueva,
log_accesos, con columnasid(clave primaria autoincremental),rol(texto) yfecha(conDEFAULT now()). - 2. Crea un rol nuevo,
auditor, y otorgaleSELECT, INSERT ON log_accesos— más elUSAGEsobre su secuencia (repasá la sección 3 si no te acordás el nombre exacto:nombretabla_id_seq). - 3. Como
auditor, insertá una fila enlog_accesosconrol = 'auditor', y confirmá queSELECT * FROM log_accesos;funciona. - 4. Todavía como
auditor, intentáSELECT * FROM productos;— debería fallar, aunqueauditorya tenga permisos sobre otra tabla.
Que un rol tenga acceso a log_accesos no le da ningún acceso a productos —cada GRANT es específico de un objeto y un rol, nunca general. Esto es justamente lo que hace que el principio de mínimo privilegio sea posible: podés darle a auditor exactamente lo que necesita (su propia tabla de registro) sin abrirle ni una fila de las demás tablas de la base.
Repaso
Preguntas cortas sobre lo que acabas de ejecutar en vivo. Tu progreso se guarda automáticamente en este navegador.
En el ejercicio 2.1, el SELECT como lector falló antes de darle ningún GRANT. ¿Por qué exactamente?
En el ejercicio 2.3, GRANT SELECT ON productos TO lector; (del ejercicio 2.2) también le permitió insertar filas nuevas.
En el ejercicio 3.1, el error cambió de "permission denied for table productos" a "permission denied for sequence productos_id_seq". ¿Qué explica ese cambio?
En el ejercicio 4.1, REVOKE SELECT ON productos FROM lector; ¿afectó de alguna forma los permisos de editor?
En el ejercicio 5.1b, admins pudo leer y modificar productos sin haber recibido nunca un GRANT directo sobre esa tabla. ¿Por qué?
Clasifica cada sentencia que usaste en este taller según a qué categoría pertenece.
Sobre el reto final: auditor pudo leer y escribir log_accesos, pero no productos.
1. Eso pasa porque los privilegios de PostgreSQL son siempre .
2. Si mañana auditor también necesitara leer productos, habría que .
Une cada término con lo que hizo en este taller.
Cheat Sheet del taller
| Forma | Para qué sirve |
|---|---|
CREATE ROLE nombre; | Crea un rol sin ningún privilegio, ni siquiera de conexión. |
CREATE ROLE nombre WITH LOGIN PASSWORD '...'; | Crea un rol que puede conectarse directamente. |
GRANT privilegio ON tabla TO rol; | Otorga un permiso específico sobre un objeto. |
REVOKE privilegio ON tabla FROM rol; | Retira un permiso otorgado antes. |
GRANT USAGE, SELECT ON SEQUENCE tabla_id_seq TO rol; | Necesario además de INSERT, cuando la tabla usa una columna SERIAL. |
GRANT rol_a TO rol_b; | rol_b se vuelve miembro de rol_a y hereda todos sus privilegios. |
SET ROLE nombre; | Cambia la identidad efectiva de la sesión actual. |
RESET ROLE; | Vuelve al rol original de la sesión. |
SELECT rolname, rolcanlogin FROM pg_roles; | Lista todos los roles y sus atributos. |
¿Sabías que...?
🗂️ Tus roles son tuyos solos
Cada estudiante que abre este taller corre su propia base de datos en su propia pestaña. Los roles lector, editor y admins que creaste no existen en ningún otro navegador ni servidor — viven solo en la memoria de tu pestaña mientras esté abierta.
🔁 SET ROLE no es una nueva conexión
A diferencia de cerrar sesión y volver a conectarte con otro usuario, SET ROLE cambia la identidad dentro de la misma sesión ya abierta — por eso es tan rápido para comprobar permisos, uno detrás de otro, sin reabrir nada.
🧩 El error de la secuencia es un clásico real
"Permission denied for sequence" es uno de los errores de permisos más comunes en PostgreSQL real, precisamente porque no es intuitivo — GRANT INSERT ON tabla "se siente" suficiente, pero la secuencia detrás de una columna SERIAL es un objeto aparte con su propio dueño.