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.
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.
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.
-- 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.
CREATE ROLE lectura_cuadros;
CREATE ROLE panel_web LOGIN PASSWORD 'una-clave-larga';
GRANT lectura_cuadros TO panel_web;| Atributo del rol | Qué concede |
|---|---|
| LOGIN | Poder iniciar sesión. Es lo que convierte el rol en lo que se entiende por usuario. |
| CREATEDB | Crear bases de datos. |
| CREATEROLE | Crear y modificar otros roles. |
| SUPERUSER | Saltarse 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.
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.
mysql_secure_installation
mariadb-secure-installationLa 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.
# 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-256El 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