Unidad 3

Auditoría, trazabilidad y gobierno práctico de datos

Gestión de Seguridad y Desempeño de Bases de Datos (DBA)

Facultad de Informática Culiacán, Universidad Autónoma de Sinaloa

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Objetivos de la unidad

Objetivo 1 Eventos auditables

Explicar el propósito de la auditoría e identificar qué debe registrarse

Objetivo 2 Registro en un SGBD real

Configurar e interpretar accesos, privilegios y cambios de estructura

Objetivo 3 Bitácoras

Consultar, interpretar y conservar bitácoras

Objetivo 4 Políticas prácticas

Redactar reglas verificables de acceso, respaldo, retención y cambios

Objetivo 5 Gobierno práctico

Construir propietarios, catálogo y diccionario de datos

Evidencia final Expediente de auditoría

Configuración de auditoría con bitácora interpretada

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

De la Unidad 2 a la Unidad 3

Unidad 2: control de acceso

Usuarios, roles, privilegios, cifrado, hardening. Actúa antes de la operación: permite o niega.

Unidad 3: auditoría

Bitácoras, auditoría del dato, políticas y responsables. Actúa durante y después: registra, sea o no autorizado.

Una cuenta con privilegio legítimo de UPDATE puede cambiar un dato por error o por abuso. El control de acceso no lo detecta, porque la operación está permitida.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

El caso de la unidad

El RFC de María García (id = 3) aparece modificado en un reporte de facturación.

¿Quién?

app_ventas tiene UPDATE. También el DBA. ¿Alguien más?

¿Cuándo y desde dónde?

¿Qué aplicación, qué equipo, a qué hora?

¿Qué valor tenía?

Sin el valor anterior, facturación no puede corregirlo

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

La pregunta de la unidad

CONTROL DE ACCESO (Unidad 2)            "¿quién PUEDE?"
        │
        ▼
AUDITORÍA Y TRAZABILIDAD                "¿qué OCURRIÓ?"
   ┌────┼──────────────┐
   ▼    ▼              ▼
eventos  bitácoras     políticas prácticas
   └──────────┬────────┘
              ▼
   GOBIERNO PRÁCTICO DE DATOS            "¿quién RESPONDE?"
              ▼
   EVIDENCIAS PARA AUDITORÍA INTERNA
UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Actividad 1: Diagnóstico

  1. ¿Por qué ese control de acceso no permite responder quién cambió el RFC?
  2. ¿Qué tendría que haber existido antes del cambio para poder responder?
  3. ¿A quién le corresponde decidir cuál es el RFC correcto?

Registra tus ideas previas. Las retomaremos al final de la unidad.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

El gestor primero, el despliegue después

Un mismo servidor PostgreSQL o MongoDB puede estar instalado de varias formas. Las instrucciones del gestor son las mismas en todas.

Despliegue Qué cambia Qué no cambia
Instalación nativa (Linux, macOS, Windows) Cómo se inicia y reinicia el servicio, rutas de archivos SQL, psql, mongosh, parámetros del motor
Máquina virtual La dirección del servidor Lo mismo
Contenedor Cómo se abre una terminal y se reinicia Lo mismo
Servicio administrado en la nube (DBaaS) Los parámetros y las bitácoras se gestionan desde la consola del proveedor Los conceptos: qué registrar, cómo interpretarlo, cuánto conservarlo

En esta unidad aprenderás a preguntarle al propio motor dónde está su configuración y su bitácora, en lugar de depender de cómo se instaló.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Dos tipos de sesión con psql

Sesión de administrador

Configura el servidor y lee la bitácora.
psql -U postgres -d comercial
En algunos despliegues se abre de otra forma, por ejemplo sudo -u postgres psql en Linux.

Sesión por red

Simula a la aplicación y a los usuarios, que entran con contraseña. Es idéntica en cualquier despliegue.

psql "postgresql://app_ventas:Ventas_Practica_2026@127.0.0.1/comercial?application_name=app-ventas-web" -c "SELECT 1"

Las contraseñas son de práctica. En las evidencias se sustituyen por <REDACTED>.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

La cadena de conexión, pieza por pieza

postgresql://app_ventas:Ventas_Practica_2026@127.0.0.1/comercial?application_name=app-ventas-web
Parte Significado
postgresql:// Protocolo de PostgreSQL
app_ventas:Ventas_Practica_2026@ Usuario (rol) y contraseña
127.0.0.1 Servidor. Al usar una dirección, la conexión viaja por TCP y se evalúan las reglas host de pg_hba.conf
/comercial Base de datos
?application_name=... Nombre de la aplicación que verá el servidor (%a en la bitácora)
-c "..." Ejecuta esa sentencia y termina. Cada -c es una sentencia

La misma cadena funciona en Bash, Zsh y PowerShell. Si el servidor está en otro equipo, solo cambia 127.0.0.1. En producción la contraseña no va en la cadena: proviene de .pgpass o de un gestor de secretos (Unidad 2).

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Preguntarle al motor por su instalación

SELECT version();
SHOW data_directory;
SHOW config_file;
SHOW hba_file;
 PostgreSQL 16.14 (Debian 16.14-1.pgdg13+1) on x86_64-pc-linux-gnu, ...
 /var/lib/postgresql/data
 /var/lib/postgresql/data/postgresql.conf
 /var/lib/postgresql/data/pg_hba.conf

Dentro de psql, las órdenes que empiezan con \ (\q, \x, \password) son metacomandos: los ejecuta el cliente, no el servidor.

Las rutas dependen del despliegue. Las consultas son las mismas en todos

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.1

Auditoría de bases de datos

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.1 | Auditoría: qué es y qué no es

Control de acceso Auditoría
Pregunta ¿Quién puede hacerlo? ¿Quién lo hizo, cuándo, desde dónde?
Momento Antes de la operación Durante y después
Resultado Permite o niega Registra, sea o no autorizado
Ejemplo GRANT UPDATE ON clientes TO app_ventas Línea de bitácora con el UPDATE

Auditar es registrar de forma sistemática lo que ocurre en una base de datos para que pueda usarse después como evidencia.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.1 | Tres ideas que no debes olvidar

No impide nada

La auditoría registra. Una operación permitida pero indebida solo se descubre con el registro.

No se configura después

Lo que no se registró en su momento no puede reconstruirse desde la bitácora.

Registrar no basta

La bitácora es evidencia solo si se conserva y alguien puede interpretarla.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.1 | Eventos auditables

Tipo Ejemplo ¿Por qué se audita?
Acceso exitoso Inicio de sesión de app_ventas Quién estuvo dentro y cuándo
Acceso fallido Contraseña incorrecta Intentos no autorizados, fuerza bruta
Privilegios GRANT, REVOKE, CREATE ROLE Quien obtiene privilegios puede hacer lo demás
Estructura ALTER TABLE, DROP, migraciones Puede romper la aplicación o borrar datos
Datos sensibles Modificar o leer un RFC Responsabilidad sobre datos personales
Error de autorización permission denied Alguien intentó lo que no le correspondía
Configuración Apagar el registro Quien apaga la auditoría actúa sin rastro
UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo: un evento de cada tipo en una bitácora real

Tipo Línea registrada por PostgreSQL 16 (resumida)
Acceso exitoso user=app_ventas ... LOG: connection authorized: user=app_ventas database=comercial application_name=app-ventas-web
Acceso fallido user=app_ventas ... FATAL: password authentication failed for user "app_ventas"
Privilegios user=postgres ... LOG: statement: GRANT UPDATE ON clientes TO app_ventas
Estructura user=postgres ... LOG: statement: ALTER TABLE clientes ADD COLUMN segmento VARCHAR(20)
Datos user=app_ventas ... LOG: statement: UPDATE clientes SET telefono = '6679990000' WHERE id = 3
Error de autorización user=soporte_ana ... ERROR: permission denied for table clientes
Configuración LOG: parameter "log_statement" changed to "mod"

Durante la unidad aprenderás a configurar el servidor para que produzca cada una de estas líneas y a leerlas campo por campo.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.1 | No todo merece registrarse

Normalmente no prioritario

Un usuario consulta su propio perfil

Depende del volumen

Un usuario consulta miles de registros en pocos minutos

Relevante por contexto

Se reinicia el servicio: explica huecos en la bitácora

Registrar todo produce volumen, costo de almacenamiento y un nuevo riesgo: la bitácora se convierte en otro depósito de datos sensibles.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Actividad 2: Clasificación de eventos auditables

Clasifica cada evento como auditable o no auditable prioritario y justifica:

  1. Un usuario consulta su propio perfil.
  2. Un administrador otorga permisos de escritura a otro usuario.
  3. Se elimina una columna de una tabla.
  4. Un usuario lee un registro de nómina que no le corresponde.
  5. Se reinicia el servicio.
  6. Un usuario consulta muchos registros en poco tiempo.

Relaciona cada justificación con seguridad, cumplimiento o responsabilidad, no con "porque sí".

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.1 y 3.2

Bitácoras en PostgreSQL

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.2 | ¿Dónde está la bitácora? Depende del despliegue

PostgreSQL escribe sus mensajes en su salida de error. Con la configuración por defecto, quien decide a dónde va es el mecanismo de despliegue:

Despliegue Destino habitual
Linux (paquetes) Un archivo que administra el script de arranque
macOS (Homebrew) El archivo de bitácora del servicio
Windows (instalador) Archivos en el directorio de datos
Contenedor La salida del contenedor

Solución del gestor: el colector de bitácora (logging_collector = on). El propio servidor escribe sus archivos dentro de log_directory, en cualquier plataforma.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo guiado: el servidor administra su bitácora

ALTER SYSTEM SET logging_collector = on;   -- requiere reiniciar el servicio
SELECT pg_current_logfile();
          pg_current_logfile
--------------------------------------
 log/postgresql-2026-10-25_224920.log
SELECT linea
FROM regexp_split_to_table(pg_read_file(pg_current_logfile()), E'\n') AS linea;
Parte Qué hace
pg_current_logfile() Ruta del archivo vigente, relativa al directorio de datos
pg_read_file(...) Devuelve el archivo como texto. Solo superusuarios
regexp_split_to_table(..., E'\n') Una fila por línea

Fuente: documentación oficial de PostgreSQL 16, "System Information Functions" y "System Administration Functions"

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Leer y filtrar la bitácora con SQL

Una vista guarda la consulta con nombre. Se crea en un esquema sin acceso público:

CREATE SCHEMA dba;
REVOKE ALL ON SCHEMA dba FROM PUBLIC;
CREATE VIEW dba.bitacora AS
SELECT t.n AS num, t.linea
FROM regexp_split_to_table(pg_read_file(pg_current_logfile()), E'\n') WITH ORDINALITY AS t(linea, n)
WHERE t.linea <> '';
SELECT num, linea FROM dba.bitacora ORDER BY num DESC LIMIT 10;      -- últimas 10
SELECT linea FROM dba.bitacora WHERE linea LIKE '%statement:%';      -- sentencias
SELECT linea FROM dba.bitacora WHERE linea ~ '(FATAL|ERROR)';        -- expresión regular
SELECT count(*) FROM dba.bitacora WHERE linea LIKE '%password authentication failed%';

Variante: con acceso al archivo, también se lee con tail, grep o Select-String. Los formatos csvlog y jsonlog facilitan procesarlo con otras herramientas.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.2 | Parámetros que controlan la bitácora

Parámetro Qué controla Por defecto
logging_collector Si el servidor escribe sus propios archivos (requiere reinicio) off
log_connections Cada intento de conexión off
log_disconnections Fin de sesión y duración off
log_line_prefix Contexto de cada línea %m [%p]
log_statement Qué sentencias se registran none
log_min_error_statement Sentencia que causó un error error

Fuente: documentación oficial de PostgreSQL, "Error Reporting and Logging"

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo guiado: configuración por defecto

SELECT name, setting, source FROM pg_settings
WHERE name IN ('log_connections','log_disconnections','log_line_prefix','log_statement');
        name        | setting  | source
--------------------+----------+---------
 log_connections    | off      | default
 log_disconnections | off      | default
 log_line_prefix    | %m [%p]  | default
 log_statement      | none     | default

Con esta configuración no se registra quién se conecta ni qué ejecuta. La línea tampoco incluye usuario ni IP.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo guiado: el incidente sin bitácora

La aplicación cambia el RFC:

psql "postgresql://app_ventas:Ventas_Practica_2026@127.0.0.1/comercial?application_name=app-ventas-web" -c "UPDATE clientes SET rfc = 'GAMA780912XXX' WHERE id = 3"
UPDATE 1

Buscamos evidencia:

SELECT linea FROM dba.bitacora WHERE linea ILIKE '%update%' OR linea LIKE '%app_ventas%';
(0 rows)

Ninguna línea. Ni el UPDATE, ni la conexión de app_ventas. No hay forma de demostrar quién hizo el cambio.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.2 | Niveles de log_statement

Valor Registra
none Nada
ddl CREATE, ALTER, DROP, y también GRANT, REVOKE, COMMENT
mod Lo anterior + INSERT, UPDATE, DELETE, TRUNCATE, COPY FROM
all Todo, incluidas las consultas SELECT

Elegir el nivel es un equilibrio entre evidencia, volumen y riesgo de registrar datos sensibles.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo guiado: configurar con ALTER SYSTEM

ALTER SYSTEM SET log_connections = on;
ALTER SYSTEM SET log_disconnections = on;
ALTER SYSTEM SET log_line_prefix = '%m [%p] user=%u db=%d app=%a client=%h ';
ALTER SYSTEM SET log_statement = 'ddl';
SELECT pg_reload_conf();
Marcador Significado
%m / %p Fecha y hora con milisegundos / PID del proceso
%u / %d Usuario / base de datos
%a / %h Aplicación (application_name) / IP del cliente

Fuente: documentación oficial de PostgreSQL, "ALTER SYSTEM". Los valores se guardan en postgresql.auto.conf

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.2 | Cuidado con la prioridad de la configuración

1. Opciones -c al arrancar el servidor     (mayor prioridad)
2. postgresql.auto.conf  ← ALTER SYSTEM
3. postgresql.conf                          (menor prioridad)

Si el servicio se arranca con -c log_statement=ddl (en un script de servicio o en la definición de un contenedor), un ALTER SYSTEM SET log_statement = 'mod' no surte efecto. pg_settings.source mostrará command line.

SELECT name, setting, source, sourcefile FROM pg_settings WHERE name = 'log_statement';

Fuente: documentación oficial de PostgreSQL, "Setting Parameters"

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo guiado: el cambio de configuración queda registrado

11 | ... [1] user= db= app= client= LOG:  parameter "log_statement" changed to "ddl"
10 | ... [1] user= db= app= client= LOG:  parameter "log_line_prefix" changed to "%m [%p] user=%u ..."
 9 | ... [1] LOG:  parameter "log_disconnections" changed to "on"
 8 | ... [1] LOG:  parameter "log_connections" changed to "on"
Lo que sí quedó

El nuevo estado y el momento en que entró en vigor, registrados por el proceso principal (PID 1)

Lo que no quedó

Las sentencias ALTER SYSTEM: cuando se ejecutaron, log_statement aún era none

pg_reload_conf() es asíncrona. En la verificación, una consulta a pg_settings en el mismo bloque aún mostró los valores anteriores. Comprueba con una consulta nueva.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.1 | Accesos fallidos: revisa las reglas de autenticación

SELECT line_number, type, address, auth_method FROM pg_hba_file_rules WHERE database = '{all}';
 line_number | type  |  address  |  auth_method
-------------+-------+-----------+---------------
         117 | local |           | trust
         119 | host  | 127.0.0.1 | trust
         128 | host  | all       | scram-sha-256

Con trust, cualquier conexión que coincida con la regla entra sin contraseña. Nunca verás un acceso fallido. Es frecuente en instalaciones de desarrollo.

Se corrige editando el archivo que indica SHOW hba_file y ejecutando SELECT pg_reload_conf();. Relación con la Unidad 2 (hardening): una regla trust también debilita lo que la bitácora puede demostrar sobre la identidad.

Fuente: documentación oficial de PostgreSQL 16, "pg_hba_file_rules"

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo guiado: accesos en la bitácora

psql "postgresql://app_ventas:incorrecta@127.0.0.1/comercial" -c "SELECT 1"
psql "postgresql://usuario_inexistente:x@127.0.0.1/comercial" -c "SELECT 1"
22:50:00.334 UTC [91] user=app_ventas db=comercial app=[unknown] client=127.0.0.1 FATAL:  password authentication failed for user "app_ventas"
22:50:00.334 UTC [91] ... DETAIL:  Connection matched file "/var/lib/postgresql/data/pg_hba.conf" line 119: "host all all 127.0.0.1/32 scram-sha-256"
22:50:00.462 UTC [98] user=usuario_inexistente ... FATAL:  password authentication failed for user "usuario_inexistente"
22:50:00.462 UTC [98] ... DETAIL:  Role "usuario_inexistente" does not exist.
22:50:00.565 UTC [105] user=app_ventas ... LOG:  connection authenticated: identity="app_ventas" method=scram-sha-256
22:50:00.566 UTC [105] user=app_ventas ... LOG:  connection authorized: user=app_ventas database=comercial application_name=app-ventas-web
22:50:00.568 UTC [105] user=app_ventas db=comercial app=app-ventas-web client=127.0.0.1 LOG:  disconnection: session time: 0:00:00.010

El cliente recibe el mismo mensaje en ambos fallos. Solo el servidor sabe que el rol no existe.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.2 | Leer una línea campo por campo

2026-10-25 22:50:00.334 UTC [91] user=app_ventas db=comercial app=[unknown] client=127.0.0.1 FATAL:  password authentication failed
Parte Valor Responde
%m 2026-10-25 22:50:00.334 UTC ¿Cuándo?
%p 91 ¿Qué proceso? Agrupa las líneas de una sesión
%u / %d app_ventas / comercial ¿Con qué rol y en qué base?
%a [unknown] ¿Qué aplicación? Aún desconocida al fallar
%h 127.0.0.1 ¿Desde dónde?
Mensaje FATAL: password authentication failed ¿Qué ocurrió?
UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo guiado: privilegios y estructura

REVOKE UPDATE ON clientes FROM soporte_ana;
GRANT UPDATE ON clientes TO app_ventas;
ALTER TABLE clientes ADD COLUMN segmento VARCHAR(20);
22:50:09.341 UTC [119] user=postgres db=comercial app=psql client=[local] LOG:  statement: REVOKE UPDATE ON clientes FROM soporte_ana
22:50:09.367 UTC [119] user=postgres db=comercial app=psql client=[local] LOG:  statement: GRANT UPDATE ON clientes TO app_ventas
22:50:09.372 UTC [119] user=postgres db=comercial app=psql client=[local] LOG:  statement: ALTER TABLE clientes ADD COLUMN segmento VARCHAR(20)

Con log_statement = 'ddl' ya quedan registrados los cambios de privilegios y de estructura, con usuario y hora. client=[local] indica una conexión por el socket local del servidor.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo guiado: la bitácora también filtra secretos

CREATE ROLE rol_temporal LOGIN PASSWORD 'Temporal_Practica_2026';
SELECT linea FROM dba.bitacora WHERE linea LIKE '%rol_temporal%';
LOG:  statement: CREATE ROLE rol_temporal LOGIN PASSWORD 'Temporal_Practica_2026'

La contraseña quedó en texto claro en la bitácora. Borrar el rol no la borra del registro.

Alternativa: \password

psql calcula el resumen SCRAM y envía solo eso: ALTER USER app_ventas PASSWORD 'SCRAM-SHA-256$4096:...'

Consecuencia

La bitácora se protege como la base de datos: acceso restringido, revisión antes de compartirla

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo guiado: ddl no registra el UPDATE

Con log_statement = 'ddl' se repite el cambio de RFC: la bitácora muestra la conexión y la desconexión de app_ventas, pero no el UPDATE.

ALTER SYSTEM SET log_statement = 'mod';
SELECT pg_reload_conf();
22:50:19.459 UTC [155] user=postgres ... LOG:  statement: ALTER SYSTEM SET log_statement = 'mod'
22:50:19.488 UTC [1]   user= db= app= client= LOG:  parameter "log_statement" changed to "mod"
22:50:20.601 UTC [162] user=app_ventas db=comercial app=app-ventas-web client=127.0.0.1 LOG:  statement: UPDATE clientes SET telefono = '6679990000' WHERE id = 3

Ahora sí: quién, cuándo, desde dónde, con qué aplicación y qué sentencia.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.2 | Lo que la bitácora todavía no muestra

El valor anterior

Sabemos qué se escribió en telefono, no qué se perdió

Las lecturas

El SELECT que leyó el RFC no aparece con mod

La persona

Se registra el rol. Si varias personas comparten app_ventas, no se distinguen

Las dos primeras limitaciones se resuelven con una tabla de auditoría y con pgaudit, como verás a continuación. La tercera es un problema de gestión de credenciales (Unidad 2).

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo guiado: errores de autorización

psql "postgresql://soporte_ana:Soporte_Practica_2026@127.0.0.1/comercial" -c "DELETE FROM clientes WHERE id = 5"
user=soporte_ana db=comercial app=psql client=127.0.0.1 ERROR:  permission denied for table clientes
user=soporte_ana db=comercial app=psql client=127.0.0.1 STATEMENT:  DELETE FROM clientes WHERE id = 5
user=postgres db=comercial app=psql client=[local] ERROR:  role "soporte_ana" cannot be dropped because some objects depend on it
user=postgres db=comercial app=psql client=[local] DETAIL:  privileges for table clientes
user=postgres db=comercial app=psql client=[local] STATEMENT:  DROP ROLE soporte_ana

log_min_error_statement = error registra la sentencia que falló aunque log_statement sea none. Un intento rechazado es tan relevante como una operación exitosa.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo guiado: pg_stat_activity

SELECT pid, usename, application_name, client_addr, state, left(query, 30) AS query
FROM pg_stat_activity WHERE backend_type = 'client backend';
 pid |   usename   | application_name | client_addr | state  |             query
-----+-------------+------------------+-------------+--------+--------------------------------
 196 | postgres    | psql             |             | active | SELECT pid, usename, applicati
 189 | soporte_ana | reporte-mensual  | 127.0.0.1   | active | SELECT pg_sleep(90)
Bitácora pg_stat_activity
Historia: lo que ocurrió Fotografía: lo que ocurre ahora
Se conserva si se conserva la bitácora La fila desaparece al terminar la sesión

El PID relaciona ambas fuentes. En la Unidad IV se usará para diagnosticar desempeño.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.2 | Exportar y proteger la bitácora

psql -U postgres -d comercial -At -c "SELECT replace(pg_read_file(pg_current_logfile()), 'Temporal_Practica_2026', '<REDACTED>')" > evidencias/bitacora.log

-A quita la alineación, -t los encabezados. replace retira el secreto antes de que salga del servidor. > envía la salida a un archivo y lo reemplaza si existe.

Sistema Resumen SHA-256 del archivo
Linux sha256sum evidencias/bitacora.log
macOS shasum -a 256 evidencias/bitacora.log
Windows Get-FileHash evidencias/bitacora.log -Algorithm SHA256

El resumen (hash) es una huella de 64 caracteres hexadecimales. Cualquier cambio en el archivo produce una huella distinta. No impide modificarlo: permite demostrar si fue modificado, siempre que la huella se guarde en otro lugar.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo: el hash detecta una alteración

shasum -a 256 bitacora.log
ad10b928960869be89354c5c522695b9122620372db29bd89a2c519057550e6a  bitacora.log

Alguien cambia app_ventas por soporte_ana en una sola línea del archivo:

sed -i '' 's/app_ventas/soporte_ana/' bitacora.log     # en Linux: sed -i 's/.../.../' archivo
shasum -a 256 bitacora.log
1f06e95f47838d699b8d2bb8770ea39f65bf979ec9eb6825642837ad6d705ec2  bitacora.log

sed -i 's/viejo/nuevo/' reemplaza texto dentro del archivo. Aquí simula una manipulación. La huella cambió por completo: la alteración queda en evidencia.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.1.6 y 3.2

Auditoría del dato

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.2 | Tres niveles de auditoría

Nivel Registra Ejemplo Mecanismo
Sentencia El texto SQL UPDATE clientes SET rfc = ... log_statement
Dato Valor antes y después, por registro rfc: GAMA780912XYZ → GAMA780912ZZZ Disparador + tabla
Objeto Qué tabla o columna se leyó o escribió Lectura de clientes.rfc pgaudit (opcional)

Un UPDATE sin WHERE genera una línea en la bitácora y una fila por registro afectado en la tabla de auditoría.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.2 | Diseñar el registro de auditoría

Campo Responde
momento TIMESTAMPTZ ¿Cuándo? Con zona horaria
usuario_sesion TEXT ¿Quién provocó el cambio?
aplicacion TEXT ¿Con qué aplicación? (la declara el cliente)
ip_cliente INET ¿Desde dónde?
operacion TEXT INSERT, UPDATE o DELETE
valores_antes JSONB ¿Qué se perdió?
valores_despues JSONB ¿Qué se escribió?

La tabla de auditoría también contiene datos personales. Necesita control de acceso y política de conservación propios.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo guiado: esquema y tabla de auditoría

CREATE SCHEMA auditoria;
REVOKE ALL ON SCHEMA auditoria FROM PUBLIC;

CREATE TABLE auditoria.cambios_clientes (
    id_evento        BIGSERIAL PRIMARY KEY,
    momento          TIMESTAMPTZ NOT NULL DEFAULT now(),
    usuario_sesion   TEXT        NOT NULL DEFAULT session_user,
    usuario_efectivo TEXT        NOT NULL DEFAULT current_user,
    aplicacion       TEXT        DEFAULT current_setting('application_name'),
    ip_cliente       INET        DEFAULT inet_client_addr(),
    operacion        TEXT        NOT NULL,
    id_cliente       BIGINT,
    valores_antes    JSONB,
    valores_despues  JSONB
);
UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo guiado: la función de disparador

CREATE OR REPLACE FUNCTION auditoria.registrar_cambio_cliente()
RETURNS trigger LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, public
AS $$
BEGIN
    IF TG_OP = 'INSERT' THEN
        INSERT INTO auditoria.cambios_clientes (operacion, id_cliente, valores_despues)
        VALUES (TG_OP, NEW.id, to_jsonb(NEW));
        RETURN NEW;
    ELSIF TG_OP = 'UPDATE' THEN
        INSERT INTO auditoria.cambios_clientes (operacion, id_cliente, valores_antes, valores_despues)
        VALUES (TG_OP, NEW.id, to_jsonb(OLD), to_jsonb(NEW));
        RETURN NEW;
    ELSIF TG_OP = 'DELETE' THEN
        INSERT INTO auditoria.cambios_clientes (operacion, id_cliente, valores_antes)
        VALUES (TG_OP, OLD.id, to_jsonb(OLD));
        RETURN OLD;
    END IF;
    RETURN NULL;
END;
$$;

Fuente: documentación oficial de PostgreSQL, "Trigger Functions", ejemplo 43.4 (función de disparador para auditoría)

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo guiado: asociar el disparador

REVOKE ALL ON FUNCTION auditoria.registrar_cambio_cliente() FROM PUBLIC;

CREATE TRIGGER trg_auditoria_clientes
AFTER INSERT OR UPDATE OR DELETE ON clientes
FOR EACH ROW EXECUTE FUNCTION auditoria.registrar_cambio_cliente();
AFTER

Registra lo que efectivamente ocurrió

FOR EACH ROW

Una fila de auditoría por registro afectado

TG_OP, OLD, NEW

Operación, registro anterior, registro nuevo

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.2 | SECURITY DEFINER y search_path

¿Por qué SECURITY DEFINER?

app_ventas debe provocar la escritura en la auditoría sin tener privilegio de escribir en ella. La función se ejecuta con los privilegios de su propietario.

¿Por qué fijar search_path?

Sin él, un usuario podría crear objetos con el mismo nombre en otro esquema y lograr que la función los use con privilegios de propietario.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo guiado: el incidente auditado

psql "postgresql://app_ventas:Ventas_Practica_2026@127.0.0.1/comercial?application_name=app-ventas-web" -c "UPDATE clientes SET rfc = 'GAMA780912ZZZ' WHERE id = 3"
id_evento        | 1
momento          | 2026-10-25 22:50:52.903439+00
usuario_sesion   | app_ventas
usuario_efectivo | postgres
aplicacion       | app-ventas-web
ip_cliente       | 127.0.0.1
operacion        | UPDATE

Dentro de una función SECURITY DEFINER, current_user es el propietario de la función. Si solo se registrara current_user, todos los cambios parecerían hechos por postgres.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo guiado: ¿qué campo cambió?

SELECT a.id_evento, a.usuario_sesion, a.ip_cliente, d.key AS campo,
       a.valores_antes ->> d.key AS antes, d.value #>> '{}' AS despues
FROM auditoria.cambios_clientes a
CROSS JOIN LATERAL jsonb_each(a.valores_despues) d
WHERE a.operacion = 'UPDATE'
  AND a.valores_antes -> d.key IS DISTINCT FROM d.value
ORDER BY a.id_evento;
 id_evento | usuario_sesion | ip_cliente | campo |     antes     |    despues
-----------+----------------+------------+-------+---------------+---------------
         1 | app_ventas     | 127.0.0.1  | rfc   | GAMA780912XYZ | GAMA780912ZZZ

Ahora facturación puede restaurar el valor anterior.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo guiado: altas y bajas

 id_evento | usuario_sesion |   aplicacion   | operacion | id_cliente |   rfc_antes   |  rfc_despues
-----------+----------------+----------------+-----------+------------+---------------+---------------
         1 | app_ventas     | app-ventas-web | UPDATE    |          3 | GAMA780912XYZ | GAMA780912ZZZ
         2 | postgres       | psql           | INSERT    |          6 |               | RUPE950101AAA
         3 | postgres       | psql           | DELETE    |          6 | RUPE950101AAA |

El cliente 6 ya no existe en clientes, pero sus datos siguen en la auditoría. Conflicto con la política de retención de la Unidad 2: ¿quién decide cuánto tiempo se conserva?

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo guiado: intentar borrar la evidencia

Desde la aplicación:

DELETE FROM auditoria.cambios_clientes                       → ERROR: permission denied for schema auditoria
ALTER TABLE clientes DISABLE TRIGGER trg_auditoria_clientes  → ERROR: must be owner of table clientes

Desde el administrador (desactiva, cambia y reactiva): la tabla de auditoría no registra el cambio, pero la bitácora sí, incluido el intento fallido de la aplicación:

user=app_ventas ... LOG:  statement: ALTER TABLE clientes DISABLE TRIGGER trg_auditoria_clientes
user=postgres ... LOG:  statement: ALTER TABLE clientes DISABLE TRIGGER trg_auditoria_clientes
user=postgres ... LOG:  statement: UPDATE clientes SET rfc = 'GAMA780912GHI' WHERE id = 3
user=postgres ... LOG:  statement: ALTER TABLE clientes ENABLE TRIGGER trg_auditoria_clientes
UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.2 | Un mecanismo audita al otro

Tabla de auditoría      →  detalle del dato (antes y después)
                           la desactiva el propietario de la tabla

Bitácora del servidor   →  registra que la auditoría se desactivó
                           la altera quien controla el servidor

Ningún mecanismo dentro del servidor protege contra un administrador con control total. Por eso las organizaciones envían las bitácoras a otro sistema y separan a quien opera la base de quien custodia la evidencia (separación de funciones, Unidad 2).

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.2 | El límite del disparador: las lecturas

No existe disparador para SELECT. Con log_statement = 'mod', la bitácora tampoco registra consultas.

Alternativa Ventaja Desventaja
log_statement = 'all' No requiere instalar nada Registra todas las consultas de todas las tablas
Entregar el dato mediante una función que registre su uso Control preciso Requiere cambiar la aplicación
pgaudit, auditoría de objeto Lecturas por tabla y por columna Requiere instalar una extensión
UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.2 | pgaudit (práctica avanzada opcional)

pgaudit no forma parte de la distribución básica de PostgreSQL. Se instala su paquete en el servidor y la biblioteca se carga al arrancar.

SELECT name, default_version FROM pg_available_extensions WHERE name = 'pgaudit';
CREATE EXTENSION pgaudit;
-- ERROR:  pgaudit must be loaded via shared_preload_libraries

ALTER SYSTEM SET shared_preload_libraries = 'pgaudit';
SELECT pg_reload_conf();
SELECT name, setting, pending_restart FROM pg_settings WHERE name = 'shared_preload_libraries';
--  shared_preload_libraries |         | t        ← espera un reinicio

Después de reiniciar el servicio: CREATE EXTENSION pgaudit; → versión 16.1.

Fuente: repositorio oficial del proyecto pgaudit

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Recargar o reiniciar: cómo saberlo

Parámetro Cambia con Por qué
log_statement, log_connections, log_line_prefix Recarga (pg_reload_conf()) Cada proceso puede leer el nuevo valor sin detenerse
logging_collector Reinicio El proceso colector se crea al arrancar el servidor
shared_preload_libraries Reinicio Las bibliotecas se cargan en memoria al arrancar

La columna pending_restart de pg_settings responde la pregunta sin memorizar la tabla. El comando de reinicio depende del despliegue (servicio del sistema, Homebrew, servicios de Windows, contenedor). El diagnóstico es el mismo en todos.

Fuente: documentación oficial de PostgreSQL 16, "Setting Parameters" y "ALTER SYSTEM"

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo guiado: auditoría de objeto con pgaudit

El rol auditor no inicia sesión. Sus privilegios son un filtro de qué columnas auditar:

CREATE EXTENSION pgaudit;
CREATE ROLE auditor_datos NOLOGIN;
GRANT SELECT (rfc, telefono), UPDATE (rfc, telefono) ON clientes TO auditor_datos;
ALTER SYSTEM SET pgaudit.log = 'role, ddl';
ALTER SYSTEM SET pgaudit.role = 'auditor_datos';
ALTER SYSTEM SET log_line_prefix = '%m [%p] user=%u db=%d app=%a client=%h ';
SELECT pg_reload_conf();
user=app_ventas ... AUDIT: OBJECT,1,1,READ,SELECT,TABLE,public.clientes,"SELECT nombre, rfc FROM clientes WHERE id = 3",<not logged>
user=app_ventas ... AUDIT: OBJECT,2,1,READ,SELECT,TABLE,public.clientes,SELECT * FROM clientes WHERE id = 4,<not logged>
user=app_ventas ... AUDIT: OBJECT,3,1,WRITE,UPDATE,TABLE,public.clientes,UPDATE clientes SET rfc = 'LOAA850315XXX' WHERE id = 1,<not logged>
user=postgres   ... AUDIT: SESSION,1,1,ROLE,GRANT,TABLE,,GRANT SELECT ON clientes TO soporte_ana,<not logged>

SELECT nombre, ciudad ... y UPDATE ... SET ciudad ... no aparecen.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.2 | Advertencias del propio pgaudit

Volumen

Puede generar un volumen muy grande de registros, agotar disco y afectar la latencia. Se recomienda limitar el alcance con auditoría de objeto.

Superusuarios

El README oficial indica que los superusuarios no pueden auditarse de forma confiable.

Usuario

La línea AUDIT no incluye el usuario: se obtiene de log_line_prefix.

Carga

Sin shared_preload_libraries, la extensión no registra nada.

Fuente: README oficial de pgaudit

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Relación con el Laboratorio 01

La bitácora del servidor, la tabla de auditoría con disparador y pgaudit se practican en el Laboratorio 01 — Bitácoras y auditoría del dato en PostgreSQL, sobre el servidor que tú despliegues.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.1 y 3.2

Trazabilidad en MongoDB Community

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Una limitación real que debes conocer

La auditoría nativa de MongoDB (--auditDestination) es exclusiva de MongoDB Enterprise y MongoDB Atlas (M10 o superior). No existe en MongoDB Community Edition, que es la edición de esta materia.

No se simula

Si una pregunta no puede responderse con Community, la respuesta es "No hay evidencia con esta edición" y su razón técnica

Se documenta

Un DBA reconoce y comunica la limitación, por ejemplo al evaluar si conviene licenciar Enterprise

Fuente: MongoDB Manual, "Auditing"

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.1 | Qué registraría la auditoría nativa

Según la documentación oficial (sin practicarlo en esta materia):

Eventos

Cambios de esquema (DDL), eventos de réplica y fragmentación, autenticación y autorización, y operaciones CRUD (con auditAuthorizationSuccess: true)

Destinos

Consola, syslog, archivo JSON o archivo BSON

Comprueba tu edición: db.adminCommand({ buildInfo: 1 }).modules. En Community devuelve []. En Enterprise incluiría "enterprise".

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.2 | Lo que sí existe en Community

Database Profiler

Registra operaciones en la colección system.profile de cada base. Diseñado para desempeño, no para seguridad.

Bitácora de mongod

Documentos JSON con conexiones, autenticaciones, errores y cambios de configuración. Se consulta con getLog o en el archivo de systemLog.

Nivel del perfilador Comportamiento
0 Apagado (por defecto)
1 Más lentas que slowms (100 ms) o que cumplan un filtro
2 Todas las operaciones

Fuente: MongoDB Manual, "Database Profiler"

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo guiado: preparar MongoDB con autenticación

use admin
db.createUser({ user: "admin", pwd: "Admin_Practica_2026", roles: ["root"] })
db.auth("admin", "Admin_Practica_2026")

use comercial
db.createUser({ user: "app_ventas", pwd: "Ventas_Practica_2026",
                roles: [{ role: "readWrite", db: "comercial" }] })
db.clientes.insertMany([ /* 5 clientes ficticios de la Unidad 2 */ ])

Mismo orden que en la Unidad 2: use admin, createUser, db.auth. Sin db.auth la sesión no queda autenticada.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo guiado: el incidente sin perfilado

db.getProfilingStatus()
{ was: 0, slowms: 100, sampleRate: 1, ok: 1 }

La aplicación cambia el RFC:

mongosh "mongodb://app_ventas:Ventas_Practica_2026@127.0.0.1:27017/comercial?appName=app-ventas-web" --quiet --eval 'db.clientes.updateOne({ _id: 3 }, { $set: { rfc: "GAMA780912XXX" } })'

system.profile está vacía y la bitácora solo muestra la autenticación de app_ventas, no la operación.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

La conexión a MongoDB, pieza por pieza

mongodb://app_ventas:Ventas_Practica_2026@127.0.0.1:27017/comercial?appName=app-ventas-web
Parte Significado
mongodb:// Protocolo de MongoDB
app_ventas:Ventas_Practica_2026@ Usuario y contraseña
127.0.0.1:27017 Servidor y puerto
/comercial Base de datos donde se autentica y trabaja
?authSource=admin (Para el DBA) base donde está definido el usuario
?appName=app-ventas-web Nombre de la aplicación. Aparece como appName en el perfilador
--quiet --eval '...' Ejecuta ese código y termina, sin mensaje de bienvenida

Usa comillas simples alrededor del código de --eval. Dentro de comillas dobles, la terminal interpreta $set como una variable vacía.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo guiado: activar el perfilador

db.setProfilingLevel(2)     // { was: 0, ... }  ← devuelve el nivel ANTERIOR
db.getProfilingStatus()     // { was: 2, slowms: 100, sampleRate: 1, ok: 1 }
{
  op: 'update',
  ns: 'comercial.clientes',
  command: { q: { _id: 3 }, u: { '$set': { rfc: 'GAMA780912XYZ' } }, multi: false, upsert: false },
  docsExamined: 1,
  nModified: 1,
  ts: ISODate('2026-10-25T22:52:45.909Z'),
  client: '127.0.0.1',
  appName: 'app-ventas-web',
  user: 'app_ventas@comercial'
}

Fuente: MongoDB Manual, "Database Profiler Output"

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.2 | Interpretar system.profile

Campo Valor observado Responde
op query, update, remove ¿Qué tipo de operación?
ns comercial.clientes ¿Sobre qué colección?
command Filtro y cambio aplicados ¿Qué se pidió?
user app_ventas@comercial ¿Quién? (usuario y base de autenticación)
client / appName 127.0.0.1 / app-ventas-web ¿Desde dónde y con qué aplicación?
ts 2026-10-25T22:52:45.909Z ¿Cuándo?

No hay valor anterior del RFC. Tampoco los datos de un documento eliminado. Y el nivel 2 registra los filtros de las consultas, que pueden contener datos personales.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo guiado: reducir volumen con un filtro

db.setProfilingLevel(0)
db.system.profile.drop()          // exporta antes lo que necesites
db.setProfilingLevel(1, { filter: { op: { $in: ["insert", "update", "remove"] } } })
{
  was: 1, slowms: 100, sampleRate: 1,
  filter: { op: { '$in': [ 'insert', 'remove', 'update' ] } },
  note: 'When a filter expression is set, slowms and sampleRate are not used ...',
  ok: 1
}

Tras una consulta y una actualización de la aplicación, system.profile contiene solo el update.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.2 | Límites del perfilador como evidencia

1 MB

system.profile es una colección limitada. Al llenarse, sobrescribe lo más antiguo: la evidencia desaparece sola.

No persiste

Tras reiniciar el servicio, el nivel volvió a 0. Para que sea permanente: operationProfiling.mode en el archivo de configuración de mongod.

Desempeño

La documentación advierte que puede degradar el rendimiento, sobre todo en nivel 2.

Propósito

Analizar operaciones lentas. No fue diseñado como auditoría de seguridad.

Fuente: MongoDB Manual, "Database Profiler"

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.2 | La bitácora de mongod

Cada línea es un documento JSON: t (fecha), s (severidad), c (componente: NETWORK, ACCESS, COMMAND), id, ctx (conexión, por ejemplo conn12), msg y attr.

¿Dónde queda? Cómo se controla
Archivo systemLog.destination: file y systemLog.path en el archivo de configuración
Salida estándar Si no se configura systemLog (frecuente en contenedores)
Memoria del servidor Siempre: los 1024 eventos más recientes, consultables con getLog
function bitacora() {
  return db.adminCommand({ getLog: "global" }).log.map(l => JSON.parse(l))
}
bitacora().filter(e => e.c === "ACCESS").slice(-5)

Fuente: MongoDB Manual, "Log Messages", "getLog" y "Self-Managed Configuration File Options"

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo guiado: acceso fallido en mongod

bitacora()
  .filter(e => e.c === "ACCESS" && e.msg === "Failed to authenticate")
  .map(e => ({ t: e.t, id: e.id, ctx: e.ctx, user: e.attr.user, client: e.attr.client, error: e.attr.error, result: e.attr.result }))
{
  t: { '$date': '2026-10-25T22:52:58.122+00:00' },
  id: 5286307, ctx: 'conn41', user: 'app_ventas', client: '127.0.0.1:37276',
  error: 'AuthenticationFailed: SCRAM authentication failed, storedKey mismatch',
  result: 18
},
{
  ..., user: 'usuario_inexistente',
  error: 'UserNotFound: Could not find user "usuario_inexistente" for db "comercial"',
  result: 11
}

Un acceso exitoso aparece como "Successfully authenticated" con result: 0 y el nombre de la aplicación en attr.doc.application.name.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo guiado: correlacionar por conexión

{ ctx: 'conn31', msg: 'Profiler settings changed',
  attr: { from: { level: 0, ... }, to: { level: 1, ..., filter: { ... } }, db: 'comercial' } }

El evento no dice quién hizo el cambio. Sí dice qué conexión:

bitacora().filter(e => e.ctx === "conn31" && e.msg === "Successfully authenticated")
          .map(e => ({ t: e.t, ctx: e.ctx, user: e.attr.user, db: e.attr.db }))
[ { t: { '$date': '2026-10-25T22:52:56.959+00:00' }, ctx: 'conn31', user: 'admin', db: 'admin' } ]

La correlación solo es válida dentro del mismo periodo de ejecución: los números de conexión y la memoria de getLog se reinician con el servidor.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.1 | Cambios de privilegios: el límite más importante

db.grantRolesToUser("app_ventas", [{ role: "dbAdmin", db: "comercial" }])

En la verificación del laboratorio, el cambio no apareció en system.profile ni en la bitácora de mongod.

Control compensatorio: instantáneas periódicas de privilegios.

db.getSiblingDB("auditoria").instantaneas_privilegios.insertOne({
  momento: new Date(),
  tomada_por: db.runCommand({ connectionStatus: 1 }).authInfo.authenticatedUsers,
  usuarios: db.getUsers().users.map(u => ({ user: u.user, db: u.db, roles: u.roles }))
})
UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.1 | Lo que responde una instantánea

Pregunta ¿Responde?
¿Cambiaron los privilegios de app_ventas? Sí
¿Qué rol se agregó? Sí: dbAdmin en comercial
¿Quién lo agregó? No
¿Cuándo exactamente? No, solo entre dos instantáneas

Un control compensatorio reduce un riesgo cuando el control preferido no existe, pero no lo sustituye y debe documentarse como tal.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.2 | Comparación de los tres escenarios

Evento PostgreSQL MongoDB Community Enterprise / Atlas
Acceso exitoso y fallido Sí Sí (bitácora) Documentado
Cambio de privilegios Sí No (solo instantáneas) Documentado
Modificación de datos Sí Sí (perfilador) Documentado
Valor anterior Sí (disparador) No No lo describe el manual de MongoDB
Lectura de datos sensibles Con pgaudit o all Nivel 2, con su costo Documentado
Cambio de configuración Sí Sí (ctx) Documentado

"Documentado" significa descrito en el manual oficial de MongoDB, no practicado en la materia

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Relación con el Laboratorio 02

La edición, el perfilador, la bitácora de mongod, la correlación por conexión y las instantáneas de privilegios se practican en el Laboratorio 02 — Trazabilidad en MongoDB Community.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.2

Conservación e interpretación de bitácoras

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.2 | Tres condiciones de la evidencia

REGISTRO      →   el evento quedó escrito
CONSERVACIÓN  →   el registro sigue existiendo, íntegro y protegido, cuando se necesita
INTERPRETACIÓN →  alguien puede leerlo y responder preguntas concretas

Si falta cualquiera de las tres, no hay evidencia útil.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.2 | Cómo se pierde la evidencia sin que nadie la borre

Registro Cómo se pierde
Archivo de bitácora de PostgreSQL Rotación sin conservar los archivos anteriores, reinstalación o recreación del servidor
Bitácora de mongod en memoria (getLog) Reinicio del servicio. Solo guarda los 1024 eventos más recientes
Bitácora en la salida estándar Se pierde con el proceso o el contenedor que la produjo, si nadie la recoge
system.profile Se sobrescribe al llenar 1 MB
Nivel del perfilador Vuelve a 0 al reiniciar, si no está en el archivo de configuración
Tabla de auditoría La desactiva o depura quien la administra
Cualquier bitácora log_statement en none durante un periodo
UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.2 | Criterio de conservación

Sensibilidad

Un cambio de privilegios pesa más que una consulta rutinaria

Obligaciones

Plazos que confirma el área jurídica. El DBA no inventa plazos legales.

Espacio y costo

El volumen depende del nivel de registro elegido

Conflicto con la retención

La auditoría conserva datos que la política de retención pide eliminar

Fuente: NIST SP 800-92, "Guide to Computer Security Log Management"

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo: un criterio de conservación razonado

Registro Sensibilidad Periodo propuesto Justificación Dónde se conserva Al vencer
Cambios de privilegios y estructura Alta Más largo que el resto Permiten reconstruir quién pudo hacer qué en cualquier momento Fuera del servidor, con hash Depurar con autorización del propietario
Accesos fallidos Media Intermedio Sirven para detectar patrones de ataque en el tiempo Fuera del servidor Depurar
auditoria.cambios_clientes Alta, contiene datos personales Plazo a confirmar con el área jurídica Conflicto con la retención de datos personales Esquema protegido Decisión del propietario y jurídico
system.profile Media, contiene filtros de consultas No sirve para conservar: 1 MB Se sobrescribe sola Exportar a archivo Depurar el archivo exportado

El ejemplo usa periodos relativos. Los plazos en días o meses dependen de las obligaciones de cada organización y no los fija el DBA por su cuenta.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.2 | Interpretar es responder preguntas

Preguntas

¿Quién? ¿Cuándo? ¿Desde dónde? ¿Con qué aplicación? ¿Qué tipo de evento? ¿Fue exitoso?

Pregunta clave

¿Qué prueba esta línea y qué no prueba?

Línea Prueba No prueba
user=app_ventas ... statement: UPDATE ... Que se usó la credencial app_ventas desde 127.0.0.1 Qué persona estaba detrás
FATAL: password authentication failed Que hubo un intento fallido Que fue un ataque

Cuando no alcanza la evidencia: "No hay evidencia" y su razón técnica. Nunca una explicación inventada.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.2 | Reconstruir una cronología

Fragmento de una ejecución verificada del Laboratorio 01:

# Hora (UTC) Usuario Cliente Tipo Qué ocurrió
— Sin registro — — Datos Primer cambio del RFC: no hay evidencia (registro apagado)
1 22:49:50.539 postgres (PID 1) — Configuración log_statement cambia a ddl
2 22:50:00.334 app_ventas 127.0.0.1 Acceso Contraseña incorrecta
3 22:50:00.462 usuario_inexistente 127.0.0.1 Acceso Rol inexistente
4 22:50:09.367 postgres local Privilegio GRANT UPDATE ON clientes TO app_ventas
5 22:50:20.601 app_ventas 127.0.0.1 Datos UPDATE clientes SET telefono = ...
6 22:50:20.720 soporte_ana 127.0.0.1 Error permission denied al intentar DELETE

Un evento que no se registró no tiene hora en la cronología. Se declara como hueco de evidencia, no se estima.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Actividad 5: Interpretación y conservación

  1. Con tu bitácora de PostgreSQL o de MongoDB, interpreta al menos cuatro eventos distintos.
  2. Indica qué prueba y qué no prueba cada uno.
  3. Propón cuánto tiempo conservarías ese tipo de bitácora y justifica con sensibilidad, obligaciones y espacio.

No existe una cifra única correcta. Se evalúa el razonamiento, no el número.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.3

Políticas prácticas de datos

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.3 | Política no es procedimiento

Política

Regla de decisión: qué debe hacerse, quién decide y cómo se demuestra.
"Se respalda diariamente y el custodio verifica cada mes que el respaldo puede restaurarse."

Procedimiento

Pasos técnicos para cumplirla.
"Ejecutar el comando de respaldo a las 2:00."
Se estudia en la Unidad V.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.3 | Las seis políticas prácticas

Política Debe responder
Acceso ¿Quién solicita, quién aprueba, cada cuánto se revisa?
Respaldo ¿Qué se respalda, con qué frecuencia, quién verifica que sirve?
Retención ¿Cuánto se conservan datos y bitácoras? ¿Qué pasa al vencer?
Restauración ¿Quién autoriza, quién ejecuta y en qué condiciones?
Datos sensibles ¿Quién accede, con qué justificación, cómo se registra?
Cambios en producción ¿Qué ocurre antes, durante y después del cambio?
UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.3 | Plantilla mínima

POL-0X — Nombre

Objetivo:      qué riesgo reduce
Alcance:       datos, sistemas y ambientes
Regla:         una a tres oraciones verificables
Responsable:   quién decide / quién ejecuta
Excepciones:   cuándo puede omitirse y quién lo autoriza
Evidencia:     qué registro demuestra que se cumplió
Revisión:      cada cuánto se revisa

Cambios en producción retoma la definición de ambiente de la Unidad I.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo: una política completa

POL-06 — Cambios en producción

Objetivo:     evitar cambios de estructura o de privilegios no autorizados en producción
Alcance:      base comercial (PostgreSQL y MongoDB), ambiente de producción
Regla:        todo cambio en producción requiere una solicitud con folio aprobada por el
              Comité de cambios y se ejecuta dentro de la ventana autorizada. El DBA concilia
              cada mes las sentencias CREATE, ALTER, DROP, GRANT y REVOKE de la bitácora con
              las solicitudes aprobadas
Responsable:  decide el Comité de cambios, ejecuta el DBA, concilia una persona distinta del DBA
Excepciones:  emergencia que detiene la operación. Se ejecuta con aviso al propietario y la
              solicitud se registra en las 24 horas siguientes
Evidencia:    tabla gobierno.solicitudes_cambio + bitácora exportada con hash + acta de conciliación
Revisión:     anual, o después de cualquier cambio no autorizado detectado
UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.3 | Verificable o no verificable

Verificable

"Todo cambio de privilegios en producción requiere una solicitud aprobada por el propietario del dato. El DBA concilia mensualmente la bitácora de GRANT y REVOKE con las solicitudes aprobadas."

No verificable

"Los accesos deben otorgarse con cuidado."

La diferencia está en la evidencia: la primera nombra un registro que alguien puede revisar.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.3 | Las políticas deben ser coherentes entre sí

Contradicción

Retención: "eliminar los datos de clientes dados de baja a los 30 días".
Datos sensibles: "conservar la auditoría completa para investigar incidentes durante un año".

Resolución

Decidir explícitamente qué conserva la auditoría, durante cuánto, con qué acceso, y quién lo aprueba. Registrar la decisión.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Actividad 6: Políticas prácticas

  1. Redacta POL-01 a POL-06 con la plantilla, para la base comercial de Comercializadora Norte.
  2. Cada Evidencia nombra un registro concreto, o indica que hoy no existe.
  3. POL-02 y POL-04 son reglas de decisión: "El procedimiento técnico se definirá en la Unidad V".
  4. Revisa que no se contradigan.

Esta actividad se desarrolla dentro del Laboratorio 03 — Políticas prácticas, gobierno de datos y evidencias.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.4

Gobierno práctico de datos

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.4 | El gobierno práctico no es burocracia

Calidad

Detectar problemas desde la operación

Responsables

Propietario, custodio y usuarios

Metadatos

Catálogo mínimo y diccionario operativo

Fuente: DAMA-DMBOK, marco profesional de gestión de datos. Aquí se trabaja su forma mínima operativa

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo guiado: calidad desde la operación

SELECT lower(correo) AS correo_normalizado, count(*) AS registros,
       string_agg(id::text, ', ') AS ids
FROM clientes GROUP BY lower(correo) HAVING count(*) > 1;

SELECT id, nombre, rfc FROM clientes
WHERE rfc IS NULL OR rfc !~ '^[A-ZÑ&]{3,4}[0-9]{6}[A-Z0-9]{3}$';
   correo_normalizado   | registros | ids
------------------------+-----------+------
 ana.lopez@example.test |         2 | 1, 7

 id |   nombre   |     rfc
----+------------+--------------
  7 | Ana Lopez  | LOAA850315AB
  8 | Jorge Díaz |

La expresión regular verifica el formato para la práctica. No valida el RFC ante el SAT

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.4 | El DBA detecta, el propietario decide

El DBA

Ejecuta verificaciones, registra el hallazgo, propone una restricción (CHECK, UNIQUE) y lo escala

El propietario

Decide cuál es el valor correcto, si se fusionan los registros duplicados y si se agrega la restricción

Si el DBA corrige un dato, la tabla de auditoría debe dejar evidencia del cambio. Un hallazgo corregido sin registro desaparece del expediente.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.4 | Propietario, custodio y usuario

Figura Responsabilidad En clientes
Propietario (data owner) Decide finalidad, acceso, corrección y eliminación Gerencia Comercial
Custodio (data custodian) Opera y protege según esas decisiones DBA
Usuario Usa el dato para una finalidad autorizada Aplicación de ventas, soporte

pg_get_userbyid(relowner) devuelve postgres: es el propietario técnico del objeto, no el propietario del dato en la organización.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.4 | Catálogo y diccionario

Catálogo mínimo

¿Qué datos existen y dónde? Una fila por tabla o colección: ubicación, propietario, custodio, clasificación, finalidad, conservación.

Fuente: IBM, "What Is a Data Catalog?"
Diccionario operativo

¿Cómo está estructurado y qué significa? Una fila por columna: tipo, nulos, valor por defecto, descripción, clasificación.

Fuente: Oracle, "Data Dictionary and Dynamic Performance Views"
UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo guiado: diccionario dentro del motor

COMMENT ON COLUMN clientes.rfc IS 'RFC del cliente. Dato personal. Uso: facturación. Cambios auditados en auditoria.cambios_clientes.';

SELECT c.column_name AS columna, c.data_type AS tipo, c.is_nullable AS acepta_nulos,
       col_description('public.clientes'::regclass, c.ordinal_position) AS descripcion
FROM information_schema.columns c
WHERE c.table_schema = 'public' AND c.table_name = 'clientes'
ORDER BY c.ordinal_position;
 columna |       tipo        | acepta_nulos |                     descripcion
---------+-------------------+--------------+------------------------------------------------------
 id      | bigint            | NO           | Identificador interno del cliente. Generado por el sistema.
 correo  | character varying | NO           | Correo de contacto. Dato personal. Uso: notificaciones al cliente.
 rfc     | character varying | YES          | RFC del cliente. Dato personal. Uso: facturación. Cambios auditados...

Fuente: documentación oficial de PostgreSQL, "COMMENT" e "information_schema.columns"

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo: exportar el diccionario a un archivo

psql -U postgres -d comercial --csv -c "SELECT c.column_name AS columna, c.data_type AS tipo, c.character_maximum_length AS longitud, c.is_nullable AS acepta_nulos, col_description('public.clientes'::regclass, c.ordinal_position) AS descripcion FROM information_schema.columns c WHERE c.table_schema = 'public' AND c.table_name = 'clientes' ORDER BY c.ordinal_position" > evidencias/diccionario-clientes.csv

--csv hace que psql entregue el resultado separado por comas, listo para abrirse en una hoja de cálculo.

columna,tipo,longitud,acepta_nulos,descripcion
id,bigint,,NO,Identificador interno del cliente. Generado por el sistema.
nombre,character varying,120,NO,Nombre completo. Dato personal identificador directo.
UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.4 | Catálogo mínimo de la base comercial

ID Conjunto Motor Ubicación Propietario Clasificación Datos personales
CAT-01 Clientes PostgreSQL 16 comercial.public.clientes Gerencia Comercial Confidencial Sí
CAT-02 Auditoría de clientes PostgreSQL 16 comercial.auditoria.cambios_clientes Por definir Confidencial Sí
CAT-03 Registro de cambios PostgreSQL 16 comercial.gobierno.solicitudes_cambio Comité de cambios Interna No
CAT-04 Clientes (tienda) MongoDB 7 comercial.clientes Por definir Confidencial Sí
CAT-05 Perfilado MongoDB 7 comercial.system.profile Por definir Confidencial Sí

CAT-02 y CAT-05 existen para la auditoría, pero contienen datos personales.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Ejemplo guiado: registro de cambios y conciliación

CREATE TABLE gobierno.solicitudes_cambio (
    folio TEXT PRIMARY KEY, descripcion TEXT NOT NULL, solicitado_por TEXT NOT NULL,
    aprobado_por TEXT, ambiente TEXT NOT NULL CHECK (ambiente IN ('desarrollo','pruebas','produccion')),
    fecha_aprobacion TIMESTAMPTZ, ventana_inicio TIMESTAMPTZ, ventana_fin TIMESTAMPTZ
);
Sentencia en la bitácora Folio ¿Autorizado?
ALTER TABLE clientes ADD COLUMN canal_alta ... CAM-2026-014 Sí
ALTER TABLE clientes DISABLE TRIGGER trg_auditoria_clientes — Hallazgo
GRANT UPDATE ON clientes TO app_ventas — Por revisar

Conciliación: comparar lo que ocurrió (bitácora, consultada con dba.bitacora) con lo que estaba autorizado (registro)

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.4 | Afirmación o evidencia

Afirmación

"Registramos los cambios de privilegios."

Evidencia

Línea de bitácora con el GRANT, el usuario y la hora, más la configuración vigente que lo permitió.

ID Evidencia técnica del expediente
E1 Configuración de registro vigente (pg_settings)
E2 Privilegios vigentes (information_schema.role_table_grants)
E3 Disparador de auditoría habilitado (pg_trigger)
E4 Muestra de la auditoría, solo metadatos
E5 Bitácora exportada con hash
E6 Evidencias de MongoDB (perfilador, bitácora, comparación)
UAS - Gestión de Seguridad y Desempeño de Bases de Datos

3.4 | El expediente de auditoría interna

EXPEDIENTE.md
 1. Alcance
 2. Configuración de auditoría             (E1, E3, E6)
 3. Bitácora interpretada                  (al menos tres eventos)
 4. Elementos de gobierno                  (responsables, catálogo, diccionario)
 5. Conservación
 6. Políticas                              (POL-01 a POL-06)
 7. Conciliación de cambios
 8. Hallazgos                              (severidad, impacto, recomendación, decisión)
 9. Limitaciones y riesgos aceptados       (verificado vs. documentado)
10. Índice de evidencias con hash
UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Actividad 7: Evidencia oficial de la unidad

Debe integrar

(1) mecanismo real de registro disponible en la edición usada, (2) bitácora capturada, (3) al menos tres eventos interpretados, (4) propietario y entrada de catálogo y diccionario

No se acepta

Simular una función de auditoría que no existe en la edición usada, o una interpretación genérica no ligada a la bitácora entregada

Relación con el Laboratorio 03 — Políticas prácticas, gobierno de datos y evidencias: ahí se integra el expediente con lo producido en los Laboratorios 01 y 02.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Cierre

Integración de la unidad

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Errores conceptuales frecuentes

Error Corrección
"Tenemos roles y contraseñas, ya tenemos auditoría" El control de acceso decide. La auditoría registra
"Activamos la bitácora para investigar lo de ayer" Lo no registrado no se reconstruye
"log_statement = 'all' es lo más seguro" Registra todo, incluidos datos sensibles
"El perfilador es la auditoría de Community" Es una herramienta de desempeño. La auditoría nativa no existe en Community
"La bitácora dice app_ventas, fue la aplicación" Prueba la credencial, no la persona
"El DBA es el dueño de los datos" El DBA custodia. El propietario decide
UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Mecanismos complementarios

                 ¿Qué ocurrió en clientes?
                           │
   ┌──────────────┬────────┴────────┬──────────────────┐
   ▼              ▼                 ▼                  ▼
Bitácora       Tabla de          pgaudit           Profiler + log
PostgreSQL     auditoría         (opcional)        MongoDB
quién, cuándo, valor antes       lecturas de        operaciones,
qué sentencia  y después         columnas           accesos
   └──────────────┴────────┬────────┴──────────────────┘
                           ▼
       Políticas + responsables + catálogo + diccionario
                           ▼
              Expediente para auditoría interna
UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Pregunta de cierre

La base de datos tiene roles correctos, la bitácora en mod, una tabla de auditoría con disparador y un perfilador activo en MongoDB. Pero nadie tiene asignado el dato, no hay política de retención de bitácoras y los servidores se reinstalan cada semana sin conservar sus archivos de bitácora.

¿Puede demostrarse quién cambió el RFC hace un mes?

No. La evidencia se perdió con cada reinstalación y nadie tenía la responsabilidad de conservarla. Sin conservación y gobierno, los mecanismos técnicos no producen evidencia.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

¿Qué sigue?

Unidad IV: desempeño

¿Cómo hacemos que esta base, ya auditable, responda rápido? Retomarás pg_stat_activity y el vocabulario de bitácoras para diagnosticar consultas costosas.

Unidad V: respaldo y restauración

POL-02, POL-03 y POL-04 serán el insumo para diseñar los mecanismos técnicos de respaldo y recuperación.

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Referencia rápida del DBA

Necesidad PostgreSQL 16 MongoDB 7 Community
¿Dónde está la configuración? SHOW config_file, SHOW hba_file db.serverCmdLineOpts()
Leer la bitácora pg_read_file(pg_current_logfile()) (vista dba.bitacora) db.adminCommand({ getLog: "global" })
Configurar registro ALTER SYSTEM + pg_reload_conf() o reinicio db.setProfilingLevel() o archivo de configuración
Ver configuración vigente pg_settings (source, pending_restart) db.getProfilingStatus()
Reglas de autenticación pg_hba_file_rules security.authorization
Sesiones actuales pg_stat_activity —
Valor anterior Disparador + tabla de auditoría No disponible
Lecturas por columna pgaudit (opcional) Nivel 2 (sin filtro por campo)
Diccionario COMMENT + information_schema Documento externo
UAS - Gestión de Seguridad y Desempeño de Bases de Datos

Referencias

UAS - Gestión de Seguridad y Desempeño de Bases de Datos

estado: v4 para estudiantes (2026-10-25) fuente: unidad03_manual_estudiante.md, unidad03_actividades.md, laboratorios/unidad03_lab01 a lab03 tema: plantillas/tema-uas3.css revisión v4: - el foco es el gestor, no la forma de despliegue: los comandos usan psql, SQL y mongosh, y funcionan igual con instalación nativa, máquina virtual o contenedor. Los contenedores aparecen solo como una variante de despliegue - la bitácora de PostgreSQL se lee desde el motor (logging_collector, pg_current_logfile, pg_read_file) y la de MongoDB con getLog - se retiran las láminas que explicaban comandos de Docker - tres laboratorios. Las láminas de laboratorio solo indican la relación con el laboratorio: las instrucciones viven en el archivo de cada laboratorio - todas las salidas provienen de ejecuciones reales del 2026-10-25 (AUDITORIA_QA_MATERIALES_U3.md)