🧪 Taller de Laboratorio
vistas

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.

RC
Ing. Roy Carrasco
Facultad de Ingeniería de Sistemas · UAB

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.

📎 Prerrequisito

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.

⚠️ Todo vive en la memoria de esta pestaña

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.

La base de datos está vacía. Baja a "Prepara tu base de datos" para empezar.

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.

🧪 Escribe cualquier sentencia SQL
⚠️ Si te quedás "atascado" como otro rol

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):

Datos de partida
nombrepreciostock
Mesa100.0015
Silla40.005
Lámpara25.000
Estante80.008
Escritorio150.003
🏗️ Crea la tabla productos y carga las 5 filas
Confirma los datos

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.

Enunciado — 1.1

Crea un rol llamado lector, sin ninguna cláusula extra — todavía no puede conectarse a nada, ni tiene ningún permiso.

🗄️ Ejercicio 1.1 — CREATE ROLE lector
Enunciado — 1.2

Crea un segundo rol llamado editor, esta vez con WITH LOGIN PASSWORD '...' (cualquier contraseña que elijas).

🗄️ Ejercicio 1.2 — CREATE ROLE editor WITH LOGIN
Enunciado — 1.3

Confirma la diferencia entre ambos: SELECT rolname, rolcanlogin FROM pg_roles WHERE rolname IN ('lector', 'editor');

🗄️ Ejercicio 1.3 — Consultar pg_roles
Confirma los valores

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.

Enunciado — 2.1: antes de arreglarlo, comprobalo

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;.

🗄️ Ejercicio 2.1 — SET ROLE lector y un SELECT que falla
Error esperado

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.

Enunciado — 2.2

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;

🗄️ Ejercicio 2.2 — GRANT SELECT y comprobar que ahora funciona
Ahora sí, 5 filas

El mismo SELECT que falló en 2.1 ahora te devuelve las 5 filas de productos. Lo único que cambió fue el GRANT.

Enunciado — 2.3

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;

🗄️ Ejercicio 2.3 — INSERT como lector (debe fallar)
SELECT no incluye INSERT

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.

Enunciado — 3.1: dale INSERT a editor, y probalo

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;

🗄️ Ejercicio 3.1 — GRANT INSERT a editor, y el INSERT falla igual
Fijate bien el mensaje

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.

Enunciado — 3.2: el permiso que faltaba

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;

🗄️ Ejercicio 3.2 — GRANT sobre la secuencia, y el INSERT que ahora funciona
6 filas ahora

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.

Enunciado — 4.1

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;

🗄️ Ejercicio 4.1 — REVOKE SELECT y comprobar que vuelve a fallar
De vuelta al principio

El mismo error de 2.1, permission denied for table productosREVOKE 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.

Enunciado — 5.1

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;

🗄️ Ejercicio 5.1a — Ampliar permisos de editor y crear admins
Enunciado — 5.1b: probá admins sin darle ningún GRANT directo

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;

🗄️ Ejercicio 5.1b — admins usa permisos heredados de editor
Ambas funcionan

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.

Requisitos
  • 1. Crea una tabla nueva, log_accesos, con columnas id (clave primaria autoincremental), rol (texto) y fecha (con DEFAULT now()).
  • 2. Crea un rol nuevo, auditor, y otorgale SELECT, INSERT ON log_accesos — más el USAGE sobre su secuencia (repasá la sección 3 si no te acordás el nombre exacto: nombretabla_id_seq).
  • 3. Como auditor, insertá una fila en log_accesos con rol = 'auditor', y confirmá que SELECT * FROM log_accesos; funciona.
  • 4. Todavía como auditor, intentá SELECT * FROM productos;debería fallar, aunque auditor ya tenga permisos sobre otra tabla.
La idea central del reto

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.

🏆 Resuelve aquí el reto

Repaso

Preguntas cortas sobre lo que acabas de ejecutar en vivo. Tu progreso se guarda automáticamente en este navegador.

0 / 0
actividades correctas en toda la guía
Selección múltiple

En el ejercicio 2.1, el SELECT como lector falló antes de darle ningún GRANT. ¿Por qué exactamente?

Verdadero o falso

En el ejercicio 2.3, GRANT SELECT ON productos TO lector; (del ejercicio 2.2) también le permitió insertar filas nuevas.

Selección múltiple

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?

Selección múltiple

En el ejercicio 4.1, REVOKE SELECT ON productos FROM lector; ¿afectó de alguna forma los permisos de editor?

Selección múltiple

En el ejercicio 5.1b, admins pudo leer y modificar productos sin haber recibido nunca un GRANT directo sobre esa tabla. ¿Por qué?

Clasificación

Clasifica cada sentencia que usaste en este taller según a qué categoría pertenece.

CREATE ROLE admins;
GRANT SELECT ON productos TO lector;
REVOKE SELECT ON productos FROM lector;
GRANT editor TO admins;

Completar

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 .

Emparejamiento

Une cada término con lo que hizo en este taller.

Cheat Sheet del taller

FormaPara 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.