Saltar al contenido

Usuarios, roles y permisos

Cómo se da de alta una cuenta en un SGBD, por qué en Oracle el usuario es el esquema, qué es un rol frente a un privilegio, cómo se deja que una aplicación lea las tablas de otro dueño, y qué hay que tocar para que una instalación recién hecha no quede abierta.

En Oracle, crear un usuario es crear un espacio de trabajo

Aquí se nota la consecuencia de lo que se vio en «El oficio del DBA». Como en Oracle la base de datos es una sola y es del producto, el administrador no crea una base por aplicación: crea un usuario. Ese usuario es a la vez una cuenta con la que conectarse y un esquema, es decir el espacio donde viven sus tablas, sus índices y sus vistas. Crear el usuario es, por tanto, el paso previo obligatorio para poder crear tablas.

sql
CREATE USER intentos_owner
  IDENTIFIED BY "una-clave-larga"
  DEFAULT TABLESPACE ts_intentos
  TEMPORARY TABLESPACE temp;
  • IDENTIFIED BY fija cómo se autentica la cuenta. Es lo primero que un administrador saca del guion y mete en un gestor de secretos.
  • DEFAULT TABLESPACE es dónde acabarán sus objetos si al crearlos no se dice otra cosa. Es la forma de que cada aplicación caiga en su propio almacenamiento sin depender de que el desarrollador se acuerde.
  • TEMPORARY TABLESPACE es dónde harán sus ordenaciones y sus resultados intermedios, que es un consumo que conviene tener aparte de los datos.

La costumbre profesional es separar dos cuentas por aplicación: una propietaria, que es dueña de los objetos y solo se usa para desplegar cambios de estructura, y una de servicio, que es la que usa la aplicación en marcha y que no puede modificar el modelo. Así un error de despliegue no puede borrar una tabla en producción.

En Oracle, usuario y esquema son la misma cosa. En PostgreSQL, MySQL y SQL Server no: ahí la cuenta y el contenedor de objetos son piezas distintas.

Para el examen

  • En Oracle: usuario y esquema van de la mano: crear el usuario crea su espacio de objetos

  • En PostgreSQL y MySQL: son cosas separadas

Un usuario recién creado no puede ni entrar

La sorpresa habitual del principiante es que después de crear la cuenta nada funciona. Es correcto y es deliberado: un usuario nuevo no tiene ningún privilegio, ni siquiera el de abrir sesión. Hay que concedérselos, y esa concesión es el trabajo de seguridad del administrador.

Conviene distinguir dos cosas que se confunden en el examen. Un privilegio es un permiso concreto: abrir sesión, crear tablas, leer una tabla determinada. Un rol es un conjunto de privilegios con nombre, que se concede de una vez y se puede retirar de una vez. Los roles existen para no tener que repetir veinte concesiones por cada cuenta nueva y para poder cambiar el criterio en un solo sitio.

sql
GRANT CONNECT TO intentos_owner;
GRANT CREATE TABLE TO intentos_owner;

CONNECT es el ejemplo clásico de rol y también de cómo cambian las cosas entre versiones. Históricamente agrupaba un buen puñado de privilegios; en las versiones actuales de Oracle se ha adelgazado hasta dejar prácticamente solo CREATE SESSION, que es el permiso de abrir sesión. La lectura correcta es que CONNECT no es un permiso suelto sino un rol, y que si se quiere que la cuenta haga algo más habrá que concederle expresamente cada privilegio.

El criterio que se aplica al conceder es el de mínimo privilegio: se da lo justo para la función y nada más. Una cuenta de sola lectura para cuadros de mando no necesita CREATE TABLE, y una cuenta de aplicación no necesita poder borrar tablas.

Privilegio es un permiso; rol es un paquete de permisos con nombre. Sin CREATE SESSION, la cuenta existe pero no puede ni conectarse.

Para el examen

  • Privilegios de sistema: permiten HACER algo

  • Privilegios de objeto: permiten actuar sobre una tabla concreta

  • Sin CREATE SESSION: una cuenta recién creada ni siquiera entra

Dejar que una cuenta lea las tablas de otra

Si las tablas son propiedad de una cuenta y la aplicación entra con otra, hay dos problemas que resolver, no uno. El primero es de permisos: la cuenta lectora tiene que poder leer. El segundo es de nombre: como los objetos pertenecen a un esquema, la lectora tendría que escribir el nombre del dueño delante de cada tabla en todas sus consultas.

El permiso se concede con GRANT SELECT. El problema del nombre se resuelve con un sinónimo, que es un alias del objeto en el espacio de la otra cuenta. Con las dos piezas, la aplicación consulta como si las tablas fueran suyas y el administrador conserva la separación entre quien es dueño y quien solo lee.

sql
-- El dueño concede la lectura
GRANT SELECT ON intentos_owner.intento TO intentos_lector;

-- Y se crea el alias para que la aplicación no tenga que cualificar
CREATE SYNONYM intento FOR intentos_owner.intento;

El patrón se completa con las vistas, que son la otra herramienta de seguridad sobre el dato: en lugar de dar acceso a la tabla entera se da acceso a una vista que ya filtra las filas o esconde las columnas sensibles. Es lo que en la lista de funciones del DBA aparece como seguridad aplicada a los datos mediante vistas y permisos.

Para el examen

  • Qué es un sinónimo: solo un alias

  • Lo que NO da: permiso

  • Sin el GRANT previo: el sinónimo falla igual

PostgreSQL: todo es un rol

PostgreSQL resolvió el asunto unificando los dos conceptos: no hay usuarios por un lado y roles por otro, hay solo roles. Un rol es un usuario si además puede iniciar sesión, y es lo que en otros gestores se llamaría grupo si no puede. Un rol puede ser miembro de otro y heredar así sus privilegios.

sql
CREATE ROLE lectura_cuadros;
CREATE ROLE panel_web LOGIN PASSWORD 'una-clave-larga';
GRANT lectura_cuadros TO panel_web;
Atributo del rolQué concede
LOGINPoder iniciar sesión. Es lo que convierte el rol en lo que se entiende por usuario.
CREATEDBCrear bases de datos.
CREATEROLECrear y modificar otros roles.
SUPERUSERSaltarse todas las comprobaciones de permisos. Se concede a lo imprescindible y nunca a una aplicación.

El equivalente al createuser de la línea de comandos es exactamente esto: una llamada que crea un rol con capacidad de conexión. Conviene saberlo porque explica por qué en PostgreSQL la orden de crear usuario y la de crear rol acaban en el mismo sitio.

Para el examen

  • Usuarios y grupos: no existen por separado: todo son roles

  • Qué llamamos usuario: un rol con atributo LOGIN

Seguridad a nivel de fila

Los permisos normales llegan hasta el objeto: se puede leer una tabla o no se puede. La seguridad a nivel de fila baja un escalón más y decide, dentro de una misma tabla, qué filas ve cada quien. Es la respuesta a un caso muy común: una única tabla de intentos donde cada alumno solo debe ver los suyos, sin que la aplicación tenga que acordarse de filtrar.

En PostgreSQL se hace en dos pasos: se define una política, que es la condición que deben cumplir las filas visibles, y se activa el mecanismo sobre la tabla. Mientras no se active, la política existe pero no filtra nada, y ese es el descuido típico.

sql
CREATE POLICY solo_mis_intentos ON intento
  FOR SELECT TO panel_web
  USING (alumno_id = current_setting('app.alumno')::bigint);

ALTER TABLE intento ENABLE ROW LEVEL SECURITY;

La ventaja de administración es que el filtro deja de depender del código de la aplicación. Si mañana alguien consulta la tabla desde una herramienta de informes o desde la propia línea de comandos, el filtro sigue aplicándose, porque vive en el gestor y no en el programa.

Para el examen

  • Qué filtra: QUÉ FILAS ve cada cuenta sobre la misma tabla

  • Qué es: un filtro automático, no un permiso de tabla

Cerrar una instalación recién hecha

Un gestor recién instalado suele quedar en un estado cómodo para probar y peligroso para producir: cuentas de administración sin contraseña, cuentas anónimas, bases de ejemplo y, a veces, el servicio escuchando en todas las interfaces de red. Cerrar eso es la primera tarea de administración después de instalar.

MySQL y MariaDB traen un guion interactivo pensado para eso. Recorre los puntos flojos uno a uno: pone contraseña a la cuenta de administración, quita las cuentas anónimas, impide que la cuenta de administración entre desde la red y elimina la base de datos de prueba. En MariaDB el mandato tiene su propio nombre y llama por debajo al mismo guion.

bash
mysql_secure_installation
mariadb-secure-installation

La segunda mitad del cierre es de red y de autenticación, y se hace en los ficheros de configuración. En MySQL, el parámetro bind-address decide en qué dirección escucha el servicio: dejarlo en la dirección de bucle local significa que solo se conecta quien esté en la propia máquina. En PostgreSQL, el fichero de autenticación de clientes es el que decide, línea a línea, qué combinación de origen, base de datos y usuario se admite y con qué método se comprueba la identidad.

bash
# MySQL: solo escucha en la propia máquina
bind-address = 127.0.0.1

# PostgreSQL, pg_hba.conf: tipo, base, usuario, origen, método
local   all        all                        peer
host    llegando   panel_web  10.0.0.0/24     scram-sha-256

El orden correcto es: instalar, asegurar la instalación, restringir por dónde escucha y solo después crear las cuentas de aplicación.

Para el examen

  • Lo primero tras instalar: quitar cuentas anónimas y bases de ejemplo

  • Cuenta de administrador: ponerle contraseña

  • Acceso remoto: cerrar el de root