Seguridad a nivel de fila RLS en PostgreSQL

La seguridad a nivel de fila (RLS) en PostgreSQL o también conocido como Row Level Security, es una característica avanzada de seguridad de esta herramienta que permite determinar que usuario o grupo de usuarios pueden ver cada una de las filas de una tabla en base a un criterio.

Especificaciones del entorno

  • Windows 10
  • PostgreSQL 13 (pgAdmin 4.26)

Preparación del ejemplo

Lo más habitual sería aplicar este tipo de seguridad a nivel de grupo de usuarios, pero para poder explicar esta funcionalidad de forma sencilla y rapida lo haré a nivel de usuario. Voy a crear tres usuarios llamados Ismael, Jesús y Pilar y una tabla llamada Coches insertando varios datos de ejemplo.

CREATE USER ismael NOSUPERUSER;
CREATE USER jesus NOSUPERUSER;
CREATE USER pilar NOSUPERUSER;
 
CREATE TABLE coches (marca text, modelo text);
INSERT INTO coches VALUES
    ('renault', 'megane'),
    ('renault', 'clio'),
    ('seat', 'leon'),
    ('seat', 'ibiza');
 
GRANT ALL ON SCHEMA PUBLIC TO ismael, jesus, pilar;
GRANT ALL ON TABLE coches TO ismael, jesus, pilar;

El objetivo de este ejemplo es que Ismael solo vea los modelos de coches de la marca Renault y que Jesús solo vea los coches de la marca Seat. Con el tercer usuario, Pilar, comprobaremos qué puede o que no puede ver.

Activar RLS

Para activar la seguridad RLS escribe la siguiente sentencia.

ALTER TABLE coches ENABLE ROW LEVEL SECURITY;

Una vez ejecutada, si cualquier usuario que no sea un super usuario como Ismael, Jesús o Pilar ejecuta una consulta sobre la tabla no podrá ver ninguna fila, la tabla estará vacía.

Crear politicas

Para definir que debe ver cada usuario en una tabla mediante RLS se deben definir una seria de políticas que indicaran exactamente que visualizara cada uno de nuestros usuarios.

Vamos a crear dos políticas para que Ismael solo vea los modelos de coches de la marca Renault y para que Jesús solo vea los coches de la marca Seat.

CREATE POLICY plcy_coches_ismael ON coches
    FOR SELECT
    TO ismael
    USING  (marca = 'renault');
 
CREATE POLICY plcy_coches_jesus ON coches
    FOR SELECT
    TO jesus
    USING  (marca = 'seat');
  • Línea 0: indicamos que se va crear una política llamada plcy_coches_ismael sobre la tabla coches.
  • Línea 1: indicamos que esta política solo aplicara cuando el usuario haga select (podríamos aplicarlo por ejemplo también a INSERT, UPDAT, DELETE o ALL)
  • Línea 2: indicamos a que usuario le va aplicar esta política.
  • Línea 3: indicamos que sobre que columna vamos a filtrar y qué condiciones debe cumplir.

Podrías crear políticas más complejas como la siguiente sentencia (aunque en este ejemplo no lo utilizaremos)

CREATE POLICY politica_ejemplo ON tabla1
    FOR SELECT
    TO  public
    USING (CASE WHEN CURRENT_USER = 'ismael'
                  THEN campo1 = 'valor1'
                  ELSE campo1 = 'valor2' END);

Comprobaciones

Para comprobar si el resultado es el esperado cambiaremos de usuario con el comando SET ROLE seguido del nombre del usuario. Recuerda que puedes saber en todo momento con que usuario estas conectado escribiendo la siguiente sentencia:

select usename from pg_catalog.pg_user where usename = current_user;

Prueba 1: ¿Qué ve Ismael?

Para comprobarlo escribe las siguientes sentencias, donde la linea 0 indicamos el cambio de usuario y en la linea 1 la consulta a la tabla coches:

SET ROLE Ismael;
select * from coches;

Como puedes ver en la siguiente imagen todo es correcto porque solo visualiza los datos a los que su política le permite, es decir, solo ve los coches de Renault.

Prueba 2: ¿Qué ven el resto de usuarios?

*el usuario postgres es el super usuario creado por defecto en la instalación de PostgreSQL.

Advertencias sobre las vistas

Es bastante frecuente pensar que una vez aplicado la seguridad a nivel de fila (RLS) en PostgreSQL en una tabla, cualquier vista que la utilice ya tendrá los datos filtrados y esto no es del todo cierto.

  • Si por ejemplo Jesús crea una vista, obviamente el resto de usuarios no tendrán acceso a ella, pero si le otorgase a Pilar permiso con la sentecia grant select on vista_coches_jesus to pilar en este caso Pilar vería lo mismo que Jesús, cuando según la política establecida en la tabla no debería ver nada.
  • Si el que crea la vista es un super usuario y concede permisos de lectura a cualquier otro usuario como a Jesús, Ismael o Pilar todos verán lo mismo que el super usuario, es decir, todo.

Si al leer esto estas pensando ¿pues Miguel me creo una política para la vista en lugar de aplicarla a la tabla? La respuesta es sencilla, no esta permitido.

Escribir un comentario

Este sitio está protegido por reCAPTCHA y se aplican la política de privacidad y los términos de servicio de Google.