Usuarios y seguridad en Firebird 3 (1)

2 comentarios

Como este es un tema largo no lo podremos tratar en un solo artículo de este blog, por eso habrá otros artículos relacionados.

Crear usuarios para las bases de datos y determinar lo que esos usuarios pueden hacer y no pueden hacer, es una tarea básica de administración.

Hasta Firebird 2.5.9 la tarea de administración de usuarios estaba centralizada.

¿Qué significa eso?

Que los datos de los usuarios (sus nombres y los hash de sus contraseñas) se guardan en una «Base de Datos de seguridad», utilizada sólo para eso, y allí se buscan cuando alguien quiere conectarse a una Base de Datos normal.

El nombre de esa «Base de Datos de seguridad», en Firebird 2.x es: security2.fdb

¿Y qué significa que se guarda el hash de la contraseña?

Que en la Base de Datos security2.fdb nunca se guarda la contraseña del usuario sino un número que se obtiene al realizar algunas operaciones con esa contraseña.

Veamos un ejemplo muy simple para entender esto. Supongamos que la contraseña de un usuario es «SUPERMAN», y que el algoritmo para obtener el hash consiste en multiplicar el código ASCII de un carácter por la posición que ocupa dentro de la contraseña, empezando por 1, y sumando todos esos resultados parciales.

S = 83  resultado1 = 83 * 1 =  83
U = 85  resultado2 = 85 * 2 = 170
P = 80  resultado3 = 80 * 3 = 240
E = 69  resultado4 = 69 * 4 = 276
R = 82  resultado5 = 82 * 5 = 410
M = 77  resultado6 = 77 * 6 = 462
A = 65  resultado7 = 65 * 7 = 455
N = 78  resultado8 = 78 * 8 = 624

El hash de SUPERMAN, usando ese algoritmo será: 83 + 170 + 240 + 276 + 410 + 462 + 455 + 624 = 2720

Y en la Base de Datos llamada security2.fdb se guarda el número 2720, no la palabra SUPERMAN. Entonces, cuando el usuario quiere conectarse a una Base de Datos normal introduce su contraseña y el Servidor del Firebird calcula el hash de lo que escribió y lo compara con el hash guardado en security2.fdb. Si es 2720 entonces se le permite la conexión a la Base de Datos. Si el resultado es cualquier otro número, se lo rechaza.

Desde luego que el algoritmo usado por Firebird no es el mostrado arriba, es un algoritmo mucho más complicado. Lo de arriba fue un ejemplo muy sencillo para ilustrar la idea.

La gran ventaja de usar un hash es que la palabra SUPERMAN no la encontrarás jamás dentro de security2.fdb por la sencilla razón de que esa palabra jamás se guardó ahí, lo que sí se guardó fue su hash.

¿Te has dado cuenta que cuando escribes una contraseña/password debes escribir exactamente las mayúsculas y las minúsculas?

Eso es debido a que el código ASCII de una letra mayúscula es diferente al código de esa misma letra en minúscula. Por ejemplo, el código ASCII de la letra «A» es 65 pero el código ASCII de la letra «a» es 97. Al ser números diferentes los hash que se obtengan también serán diferentes, por supuesto.

¿Qué significa que la administración de usuarios está centralizada?

Que los nombres de todos los usuarios y los hash de todos los usuarios (hay un hash para cada usuario, nunca más y nunca menos) se encuentran siempre, sí o sí, en la Base de Datos de nombre security2.fdb

La ventaja de la administración de usuarios centralizada

Cada usuario (y su hash, claro) se crea una sola vez aunque haya muchas bases de datos en el Servidor. Escribiendo su nombre y su contraseña/password podría conectarse a cualquier Base de Datos. Aunque en cada Base de Datos se le podrían restringir los accesos/permisos/derechos, pero no se le podría impedir la conexión.

Y si está conectado a una Base de Datos entonces podría crear objetos dentro de esa Base de Datos, por ejemplo escribiendo:

CREATE TABLE PRUEBA1 (MiColumna1 INTEGER);

Listo, ya creó una tabla llamada PRUEBA1

También podría crear vistas, stored procedures, triggers, etc.

Te guste o no te guste…así funciona.

La desventaja de la administración de usuarios centralizada

Si un usuario conoce el nombre de una Base de Datos y su ubicación, entonces podrá conectarse a ella. Por ejemplo, si la Base de Datos es:

D:\CONTABILIDAD\DATABASES\MARCELA.FDB

con solamente conocer eso ya podrá realizar una conexión exitosa.

Lo mismo si no conoce la ruta y el nombre de la Base de Datos pero sí conoce el alias que se le asignó en el archivo ALIASES.CONF, podrá conectarse con éxito.

Y como ya sabes, si se conectó a una Base de Datos entonces podrá crear objetos dentro de esa Base de Datos.

Resumiendo:

La administración de usuarios centralizada tiene la ventaja de que se escribe poco porque el nombre de cada usuario y su contraseña se determinan una sola vez y pueden ser usados en múltiples bases de datos.

La desventaja es que cualquier usuario podría conectarse a cualquier Base de Datos si conoce el nombre y la ubicación (o el alias) de esa Base de Datos. Y aunque con los comandos GRANT y REVOKE se podría limitar las operaciones que puede realizar, que tenga esa posibilidad de poder conectarse a la Base de Datos que se le antoje, es un riesgo a la seguridad.

Otro riesgo a la seguridad, aún mucho más grave, es que si consigue copiar la Base de Datos (en un pen-drive, por ejemplo) y luego la lleva a una computadora donde conoce la contraseña del usuario SYSDBA entonces podrá ver todo lo que se le ocurra ver. O agregar. O borrar. O modificar.

En muchas empresas, sobre todo las pequeñas y medianas, es imposible evitar que algún empleado copie en un pen-drive una Base de Datos. Y algo así, podría ser muy grave.

Afortunadamente, con Firebird 3 se aumentó mucho la seguridad, como veremos en los siguientes artículos de esa serie.

Artículos relacionados:

Usuarios y seguridad en Firebird 3 (2)

Usuarios y seguridad en Firebird 3 (3)

Usuarios y seguridad en Firebird 3 (4)

Usuarios y seguridad en Firebird 3 (5)

Usuarios y seguridad en Firebird 3 (6)

El índice del blog Firebird21

Auditoría Informática

6 comentarios

Muchas veces sería muy útil poder responder preguntas como: ¿quién lo hizo? ¿cuándo lo hizo? ¿qué hizo?

En este blog ya hemos tocado esos temas pero ahora los veremos con mayor profundidad.

La gran ventaja de tener una buena metodología de auditoría informática es que eso nos permite contar con una «máquina del tiempo«. O sea, podremos saber que contenía exactamente cada tabla de nuestra Base de Datos en el momento que se nos ocurra. Por ejemplo: el 20 de septiembre del año pasado a las 14:23:18.

También teniendo una buena metodología de auditoría informática responder las siguientes preguntas (y muchísimas otras) será muy sencillo:

  • ¿Quién registró la Factura N° 001-002-3456789?
  • ¿En qué fecha se registró la Factura N° 001-002-3456789?
  • ¿Cuál era el domicilio del cliente JUAN PÉREZ hace dos años?
  • ¿Cuál era el precio de venta original de COCA COLA de 1 litro?
  • ¿Cuántas veces ya se cambió el precio de venta de COCA COLA de 1 litro?
  • ¿Cuál era el precio de venta anterior de COCA COLA de 1 litro?
  • ¿Quién modificó el precio de venta de COCA COLA de 1 litro hace dos meses?
  • ¿De cuáles productos nunca se modificó el precio de venta?
  • ¿Cuántas Facturas registró el día de ayer el usuario MARÍA BENÍTEZ?
  • ¿Quién es el usuario que más Facturas registró el día de ayer?

Hay varias formas de conseguir nuestro objetivo, desde luego que algunas de esas formas son mejores que otras. La mostrada en este articulo es la usada por el autor de este blog desde hace muchos años. ¿La ventaja? rápidamente puedes obtener cualquier información que necesites y puedes saber todo lo que ocurrió en tu Base de Datos desde el instante cero. ¿La desventaja? la tabla de AUDITORÍA crece muchísimo, puede llegar a ser desmesuradamente grande.

La idea es la siguiente:

  • Tener una tabla de AUDITORÍA para registrar en ella todos los INSERT, UPDATE, y DELETE realizados en cualquiera de las tablas auditables.
  • Para cada tabla auditable tener un trigger que se encargará de insertar en la tabla de AUDITORÍA los datos del INSERT, UPDATE, o DELETE realizados en esa tabla auditable.

Desde luego que podríamos crear manualmente cada uno de esos triggers pero eso sería muy poco inteligente ya que es mucho más práctico crear un stored procedure que se encargue de realizar por nosotros esa aburridísima tarea.

La tabla de AUDITORÍA tiene esta estructura:

Captura 1. La estructura de la tabla de AUDITORÍA

Los nombres de los triggers empiezan con AUDIT_ para que sea muy fácil saber que ese trigger se encarga de realizar la tarea de auditoría de esa tabla.

Captura 2. Los nombres de todos los triggers de auditoría empiezan con AUDIT_

La estructura de la tabla de BANCOS es la siguiente:

Captura 3. La estructura de la tabla de BANCOS

Y el trigger de la tabla de BANCOS que se encarga de insertar las operaciones realizadas en la tabla de BANCOS dentro de la tabla de AUDITORÍA es el siguiente:

Listado 1. El trigger de la tabla de BANCOS que inserta sus operaciones en la tabla de AUDITORÍA

CREATE TRIGGER AUDIT_BANCOS FOR BANCOS
ACTIVE BEFORE 
  INSERT OR UPDATE OR DELETE
POSITION 9
AS
DECLARE VARIABLE lcOperac CHAR(1);
BEGIN 

  lcOperac = IIF(INSERTING, 'I', IIF(UPDATING, 'U', 'D')) ;

  IF (INSERTING OR NEW.BAN_SERVID <> OLD.BAN_SERVID) THEN
    INSERT INTO AUDITORIA (AUD_SERVID, AUD_TABLAX, AUD_OPERAC, AUD_IDEOTR, AUD_NOMCOL, AUD_VALORX) VALUES(NEW.BAN_SERVID, 'BANCOS', :lcOperac, NEW.BAN_IDENTI, 'BAN_SERVID', NEW.BAN_SERVID) ;

  IF (INSERTING OR NEW.BAN_CODSUC <> OLD.BAN_CODSUC) THEN
    INSERT INTO AUDITORIA (AUD_SERVID, AUD_TABLAX, AUD_OPERAC, AUD_IDEOTR, AUD_NOMCOL, AUD_VALORX) VALUES(NEW.BAN_SERVID, 'BANCOS', :lcOperac, NEW.BAN_IDENTI, 'BAN_CODSUC', NEW.BAN_CODSUC) ;

  IF (INSERTING OR NEW.BAN_IDENTI <> OLD.BAN_IDENTI) THEN
    INSERT INTO AUDITORIA (AUD_SERVID, AUD_TABLAX, AUD_OPERAC, AUD_IDEOTR, AUD_NOMCOL, AUD_VALORX) VALUES(NEW.BAN_SERVID, 'BANCOS', :lcOperac, NEW.BAN_IDENTI, 'BAN_IDENTI', NEW.BAN_IDENTI) ;

  IF (INSERTING OR NEW.BAN_CODIGO <> OLD.BAN_CODIGO) THEN
    INSERT INTO AUDITORIA (AUD_SERVID, AUD_TABLAX, AUD_OPERAC, AUD_IDEOTR, AUD_NOMCOL, AUD_VALORX) VALUES(NEW.BAN_SERVID, 'BANCOS', :lcOperac, NEW.BAN_IDENTI, 'BAN_CODIGO', NEW.BAN_CODIGO) ;

  IF (INSERTING OR NEW.BAN_NOMBRE <> OLD.BAN_NOMBRE) THEN
    INSERT INTO AUDITORIA (AUD_SERVID, AUD_TABLAX, AUD_OPERAC, AUD_IDEOTR, AUD_NOMCOL, AUD_VALORX) VALUES(NEW.BAN_SERVID, 'BANCOS', :lcOperac, NEW.BAN_IDENTI, 'BAN_NOMBRE', NEW.BAN_NOMBRE) ;

  IF (DELETING) THEN
    INSERT INTO AUDITORIA (AUD_SERVID, AUD_TABLAX, AUD_OPERAC, AUD_IDEOTR) VALUES(OLD.BAN_SERVID, 'BANCOS', :lcOperac, OLD.BAN_IDENTI) ;

END;

Como vimos antes, ese trigger no fue creado manualmente, fue creado automáticamente por un stored procedure. De esta manera ahorramos muchísimo tiempo. Y si la estructura de alguna de nuestras tablas cambió (o si agregamos una tabla a nuestra Base de Datos) entonces al volver a ejecutar ese stored procedure recreamos todos los triggers de auditoría. Y listo.

El stored procedure se llama SPG_AUDITORIA (Nota: SPG significa «stored procedure de uso general», o sea que puede ser útil en muchas bases de datos. Costumbre del autor de este blog usar esa nomenclatura).

SPG_AUDITORÍA lo que hace es:

  • Eliminar todos los triggers cuyos nombres empiezan con AUDIT_
  • Crear triggers de auditoría para (casi) todas las tablas de la Base de Datos. Los nombres de todos esos triggers empezarán con AUDIT_

NOTA: Algunas tablas no deben tener triggers de auditoría. La propia tabla de AUDITORÍA no debe tener o se produciría un ciclo infinito. La tabla de LOG (usada para ver como se va ejecutando el código fuente) tampoco debe tener.

Para saber si una columna existe en una tabla se puede usar un stored procedure como el siguiente:

Listado 2. Un stored procedure para saber si una columna existe en una tabla

CREATE PROCEDURE SPG_COLUMNA_EXISTE(
  tcNombreTabla   CHAR(32),
  tcNombreColumna CHAR(32))
RETURNS(
  ftcExiste CHAR(1))
AS
DECLARE VARIABLE lcColumna VARCHAR(32);
BEGIN
  
  lcColumna = (SELECT 
                 RDB$FIELD_NAME 
               FROM 
                 RDB$RELATION_FIELDS 
               WHERE 
                 RDB$RELATION_NAME = :tcNombreTabla AND
                 RDB$FIELD_NAME    = :tcNombreColumna) ;
                 
  ftcExiste = IIF(lcColumna IS NOT NULL, 'T', 'F');
  
  SUSPEND;
  
END;

Y se lo usaría así:

lcColumnaExiste = (SELECT ftcExiste FROM SPG_COLUMNA_EXISTE('PRODUCTOS', 'PRD_NOMBRE')) ;

Y en la variable lcColumnaExiste tendríamos ‘T’ si existe la columna PRD_NOMBRE en la tabla PRODUCTOS o ‘F’ si no existe esa columna en esa tabla.

Listado 3. El stored procedure SPG_AUDITORIA que sirve para crear todos los triggers de auditoría

CREATE PROCEDURE SPG_AUDITORIA
AS
DECLARE VARIABLE lcNombreTabla   VARCHAR(32);
DECLARE VARIABLE lcNombreTrigger VARCHAR(32);
DECLARE VARIABLE lcNombreColumna VARCHAR(32);
DECLARE VARIABLE lcColumnaExiste CHAR(1);
DECLARE VARIABLE lcServid        VARCHAR(14);
DECLARE VARIABLE lcIdeOtr        VARCHAR(14);
DECLARE VARIABLE lcOperac        CHAR(1);
DECLARE VARIABLE lcComando       VARCHAR(16384);
BEGIN
  
  -- Paso 1. Se eliminan todos los triggers cuyos nombres empiezan con: AUDIT_
  --         Este FOR SELECT devuelve los nombres de todos los triggers
  
  FOR SELECT
    RDB$TRIGGER_NAME
  FROM
    RDB$TRIGGERS
  WHERE
    RDB$SYSTEM_FLAG = 0
  INTO
    :lcNombreTrigger
  DO BEGIN
    IF (UPPER(LEFT(lcNombreTrigger, 6)) = 'AUDIT_') THEN BEGIN
      lcComando = 'DROP TRIGGER ' || lcNombreTrigger;
      EXECUTE STATEMENT lcComando;
    END
  END
  
  -- Paso 2. Se crea un trigger AUDIT_ para cada tabla de la Base de Datos (menos para las tablas AUDITORIA y LOG)
  
  FOR SELECT
    RDB$RELATION_NAME
  FROM
    RDB$RELATIONS
  WHERE
    RDB$SYSTEM_FLAG = 0 AND
    RDB$VIEW_BLR IS NULL
  ORDER BY
    RDB$RELATION_NAME
  INTO
    :lcNombreTabla
  DO BEGIN
    lcNombreTabla = UPPER(TRIM(lcNombreTabla));
    IF (lcNombreTabla <> 'AUDITORIA' AND lcNombreTabla <> 'LOG') THEN BEGIN
      lcComando = 'CREATE OR ALTER TRIGGER AUDIT_' || lcNombreTabla || ' FOR ' || lcNombreTabla || ASCII_CHAR(13);
      lcComando = lcComando || 'ACTIVE BEFORE ' || ASCII_CHAR(13) ;
      lcComando = lcComando || 'INSERT OR UPDATE OR DELETE ' || ASCII_CHAR(13) ;
      lcComando = lcComando || 'POSITION 9 ' || ASCII_CHAR(13) ;
      lcComando = lcComando || 'AS ' || ASCII_CHAR(13) ;
      lcComando = lcComando || '  DECLARE VARIABLE lcOperac CHAR(1); ' || ASCII_CHAR(13) ;
      lcComando = lcComando || 'BEGIN ' || ASCII_CHAR(13) ;
      lcComando = lcComando || ASCII_CHAR(13) ;
      lcComando = lcComando || '  lcOperac = IIF(INSERTING, ''I'', IIF(UPDATING, ''U'', ''D'')) ;' || ASCII_CHAR(13) ;
      lcComando = lcComando || ASCII_CHAR(13) ;
      -- Se agrega el IF() THEN que usarán los INSERT y los UPDATE
      FOR SELECT
        RDB$FIELD_NAME
      FROM
        RDB$RELATION_FIELDS
      WHERE
        RDB$RELATION_NAME = :lcNombreTabla
      INTO
        :lcNombreColumna
      DO BEGIN
        lcNombreColumna = TRIM(lcNombreColumna);
        lcColumnaExiste = (SELECT ftcExiste FROM SPG_COLUMNA_EXISTE(:lcNombreTabla, LEFT(:lcNombreColumna, 3) || '_SERVID')) ;
        lcServid        = IIF(lcColumnaExiste = 'T', 'NEW.' || LEFT(lcNombreColumna, 3) || '_SERVID', 'NULL') ;
        lcIdeOtr        = 'NEW.' || LEFT(lcNombreColumna, 3) || '_IDENTI';
        lcComando       = lcComando || '  IF (INSERTING OR NEW.' || lcNombreColumna || ' <> OLD.' || lcNombreColumna || ') THEN' || ASCII_CHAR(13) ;
        lcComando       = lcComando || '    INSERT INTO AUDITORIA (AUD_SERVID, AUD_TABLAX, AUD_OPERAC, AUD_IDEOTR, AUD_NOMCOL, AUD_VALORX) VALUES(' || lcServid || ', ''' || lcNombreTabla || ''', :lcOperac, ' || lcIdeOtr || ', ''' || lcNombreColumna || ''', NEW.' || lcNombreColumna || ') ;' || ASCII_CHAR(13) ;
        lcComando       = lcComando || ASCII_CHAR(13) ;
      END
      -- Se agrega el IF () THEN que usarán los DELETE
      FOR SELECT
        RDB$FIELD_NAME
      FROM
        RDB$RELATION_FIELDS
      WHERE
        RDB$RELATION_NAME = :lcNombreTabla
      ROWS
        1
      INTO
        :lcNombreColumna
      DO BEGIN
        lcColumnaExiste = (SELECT ftcExiste FROM SPG_COLUMNA_EXISTE(:lcNombreTabla, LEFT(:lcNombreColumna, 3) || '_SERVID')) ;
        lcServid        = IIF(lcColumnaExiste = 'T', 'OLD.' || LEFT(lcNombreColumna, 3) || '_SERVID', 'NULL') ;
        lcIdeOtr        = 'OLD.' || LEFT(lcNombreColumna, 3) || '_IDENTI';
        lcComando       = lcComando || '  IF (DELETING) THEN' || ASCII_CHAR(13) ;
        lcComando       = lcComando || '    INSERT INTO AUDITORIA (AUD_SERVID, AUD_TABLAX, AUD_OPERAC, AUD_IDEOTR) VALUES(' || lcServid || ', ''' || lcNombreTabla || ''', :lcOperac, ' || lcIdeOtr || ') ;' || ASCII_CHAR(13) ;
        lcComando       = lcComando || ASCII_CHAR(13) ;
      END
      
      -- Se finaliza el código fuente del trigger de auditoría
      lcComando = lcComando || 'END ' || ASCII_CHAR(13) ;
      
      -- Se crea el trigger de auditoría
      EXECUTE STATEMENT lcComando;
    END
  END
  
END;

En el Paso 1. del stored procedure SPG_AUDITORIA se obtienen los nombres de todos los triggers y aquellos cuyos nombres empiezan con AUDIT_ son eliminados. Serán nuevamente creados en el Paso 2.

Lo que se hace en el Paso 2. del stored procedure SPG_AUDITORIA es poner en el string lcComando todo el código fuente de cada trigger y luego mediante un EXECUTE STATEMENT crear ese trigger.

Para ello va obteniendo los nombres de cada una de las tablas de la Base de Datos y los nombres de las columnas que contiene cada una de esas tablas. De acuerdo a eso le va agregando texto al string lcComando.

Lo bueno de tener al stored procedure SPG_AUDITORIA es que si se agregan o se eliminan columnas de una tabla o si se agrega una tabla a la Base de Datos entonces volviendo a ejecutar a SPG_AUDITORIA se tienen todos los triggers actualizados. Súper rápido y súper fácil.

Ejemplo de uso

Insertaremos una fila a la tabla de BANCOS, luego modificaremos el nombre de una columna y luego borraremos la fila insertada. En la tabla de AUDITORÍA se reflejarán todas esas acciones que realizamos.

Captura 4. Insertamos una fila a la tabla de BANCOS

La inserción en la tabla de BANCOS se registró en la tabla de AUDITORÍA.

Captura 5. En la tabla de AUDITORÍA se registró lo que se realizó en la tabla de BANCOS

Ahora le hacemos un cambio a esa fila (la que tiene a 18 como el identificador del Banco).

Captura 6. Se le cambió el nombre al Banco cuyo identificador es 18

Y vemos que en la tabla de AUDITORÍA se insertó una fila que nos indica ese cambio.

Captura 7. El cambio que se hizo en la tabla de BANCOS ha quedado registrado en la tabla de AUDITORÍA

Finalmente, eliminamos al Banco cuyo identificador es 18 de la tabla de BANCOS y en la tabla de AUDITORÍA veremos que ha sido eliminado.

Captura 8. Al eliminar a un Banco de la tabla de BANCOS esa eliminación ha quedado registrada en la tabla de AUDITORÍA

Visualización

Si haces clic sobre una Captura entonces verás a esa imagen en mayor tamaño.

Conclusión

Si registramos todos los INSERT, UPDATE, y DELETE que se hicieron en cada una de las tablas de nuestra Base de Datos entonces siempre podremos saber lo que se hizo en cada tabla, quien lo hizo, y cuando lo hizo.

Esto nos permite tener una «máquina del tiempo» para retrotraernos a cualquier momento pasado. Y muchísimas preguntas podremos responder.

La ventaja del método mostrado en este artículo es que tenemos a nuestra disposición toda la información que podamos llegar a necesitar. La desventaja es que la tabla de AUDITORÍA crece inmensamente ya que todo queda registrado en ella.

Por supuesto que una alternativa es auditar solamente algunas tablas de nuestra Base de Datos, no todas las tablas.

En casi todas las aplicaciones es importantísimo poder auditar (aunque más no sea para señalar al culpable cuando se sabe que alguien «metió la pata»).

Artículos relacionados

Nombres de todas las tablas

Nombres de todas las columnas de una tabla

Nombres de los triggers

Registrando los cambios realizados a los datos de una tabla

Registrar los cambios a los precios de venta

Registrando los productos borrados

Registrando errores en una tabla de LOG

Otro ejemplo del uso de la tabla de LOG

El índice del blog Firebird21

Error Request depth exceeded

2 comentarios

Si al intentar grabar un vista ves el mensaje:

Unsuccessful metadata update.
Request depth exceeded. (Recursive definition?).

SQL Code: -607
IB Error Number: 335544351

eso significa que muy probablemente hay una recursión. O sea, la vista1 hace un JOIN a la vista2, y la vista2 hace un JOIN a la vista1.

La solución, por supuesto, es evitar esa recursión. Para ello, en lugar de escribir:

Listado 1. Este código causó un error de Request depth exceeded

SELECT
  T.UnaColumna,
  V.OtraColumna
FROM
  MiTabla T
JOIN
  MiVista V
    ON MiCondición

Se debe escribir:

Listado 2. Este código se compila sin error

SELECT
  T.UnaColumna,
  (SELECT V.OtraColumna FROM MiVista V ON MiCondición)
FROM
  MiTabla T

Instalando y configurando Firebird en un VPS

2 comentarios

En esta época es muy común que las empresas contraten un VPS (Virtual Private Server) para instalar programas en ellos y guardar sus archivos importantes.

La gran ventaja de un VPS sobre un hosting o un sitio de almacenamiento de archivos es que en el VPS puedes instalar cualquier programa que quieras.

Y por supuesto que aquí veremos como instalar el Servidor del Firebird y algunas bases de datos.

Evidentemente que para poder acceder a un VPS debes conocer su dirección IP, el nombre de un usuario (preferentemente «root», ya que «root» tiene siempre todos los permisos) y la contraseña (o password) de ese usuario.

Para que desde Windows sea fácil subir y bajar archivos en un VPS e instalarle programas podemos hacer uso de dos aplicaciones muy útiles:

  • PuTTY
  • WinScp

Ambas son gratis, muy populares, y podemos encontrarlas fácilmente en Internet. No son las únicas alternativas que existen pero son muy populares y por lo tanto cualquier duda que tengas podrás resolver muy rápido con la ayuda del omnisciente dios Google.

PuTTY sirve para ejecutar comandos en la computadora remota. Aunque la computadora remota se encuentre a miles de kilómetros desde tu propia computadora podrás acceder a la computadora remota y los comandos que escribas se ejecutarán en la computadora remota. Es como si estuvieras allí.

WinScp sirve para copiar archivos hacia o desde la computadora remota, crear archivos, crear carpetas (las llama «directorios»), ver el contenido de los archivos, otorgar permisos a las carpetas y a los archivos, y muchísimas osas más.

Si tenemos instaladas estas dos aplicaciones entonces trabajar con un VPS es algo realmente sencillo.

Captura 1. La pantalla inicial de PuTTY

Al programa PuTTy debemos indicarle el nombre del host o la dirección IP a la cual queremos conectarnos. Abrirá una ventana la cual será nuestra «terminal», todo lo que escribamos allí se ejecutará en la computadora remota. Lo primero que hace es preguntar por el nombre del usuario («login as») y la contraseña/password de ese usuario.

Captura 2. Todo lo que escribas en la «terminal» se ejecutará en la computadora remota, como si estuvieras físicamente allí.

El comando ls del Linux sirve para mostrar el contenido de una carpeta (directorio).

Captura3. Viendo los archivos y las carpetas/directorios que se encuentran en la computadora remota.

Si quieres conocer cual distribución de Linux tiene instalada la computadora remota, el comando cat /etc/issue te mostrará ese dato

Captura 4. El comando cat /etc/issue muestra el nombre y la versión del Sistema Operativo de la computadora remota

El comando who te mostrará quienes son los usuarios conectados en este momento.

Captura 5. El comando who muestra los nombres de los usuarios conectados ahora mismo.

Para poder enviar y recibir archivos de la computadora remota, crear carpetas/directorios, otorgarles permisos a las carpetas y a los archivos, y muchas cosas más, podemos usar a WinScp.

Captura 6. Debes escribir la dirección IP del Servidor y elegir un protocolo. Muchos VPS ya no aceptan FPT pero sí aceptan SFTP.

Si están correctas la dirección IP, el protocolo, el nombre del usuario, y la contraseña del usuario, entonces ya podrás interactuar con la computadora remota.

Captura 7. Puedes enviar archivos del panel izquierdo (computadora local) hacia el panel derecho (computadora remota). Y viceversa.
Captura 8. Se envió un archivo desde el panel izquierdo (computadora local) hacia el panel derecho (computadora remota)
Captura 9. Ejecución de comandos en la computadora remota

En la «terminal» que tenemos con PuTTY escribimos varios comandos:

  • cd sirve para cambiarse (ubicarse) en otra carpeta (directorio)
  • ls sirve para mostrar los nombres de las carpetas (directorios) y de los archivos
  • tar -xf sirve para descomprimir archivos que tienen la extensión .tar.gz, estos archivos son equivalentes a los archivos .zip del Windows
Captura 10. Un archivo comprimido

Los archivos .tar.gz deben descomprimirse antes de que alguno de los archivos que contiene pueda ser usado.

Captura 11. Al descomprimir ese archivo .tar.gz se creó una carpeta que tiene su mismo nombre y que contiene varios archivos
Captura 12. El contenido de la carpeta descomprimida

En la carpeta mostrada en la Captura 12. vemos que hay otro archivo comprimido (lo sabemos porque ese archivo tiene la extensión .tar.gz), pero ya fue descomprimido en la Captura 9. como puedes comprobar.

Instalar al Servidor del Firebird

Para esto hay 2 pasos que debemos seguir:

  1. Escribir: cd /root/FirebirdSS-2.5.9.27139-0.amd64 para ubicarnos en esa carpeta
  2. Escribir: sudo ./install.sh para que se inicie el programa de instalación

El nombre de la carpeta del Firebird podría ser distinto en tu caso. Este es un ejemplo para la versión 2.5.9

Los archivos con extensión .sh son equivalentes a los archivos con extensión .bat del Windows

NOTA: Si aparece el error bad ELF interpreter significa que la computadora remota es de 64 bits y quieres instalar en ella una aplicación de 32 bits pero tiene deshabilitada la opción de agregar aplicaciones de 32 bits. Puedes habilitar esa opción si quieres, en Internet encontrarás como hacerlo. Pero para el caso del Firebird no es necesario ya que si el driver ODBC de tu computadora local es de 32 bits entonces igual podrás conectarte al Servidor del Firebird aunque éste sea de 64 bits.

Crear carpetas para las bases de datos

Las bases de datos que tendrás en la computadora remota estarán en alguna carpeta, desde luego. Lo más conveniente suele ser que crees subcarpetas de la carpeta /opt, algo como:

/opt/sistemas/contabilidad/basesdatos/

esas carpetas puedes crearlas con el comando mkdir del Linux o usando el programa WinScp que ya vimos más arriba.

Copiar bases de datos en las carpetas remotas

Para esto lo más recomendable es usar el programa WinScp tal y como se muestra en la Captura 7. y en la Captura 8.

Otorgar permisos a las carpetas y a las bases de datos

Para que los usuarios de tu aplicación puedan conectarse a las bases de datos remotas deben contar con los permisos respectivos (Linux es muy estricto con el tema de los permisos). Puedes usar el programa WinScp para otorgar esos permisos.

Captura 13. Clic derecho en el nombre de un archivo para ver un menú contextual y luego clic en «Propiedades» para poder cambiar sus permisos.
Captura 14. Hay que otorgar los permisos 0666 a cada Base de Datos para que los usuarios puedan conectarse a ellas
Captura 15. Los permisos de las carpetas si son 0755 funcionan bien

Editar el archivo aliases.conf

Para que no tengas que escribir toda la ruta para conectarte a una Base de Datos (que en el caso de Linux suelen ser rutas muy largas) es conveniente que edites el archivo aliases.conf y coloques en él los alias con los cuales podrás referirte a las bases de datos. Por ejemplo:

cinthia = /opt/vs_sistemas/vs_conta/databases/CINTHIA.FDB
Captura 16. Clic con el botón derecho para que aparezca un menú contextual
Captura 17. Asignando alias a las bases de datos nos permite escribir menos cuando queremos conectarnos a ellas

Para conectarte a las bases de datos

Puedes conectarte a las bases de datos tanto desde Linux como desde Windows. Lo que debes recordar si te conectas desde Windows es que debes usar las barras hacia adelante y no las barras hacia atrás.

Listado 1. Conexión sin alias

CONNECT 100.101.102.103:/opt/vs_sistemas/vs_conta/databases/CINTHIA.FDB user SYSDBA password MiPassword;

Listado 2. Conexión con alias

CONNECT 100.101.102.103:cinthia user SYSDBA password MiPassword;

Podrás conectarte tanto como se muestra en el Listado 1. o como se muestra en el Listado 2., suele ser más recomendable hacerlo como se muestra en el Listado 2. pero es cuestión de gustos.

Conclusión

En este artículo hemos visto como conectarnos a un VPS, como ejecutar comandos en el VPS, como instalar al Servidor del Firebird, como copiar archivos, como otorgarles permisos a los archivos y a las carpetas, como editar archivos, y como conectarnos a las bases de datos remotas.

Si el VPS tiene instalada alguna distribución de Linux (es lo más común en los VPS) y no usamos alias entonces debemos usar las barras hacia adelante, tal y como se muestra en el Listado 1.

Artículos relacionados

Instalando Firebird en Ubuntu (Linux)

El índice del blog Firebird21

Instalando Firebird en Ubuntu (Linux)

7 comentarios

Instalar a Firebird en Ubuntu es más complicado que instalarlo en Windows (donde solamente haces clic en «siguiente», «siguiente», prácticamente), pero tampoco es difícil…cuando sabes como.

En Ubuntu el Firebird está en la lista de paquetes de instalación. No está instalado por defecto pero si quieres instalarlo es muy fácil.

Lo que debemos hacer en todos los casos es abrir la «terminal», el equivalente en Linux a la «ventanita símbolo del sistema» del Windows. Para ello presionamos las teclas CTRL + ALT + T

A continuación, para trabajar con derechos de «root» (o sea de Administrador en Windows) escribimos:

sudo su

Nos preguntará por la contraseña. Después de escribirla…

Con versiones antiguas de Ubuntu

  :~$ sudo add-apt-repository ppa:mapopa/firebird3.0
  :~$ sudo apt update

Con versiones recientes de Ubuntu

sudo apt firebird3.0-server

preguntará por el password del usuario SYSDBA, después de especificarlo debemos escribir:

sudo dpkg-reconfigure firebird3.0-server

ese comando lo que hará será reconfigurar y aplicar los cambios.

Alternativamente, se podría escribir también algo como:

sudo apt-get install firebird3.0-super

Como sabes, Ubuntu siempre incluye una versión de Firebird y si quieres instalar la versión que viene incluida lo tienes fácil, simplemente escribes los comandos mostrados arriba y listo, asunto terminado. Más complicado es cuando queremos instalar otra versión del Firebird. Por ejemplo, nuestra versión del Ubuntu tiene incluido el paquete de instalación de Firebird 3.0.7 pero nosotros queremos instalar la versión 2.5.9, o la versión 4.0.1, o cualquier otra versión.

Instalación

Paso 1. Descargar la versión que nos interesa

Para ello, ingresamos al sitio:

www.firebirdsql.org

y en la sección de Downloads encontraremos lo que buscamos. Las versiones para Linux tienen las extensiones .rpm o .tar.gz, para el caso de Ubuntu hay que descargar la .tar.gz ya que la .rpm es para las distros Red Hat y Fedora.

Paso 2. Extraer los archivos

Los archivos con extensión .tar.gz en Linux son equivalentes a los archivos .zip del Windows y por lo tanto no se pueden usar así como están, primero se debe extraer lo que contienen. IMPORTANTE: Debes extraer todos los archivos que se encuentran en cada .tar.gz antes de continuar.

Paso 3. Abrir la terminal

Esto lo consigues presionando juntas las teclas CTRL + ALT + T

Paso 4. Usar la terminal con derechos de usuario «root» (como el Administrador del Windows)

Para ello debes escribir:

sudo su

te pedirá que escribas la contraseña.

Paso 5. Ubicarte en la carpeta de Descargas

cd Descargas

Paso 6. Ubicarte en la carpeta donde se extrajeron los archivos del Firebird (aún no están instalados pero ya están extraídos del archivo .tar.gz que los contenía)

Por ejemplo:

cd FirebirdSS-2.5.9.27139-0.i686

Paso 7. Iniciar la instalación

sudo ./install

Paso 8. Escribir la contraseña del usuario SYSDBA

Te pedirá esa contraseña, escribe cualquiera que desees.

Y listo, con eso estará finalizada la instalación del Firebird.

NOTA: si aparece el mensaje de que no existe libncurses5 debes agregarlo al repositorio e instalarlo, con los siguientes comandos:

sudo add-apt-repository universe
sudo apt-get install libncurses5 libncurses5:1386

Luego, repites desde el Paso 7.

Para permitir que los usuarios puedan conecarse a una Base de Datos en Ubuntu

chmod 777 /samba/public/sistemas/contabilidad/databases/marcela.fdb

Desde luego que los nombres de las carpetas y de la Base de Datos pueden ser distintos en tu caso. El comando chmod sirve para otorgarles permisos a los usuarios y el número 777 significa: todos los permisos a todos los usuarios.

Para que puedan realizarse conexiones desde otras computadoras

La computadora donde se instaló el Servidor del Firebird necesita tener abierto el puerto que se usará para las conexiones. Por defecto ese puerto es el 3050 pero en el archivo firebird.conf se lo puede cambiar por otro (3051,3052, 3057, 3099, etc.). Para abrir un puerto:

sudo ufw allow 3050/tcp

desde luego que en lugar de 3050 podrías escribir 3051, 3052, 3057, o cualquier otro número de puerto que quieras usar para las conexiones con el Servidor del Firebird.

Si no recuerdas si un puerto está abierto o no, puedes escribir:

sudo ufw status verbose

Ejecutar el programa ISQL en Ubuntu

En la terminal se necesita escribir la ruta completa, si escribes solamente ISQL no funcionará.

/opt/firebird/bin/isql

el motivo es que hay otros programas que también se llaman isql y eso causa conflictos. Pero escribiendo la ruta completa se soluciona.

Conectarse a una Base de Datos desde Ubuntu

CONNECT /samba/public/sistemas/contabilidad/databases/marcela.fdb USER SYSDBA PASSWORD MiPassword;

si quieres o necesitas especificar la dirección IP de la computadora donde se instaló el Servidor del Firebird:

CONNECT 192.168.1.2:/samba/public/sistemas/contabilidad/databases/marcela.fdb USER SYSDBA PASSWORD MiPassword;

desde luego que la dirección IP, las carpetas, y el nombre de la Base de Datos pueden ser distintos en tu caso.

Asignando alias a las bases de datos

Conectarse a una Base de Datos en la computadora donde se instaló el Servidor del Firebird es muy fácil, cualquiera de las maneras mostradas en el apartado anterior funcionará bien. Pero Ubuntu (y Linux en general) son muy estrictos con el tema de los permisos y por lo tanto si usamos alias se nos facilitará la vida. Lo primero que debemos hacer es permitir que se realicen cambios en el archivo aliases.conf y para ello:

chmod 777 /opt/firebird/aliases.conf

Lo segundo es abrir ese archivo y escribir un alias para todas y cada una de las bases de datos que podrían ser accedidas desde otras computadoras. Por ejemplo:

marcela = /samba/public/sistemas/contabilidad/databases/marcela.fdb

Conectarse a una Base de Datos desde Windows

Aquí lo más conveniente es conectarse usando alguno de los alias especificados en el archivo aliases.conf, por ejemplo:

CONNECT 192.168.1.2:marcela USER SYSDBA PASSWORD MiPassword;

Conclusión

Instalar el Servidor del Firebird y conectarse a sus bases de datos es más complicado en Ubuntu (Linux) que en Windows pero tiene sus ventajas:

  • Mayor seguridad
  • Más barato en Internet (los VPS no cobran adicional si instalas Linux pero sí te cobran si instalas Windows)

Artículos relacionados

El índice del blog Firebird21

Usando la función LIST() para concatenar filas

3 comentarios

Con la función LIST() puedes obtener un string cuyo contenido serán todas las columnas que fueron agrupadas. Por ejemplo:

Listado 1. Todos los Presupuestos recibidos en cada fecha

SELECT
   PRC_FECHAX,
   LIST(PRC_NUMERO)
FROM
   PRESUPCONTCAB
GROUP BY
   PRC_FECHAX

En el Listado 1. estamos pidiendo agrupar por fechas y en cada fecha ver los números de todos los Presupuestos recibidos en esa fecha.

Captura 1. Todos los números de Presupuesto recibidos en cada fecha

Como puedes ver en la Captura 1., se obtienen para cada una de las fechas todos los Números de Presupuesto recibidos en esa fecha.

Pero ¿y si queremos ver todos los Números de Presupuesto recibidos? O sea, no agrupar por fechas sino tener a todos esos Números en una sola celda. En este caso escribiríamos:

Listado 2. Todos los Números de Presupuesto que están en la tabla

SELECT
   LIST(PRC_NUMERO)
FROM
   PRESUPCONTCAB
GROUP BY
   NULL

Al escribir GROUP BY NULL le estamos diciendo que queremos todas las filas de la tabla.

Captura 2. Todas las filas de la tabla se agrupan en una sola columna

Entonces, con la función agregada LIST() podemos tener los datos agrupados por algún criterio o todos los datos que están en la tabla.

Artículos relacionados:

La función LIST()

Ejemplo N° 043 – Usar la función LIST() para obtener todos los valores que tiene una columna

Ejemplo N° 047 – Usando funciones (2)

El índice del blog Firebird21

Cantidad de usuarios conectados a la Base de Datos

3 comentarios

A veces necesitamos saber cuantos usuarios están conectados a la Base de Datos. Para ello podríamos escribir algo como:

Listado 1. Cantidad de usuarios conectados a la Base de Datos actualmente

SELECT
  COUNT (MON$ATTACHMENT_ID)
FROM
  MON$ATTACHMENTS
WHERE
  MON$ATTACHMENT_ID <> CURRENT_CONNECTION AND
  MON$SYSTEM_FLAG = 0

Se debe escribir MON$SYSTEM_FLAG = 0 porque el Servidor del Firebird podría estar conectado para realizar tareas de recolección de la basura, por ejemplo. Si no se escribe MON$SYSTEM_FLAG = 0 entonces podrías ver una cantidad de usuarios mayor que la real. Esta columna solamente está disponible en Firebird 3 y posteriores, no funcionará en versiones anteriores de Firebird, en esos casos deberías eliminarla en el Listado 1. y escribir el SELECT sin ella.

Saber cuantos usuarios estás conectados actualmente a la Base de Datos es muy importante cuando deseas realizar tareas de mantenimiento. Por ejemplo, reemplazarla por un backup.

Artículos relacionados:

El índice del blog Firebird21

Usuarios y seguridad en Firebird 3 (6)

Deja un comentario

Cuando instalas el Servidor del Firebird 3 las conexiones a las bases de datos en esa computadora son todas embedded.

Y las conexiones embedded no requieren ni de usuario ni de contraseña.

Desde las otras computadoras, o sea desde las computadoras Cliente sí se deberá escribir el nombre del usuario y su contraseña para conseguir una conexión exitosa, pero en la computadora donde se instaló el Servidor esos datos no son requeridos.

¿Por qué no?

Porque después de instalar al Servidor puedes querer realizar algunas tareas administrativas, como por ejemplo, agregar usuarios que pueden conectarse a las bases de datos. Y para ello necesitas estar conectado a una Base de Datos. Es por ese motivo que el Firebird 3 permite las conexiones embedded y se instala junto con una Base de Datos de ejemplo llamada employee.fdb para que puedas conectarte a ella sin necesidad de tener un usuario o su contraseña.

Pero luego, muy probablemente ya no quieras que alguien pueda conectarse sin escribir nombre de usuario y contraseña, ¿se puede conseguir eso?

Sí.

Para ello, debes abrir el archivo FIREBIRD.CONF y cambiar sus «Providers».

Captura 1. Los valores del parámetro Providers, por defecto

En la Captura 1. vemos al parámetro Providers del archivo FIREBIRD.CONF con sus valores por defecto. Esa configuración permite que alguien se conecte de forma «embedded» en el Servidor.

Captura 2. Cambiando los valores para no permitir conexiones embedded

Si intercambiamos las posiciones de Loopback y de Remote, entonces las conexiones «embedded» ya no serán permitidas. Después de reiniciar al Servidor, para que una conexión a cualquier Base de Datos sea aceptada, se deberá escribir un nombre de usuario y una contraseña válidos.

Presta atención a estos dos puntos:

  1. Debes borrar/eliminar el símbolo de numeral # que se encuentra delante de la palabra Providers
  2. El cambio solamente tendrá efecto después de que reinicies el Servidor del Firebird

IMPORTANTE:

Si alguien tiene acceso a la computadora donde está instalado el Servidor del Firebird entonces esa persona podría modificar el archivo FIREBIRD.CONF y solamente necesitaría poner un símbolo de numeral # delante de la palabra «Providers» para que nuevamente las conexiones embedded sean aceptadas (después que se reinicie el Servidor). Por lo tanto, como siempre, la medida de seguridad más importante es no permitir que personas no autorizadas tengan acceso a la computadora donde se instaló el Servidor del Firebird.

Artículos relacionados:

Usuarios y seguridad en Firebird 3 (1)

Usuarios y seguridad en Firebird 3 (2)

Usuarios y seguridad en Firebird 3 (3)

Usuarios y seguridad en Firebird 3 (4)

Usuarios y seguridad en Firebird 3 (5)

El índice del blog Firebird21

Usuarios y seguridad en Firebird 3 (5)

Deja un comentario

En los cuatro artículos anteriores de esta serie ya hemos visto los conceptos más importantes que se deben conocer sobre este tema. Es hora de hacer un resumen.

Resumen sobre usuarios y seguridad en Firebird 3

Hasta Firebird 2.5.9 la administración de usuarios está centralizada. Eso significa que hay una sola «Base de Datos de seguridad», la cual se encuentra en la misma carpeta en donde se instaló el Firebird y cuyo nombre en la versión 2 es security2.fdb. La ventaja es que facilita la administración de usuarios, la desventaja es que el nivel de seguridad es muy bajo porque si un usuario puede conectarse a una Base de Datos entonces puede conectarse a todas las bases de datos, solamente necesita saber la ubicación y el nombre (o el alias) y listo.

Desde Firebird 3 la administración de usuarios puede continuar estando centralizada pero también puede ser descentralizada, significando eso que cada Base de Datos puede tener sus propios usuarios, los cuales podrían no tener derecho a conectarse a otras bases de datos.

En Firebird 3 la «Base de Datos de seguridad» por defecto se llama security3.fdb pero podemos cambiar ese nombre e inclusive moverla a otra carpeta, algo que antes era imposible hacer. Esto lo conseguimos modificando el nuevo parámetro SecurityDatabase que se encuentra en el archivo FIREBIRD.CONF

En el archivo DATABASES.CONF, el cual reemplaza y mejora al antiguo ALIASES.CONF, podemos especificar para cada Base de Datos cual será la «Base de Datos de seguridad» que usará. Que inclusive puede referenciarse a sí misma.

Si en el archivo DATABASES.CONF una Base de Datos no tiene un alias, o sí tiene un alias pero no tiene el parámetro SecurityDatabase, entonces usará a la «Base de Datos de seguridad» por defecto, o sea la especificada en el archivo FIREBIRD.CONF.

La creación de «Bases de Datos de seguridad» es muy fácil y podemos hacerla de dos maneras:

a) Copiando el archivo security3.fdb.empty a otra carpeta y luego cambiando su nombre, o

b) Creando una Base de Datos normal con el programa ISQL.EXE (o con cualquier otro programa que también nos permita crear bases de datos de Firebird 3) y que tendrá como nombre el de la «Base de Datos de seguridad» que necesitamos.

A continuación, nos conectamos a la Base de Datos normal como usuario SYSDBA y con el comando CREATE USER o con el comando CREATE OR ALTER USER, podremos crear todos los usuarios que necesitemos.

El usuario SYSDBA puede estar o no estar en la lista de usuarios de una Base de Datos normal.

Para ver los datos de los usuarios que pueden conectarse a una Base de Datos normal, existen dos seudo-tablas, llamadas SEC$USERS y SEC$USER_ATTRIBUTES. Por ejemplo: si te conectas a la Base de Datos alicia.fdb y escribes SELECT * FROM SEC$USERS entonces verás los nombres de todos los usuarios que pueden conectarse a alicia.fdb

Las contraseñas en Firebird 3 pueden tener hasta 255 caracteres aunque solamente los primeros 20 están garantizados de tener hash distintos. Hay que tener cuidado con la contraseña «masterkey» porque antes solamente sus primeros 8 caracteres eran válidos, ahora ya son válidos los 9 caracteres. De todas maneras no se recomienda que la contraseña del usuario SYSDBA sea «masterkey» porque es demasiado fácil descubrirla.

Para que un usuario puede utiliza los comandos CREATE USER, y CREATE OR ALTER USER, debe ser el SYSDBA o haberse conectado con el rol RDB$ADMIN.

No se recomienda que los usuarios comunes se conecten como SYSDBA. Hay programadores que hacen eso pero es considerada una muy mala práctica porque tira al piso todas las medidas de seguridad.

En la computadora donde se instaló el Servidor del Firebird el acceso a las bases de datos es por defecto «embedded», y eso significa que cualquier persona puede conectarse a cualquier Base de Datos. Mucho cuidado con este punto.

Para que puedan conectarse a una Base de Datos desde las computadoras Cliente, el parámetro RemoteAccess debe ser true.

Para una máxima seguridad, se debe poner el valor false en el parámetro RemoteAccess del archivo FIREBIRD.CONF; y en cada Base de Datos normal, poner el valor true en su parámetro RemoteAccess del archivo DATABASES.CONF.

Las «bases de datos de seguridad» deberían tener el parámetro RemoteAccess siempre en false para que nadie pueda conectarse a ellas desde las computadoras Cliente.

Artículos relacionados:

Usuarios y seguridad en Firebird 3 (1)

Usuarios y seguridad en Firebird 3 (2)

Usuarios y seguridad en Firebird 3 (3)

Usuarios y seguridad en Firebird 3 (4)

Usuarios y seguridad en Firebird 3 (6)

El índice del blog Firebird21

Usuarios y seguridad en Firebird 3 (4)

Deja un comentario

Con lo visto en los artículos anteriores ya tenemos para empezar con este tema de la administración de usuarios, pero aún hay más.

Los comandos que podemos usar son los siguientes:

CREATE USER username [ <options_list> ]
  TAGS ( <tag> [, <tag> ...] )

ALTER USER username [ SET ] [ <options_list> ]
  TAGS ( <tag> [, <tag> ...] )

ALTER CURRENT USER [ SET ] [ <options_list> ]
  TAGS ( <tag> [, <tag> ...] )

CREATE OR ALTER USER username [ SET ] [ <options_list> ]
  TAGS ( <tag> [, <tag> ...] )

DROP USER username [ USING PLUGIN plugin_name ]

<options_list> es una lista (que puede estar vacía) con las siguientes opciones:

PASSWORD 'password'
FIRSTNAME 'string'
MIDDLENAME 'string'
LASTNAME 'string'
ACTIVE
INACTIVE
USING PLUGIN nombre_del_plugin

Donde cada <tag> puede tener una de estas formas:

   tagname = 'string'

o contener el nombre del usuario que será eliminado:

   DROP tagname

Comentarios

Los comandos CREATE USERCREATE OR ALTER USER, y DROP USER, solamente pueden ser ejecutados por el usuario SYSDBA o por un usuario que tenga el rol RDB$ADMIN y se haya conectado con ese rol a la Base de Datos.

Cuando se crea un usuario la cláusula PASSWORD es obligatorio escribirla.

Cualquier usuario puede usar el comando ALTER USER o el comando ALTER CURRENT USER para cambiar su propio password, su FIRSTNAME, su MIDDLENAME, su LASTNAME, y sus «tags».

Un usuario no puede cambiar su estado (ACTIVE o INACTIVE) ni tampoco los datos de otros usuarios. Esas tareas solamente las puede realizar el usuario SYSDBA o un usuario que se conectó con el rol RDB$ADMIN.

En los comandos ALTER USER y ALTER OR CREATE USER, al menos una de estas cláusulas debe escribirse: PASSWORD, FIRSTNAME, MIDDLENAME, LASTNAME, ACTIVE, INACTIVETAGS

No es obligatorio llenar las cláusulas: FIRSTNAME, MIDDLENAME, LASTNAME. Cualquiera de ellas puede estar vacía.

La cláusula INACTIVE se usa para impedir que ese usuario pueda conectarse a la Base de Datos, pero sin eliminar al usuario. La cláusula ACTIVE nuevamente le permitirá conectarse.

TAGS permite asignarle atributos a un usuario. La cantidad de caracteres del valor asignado no puede ser mayor que 255.

Al escribir TAGS no se eliminan los TAGS anteriormente asignados.

Ejemplos

Listado 1. Creando, modificando, y borrando usuarios

CONNECT MiBaseDatos USER SYSDBA;

CREATE USER Secretaria PASSWORD 'MujerBonita';

ALTER USER Secretaria SET FIRSTNAME 'Deisy';

CREATE OR ALTER USER Secretaria SET PASSWORD 'LindaMujer';

DROP USER Secretaria;

ALTER CURRENT USER SET PASSWORD 'ASDFGhjklñ';

En el Listado 1. vemos un ejemplo de como usar los comandos que nos permiten crear, modificar, y borrar usuarios. Recuerda que debes estar conectado a una Base de Datos normal como usuario SYSDBA o como un usuario que tiene el rol RDB$ADMIN.

Listado 2. Usando la cláusula TAGS

ALTER USER Secretaria SET TAGS (altura = '1,65');

ALTER USER Secretaria SET TAGS (email = 'alguien@gmail.com');

ALTER USER Secretaria SET TAGS (codigo = 'S01', cargo = 'secre');

ALTER USER Secretaria SET TAGS (altura = '1,66');

ALTER USER Secretaria SET TAGS (DROP email);

La cláusula TAGS nos permite agregar todos los atributos que deseemos a un usuario. El nombre del atributo debe cumplir con las mismas reglas que se usan para dar nombres a tablas, vistas, stored procedures, etc. El valor del atributo es un string cuya longitud no puede pasar de 255 caracteres.

Al agregar un atributo, los atributos anteriormente creados continúan existiendo.

Se puede cambiar el valor de un atributo en cualquier momento. Como el atributo «altura» en el Listado 2. que pasó de ‘1,65’ a ‘1,66’.

Se puede también eliminar un atributo, como se ve en la última línea del Listado 2. que eliminó al atributo «email».

Listado 3. Mostrar los nombres de todos los usuarios

SELECT
  SEC$USER_NAME AS USUARIO
FROM
  SEC$USERS;
Captura 1. Viendo los nombres de todos los usuarios

El comando SELECT mostrado en el Listado 3. nos permite ver los nombres de todos los usuarios.

Recuerda que ningún usuario es imprescindible. Puedes borrar tanto a SYSDBA como a SECRETARIA, si quieres. Pero para poder establecer una conexión remota al menos debe existir un usuario.

Listado 4. Mostrar los datos y los TAGS de todos los usuarios

SELECT 
  CAST(U.SEC$USER_NAME AS CHAR(20)) AS USUARIO,
  U.SEC$FIRST_NAME                  AS PRIMER_NOMBRE,
  U.SEC$MIDDLE_NAME                 AS SEGUNDO_NOMBRE,
  U.SEC$LAST_NAME                   AS APELLIDO,
  U.SEC$ACTIVE                      AS ESTA_ACTIVO,
  U.SEC$ADMIN                       AS ES_ADMIN,
  CAST(A.SEC$KEY AS CHAR(10))       AS TAG_NOMBRE,
  CAST(A.SEC$VALUE AS CHAR(20))     AS TAG_VALOR
FROM 
  SEC$USERS U 
LEFT JOIN 
  SEC$USER_ATTRIBUTES A
    ON U.SEC$USER_NAME = A.SEC$USER_NAME;
Captura 2. Viendo los datos y los TAGS de los usuarios

En la Captura 2. vemos que el usuario SYSDBA está activo y tiene derechos de administrador. El usuario SECRETARIA tiene como nombre «Deisy», su altura es 1,66, su email es «alguien@gmail.com», está activo, pero no tiene derechos de administrador.

Las seudo-tablas SEC$USERS y SEC$USER_ATTRIBUTES

Las tablas SEC$USERS y SEC$USER_ATTRIBUTES no existen en la realidad, si las buscas no las encontrarás dentro de ninguna Base de Datos ya que son creadas en el preciso momento en que ejecutas un comando SELECT que las referencia (como en el Listado 3. y en el Listado 4.). Y siempre sus datos corresponden a los usuarios que pueden conectarse a la Base de Datos actual.

Por ejemplo, si estás conectado a la Base de Datos alicia.fdb y escribes SELECT * FROM SEC$USERS te mostrará los usuarios que pueden conectarse a alicia.fdb

Y si estás conectado a la Base de Datos veronica.fdb y escribes SELECT * FROM SEC$USERS, te mostrará los usuarios que pueden conectarse a veronica.fdb

Artículos relacionados:

Usuarios y seguridad en Firebird 3 (1)

Usuarios y seguridad en Firebird 3 (2)

Usuarios y seguridad en Firebird 3 (3)

Usuarios y seguridad en Firebird 3 (5)

Usuarios y seguridad en Firebird 3 (6)

El índice del blog Firebird21

Usuarios y seguridad en Firebird 3 (3)

1 comentario

Este tema de la administración de los usuarios es interesante y es importante, así que continuemos.

Como ya habíamos visto en el anterior artículo de esta serie, en nuestro archivo de texto plano llamado DATABASES.CONF tenemos lo siguiente:

Listado 1. El contenido del archivo DATABASES.CONF

MARCELA = D:\SISTEMAS\CONTABILIDAD\DATABASES\MARCELA.FDB
 
SILVIA = D:\SISTEMAS\CONTABILIDAD\DATABASES\SILVIA.FDB
{
  SecurityDatabase = E:\SEGURIDAD\USUARIOS_OK.FDB
}
 
SUSANA = D:\SISTEMAS\CONTABILIDAD\DATABASES\SUSANA.FDB
{
  SecurityDatabase = SUSANA
}
 
VERONICA = D:\SISTEMAS\CONTABILIDAD\DATABASES\VERONICA.FDB
{
  SecurityDatabase = VERONICA
}
 
security.db = E:\SEGURIDAD\PERMISOS.FDB

Por lo visto ahí podemos deducir que hay varias «bases de datos de seguridad» cuyos nombres son: usuarios_ok.fdb, susana.fdb, veronica.fdb, permisos.fdb. Entonces:

  1. ¿Cómo creamos una nueva «Base de Datos de seguridad»?
  2. ¿Cómo le agregamos usuarios?
  3. ¿Cómo conseguimos que la «Base de Datos de seguridad» sea la misma que la Base de Datos normal?

Crear una «Base de Datos de Seguridad»

Esto es muy simple. Y hay 2 formas de hacerlo.

  1. Copiamos el archivo security3.fdb.empty que se encuentra en la misma carpeta en donde se instaló al Firebird 3 y lo pegamos en cualquier otra carpeta y le cambiamos el nombre.

Por ejemplo: copiamos a security3.fdb.empty en la carpeta E:\SEGURIDAD\ y lo renombramos como usuarios_ok.fdb

2. Creamos una Base de Datos con el programa ISQL.EXE, algo como:

Captura 1. Creamos una Base de Datos vacía

Fíjate que aunque no exista aún el usuario SYSDBA debes escribir ese nombre.

Agregar usuarios a una «Base de Datos de seguridad»

Aquí debes prestar mucha atención porque esto no es intuitivo, no es lo que uno esperaría.

Y es que para agregarle usuarios no debes estar conectado a la «Base de Datos de seguridad» sino que debes estar conectado a una Base de Datos normal, cuyo parámetro SecurityDatabase apunte a la «Base de Datos de seguridad».

Por ejemplo: la «Base de Datos de seguridad» de silvia.fdb se especificó que sea: E:\SEGURIDAD\USUARIOS_OK.FDB, entonces para agregarle usuarios a usuarios_ok.fdb debes conectarte a silvia.fdb, y no a usuarios_ok.fdb como podrías suponer.

¿Verdad que es raro? pero bueno, ¡¡¡así funciona!!!

Otra cosa rara es que debes conectarte como SYSDBA aún cuando no exista un usuario SYSDBA.

El programa que puedes utilizar para realizar esta tarea se llama ISQL.EXE y viene incluido con el Firebird.

Captura 2. Usando al programa ISQL para conectarse a una Base de Datos

El usuario SYSDBA aún no existe, pero debe ser especificado. Y no necesitas escribir un password (ya que si lo escribes, será ignorado, no se usará).

Captura 3. Creando al usuario SYSDBA

NOTA: No es obligatorio que crees a un usuario con el nombre SYSDBA. Mucha gente se acostumbró a tener un super-usuario llamado SYSDBA pero no es obligatorio en Firebird 3 tenerlo.

Con el comando CREATE USER podemos crear a todos los usuarios que deseemos crear.

Captura 4. Creando al usuario ALEJANDRA

Hasta Firebird 2.5.9 un password podía tener un máximo de 8 caracteres. Desde Firebird 3 puede tener un máximo de 255 caracteres pero se provee seguridad por los primeros 20 caracteres (eso significa que si escribes un password de más de 20 caracteres existe una posibilidad remota, pero existe, de que su hash sea igual a un hash de hasta 20 caracteres).

Para que el usuario sea creado debes escribir el comando COMMIT.

Hacer que una Base de Datos normal sea su propia «Base de Datos de seguridad»

Esto es muy sencillo. Lo que debes hacer es que en el archivo DATABASES.CONF el parámetro SecurityDatabase tenga el mismo alias que la Base de Datos normal. Luego, reiniciar el Servidor del Firebird, luego conectarte a tu Base de Datos normal, y a partir de ese momento el comando CREATE USER creará a los usuarios dentro de la Base de Datos normal.

Por ejemplo: en el Listado 1. hay una Base de Datos cuyo alias es VERONICA. Si te conectas a VERONICA y escribes el comando CREATE USER ese usuario se creará dentro de VERONICA. ¿Por qué? porque el alias es igual al valor del parámetro SecurityDatabase.

Conectándose a una «Base de Datos de seguridad»

En Firebird 3 puedes conectarte a una «Base de Datos de seguridad» exactamente de la misma manera en que puedes conectarte a una Base de Datos normal.

Captura 5. La conexión a una «Base de Datos de seguridad» está permitida

Para ver las tablas puedes escribir el comando:

SHOW TABLES;

Y para ver el contenido escribes un SELECT, como siempre, algo como:

SELECT * FROM PLG$SRP;

En la tabla PLG$SRP se guardan los datos de los usuarios que tú has creado.

Agregando usuarios a la «Base de Datos de seguridad» por defecto.

La «Base de Datos de seguridad» por defecto es security3.fdb y se encuentra en la carpeta donde se instaló el Firebird 3., salvo que hayas cambiado el valor del parámetro SecurityDatabase del archivo FIREBIRD.CONF.

Igual que antes, para agregarle usuarios debes conectarte no a security3.fdb (o su reemplazante) sino a una Base de Datos normal. Por ejemplo, como alicia.fdb no tiene un alias en el archivo DATABASES.CONF entonces si te conectas a alicia.fdb y escribes el comando CREATE USER ese usuario será agregado a la «Base de Datos de seguridad» por defecto (que en nuestro ejemplo será permisos.fdb).

En este artículo, la «Base de Datos de seguridad» por defecto es E:\SEGURIDAD\PERMISOS.FDB porque es la especificada en el alias security.db del archivo DATABASES.CONF.

Agregando usuarios después de instalar al Firebird 3

Si inmediatamente después de haber instalado el Servidor del Firebird 3 ya quieres agregar usuarios, ¿cómo lo consigues?

Como recordarás, para agregar usuarios a una «Base de Datos de seguridad» debes estar previamente conectado a una Base de Datos normal.

Para que puedas hacerlo desde el primer instante es que al instalar al Firebird 3 se copia una Base de Datos de ejemplo llamada employee.fdb

Si no modificaste el parámetro SecurityDatabase del archivo FIREBIRD.CONF entonces la «Base de Datos de seguridad» será security3.fdb

Captura 6. Creando usuarios inmediatamente después de instalar al Servidor del Firebird

En este caso, la Base de Datos normal es employee.fdb, que trae como ejemplo el Firebird. Y la «Base de Datos de seguridad» por defecto es security3.fdb

Entonces, si no cambiaste a la «Base de Datos de seguridad» en el archivo FIREBIRD.CONF mediante el parámetro SecurityDatabase, el usuario WALTER y el usuario OJEDA se guardarán en security3.fdb

Artículos relacionados:

Usuarios y seguridad en Firebird 3 (1)

Usuarios y seguridad en Firebird 3 (2)

Usuarios y seguridad en Firebird 3 (4)

Usuarios y seguridad en Firebird 3 (5)

Usuarios y seguridad en Firebird 3 (6)

El índice del blog Firebird21

Older Entries