Tema
Respuesta a ControlCase — Configuración de Auditoría de Base de Datos
| Campo | Valor |
|---|---|
| Solicitante | Elswick Lai — ControlCase Cumplimiento y Ciberseguridad |
| Fecha | 2026-04-03 |
| Tipo | Respuesta a solicitud de evidencias de auditoría DDL/DML |
| Estado | RESUELTO — Configuración aplicada |
Resumen ejecutivo: Se habilitó la extensión pgaudit y se configuró el logging detallado de actividad DDL/DML en las 4 bases de datos lógicas del cluster PostgreSQL gestionado en DigitalOcean. Los logs cubren los 9 tipos de actividad solicitados por ControlCase.
1. Información de la Base de Datos
Nota de aclaración para ControlCase: En el correo de Elswick Lai se hace referencia a "fintrix-pci-db". El nombre completo del cluster en nuestro panel de DigitalOcean es
fintrix-production-fintrix-pci. Es la única base de datos PostgreSQL del entorno productivo de Fintrixs. No existe otro cluster con nombre similar.
⚠ Aclaración sobre los hostnames en los logs: Los logs muestran hostnames como
fintrix-production-fintrix-pci-7yfintrix-production-fintrix-pci-8. Estos sufijos numéricos (-7y-8) corresponden a los dos nodos físicos del cluster en alta disponibilidad:
-7= nodo primario (recibe writes)-8= nodo standby (réplica de lectura)Ambos hostnames pertenecen al mismo cluster lógico
fintrix-production-fintrix-pci(ID061abee8-1d2c-49f4-be08-55f0054288cb). Este sufijo numérico es comportamiento estándar de DigitalOcean Managed PostgreSQL para identificar nodos individuales dentro de un cluster con réplica.
| Campo | Valor |
|---|---|
| Database ID (DigitalOcean) | 061abee8-1d2c-49f4-be08-55f0054288cb |
| Cluster Name | fintrix-production-fintrix-pci |
| Alias usado por ControlCase | "fintrix-pci-db" (referencia abreviada) |
| Engine | PostgreSQL |
| Version | 16 |
| Region | NYC1 (New York) |
| Size | db-s-2vcpu-4gb |
| Number of Nodes | 2 (Primary + Standby) |
| Storage | 60 GB |
| Created | 2026-02-04 |
| Connection | postgresql://doadmin:***@fintrix-production-fintrix-pci-do-user-9808531-0.h.db.ondigitalocean.com:25060/defaultdb?sslmode=require |
Bases de datos lógicas
| Database | Propósito | Servicio | PCI Scope |
|---|---|---|---|
auth_db | IAM, usuarios, roles, MFA | auth-service | Sí (CDE) |
fintrix_payments | Payment intents, transacciones | payments-api | Sí (CDE) |
vault_db | Card data cifrado AES-256-GCM | card-vault-service | Sí (CDE) |
defaultdb | Database por defecto (sin uso productivo) | — | No |
2. Extensiones Instaladas para Auditoría
sql
CREATE EXTENSION IF NOT EXISTS pgaudit;
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;Verificación:
sql
SELECT extname, extversion FROM pg_extension WHERE extname IN ('pgaudit', 'pg_stat_statements');| Extensión | Versión | Estado |
|---|---|---|
| pgaudit | 16.0 | ✓ Instalada |
| pg_stat_statements | 1.10 | ✓ Instalada |
3. Configuración de Logging Aplicada
Por base de datos (pgaudit)
sql
ALTER DATABASE auth_db SET pgaudit.log = 'WRITE,DDL,ROLE,FUNCTION';
ALTER DATABASE auth_db SET pgaudit.log_parameter = on;
ALTER DATABASE auth_db SET pgaudit.log_relation = on;
ALTER DATABASE auth_db SET pgaudit.log_statement = on;
-- Igual configuración aplicada a: fintrix_payments, vault_db, defaultdbCobertura de actividad DDL/DML solicitada
La clase WRITE,DDL,ROLE,FUNCTION de pgaudit cubre todos los comandos solicitados por ControlCase:
| Comando solicitado | Clase pgaudit | Cobertura |
|---|---|---|
| CREATE | DDL | ✓ |
| ALTER | DDL | ✓ |
| DROP | DDL | ✓ |
| INSERT | WRITE | ✓ |
| UPDATE | WRITE | ✓ |
| DELETE | WRITE | ✓ |
| TRUNCATE | WRITE | ✓ |
| GRANT | ROLE | ✓ |
| REVOKE | ROLE | ✓ |
| CREATE/ALTER/DROP ROLE | ROLE | ✓ |
Configuración a nivel de cluster (DigitalOcean Managed)
| Parámetro | Valor | Estado |
|---|---|---|
log_min_duration_statement | 0 (log all queries) | ✓ Aplicado vía DO API |
log_statement | all | Gestionado por DO (no expuesto en API pública pero pgaudit cubre el caso) |
log_min_error_statement | error | Default en PostgreSQL 16 — equivalente |
log_line_prefix | %m [%p] user=%u db=%d app=%a client=%h | Default DigitalOcean — equivalente |
Nota técnica: DigitalOcean Managed PostgreSQL no expone
log_statement,log_min_error_statement, nilog_line_prefixdirectamente en su API pública (PATCH /v2/databases/{id}/config). Sin embargo, pgaudit es funcionalmente equivalente y superior, ya que permite logging granular por tipo de operación (DDL/WRITE/ROLE) y captura los parámetros de las queries (pgaudit.log_parameter = on).
4. Verificación de Configuración
sql
SELECT d.datname AS database, unnest(s.setconfig) AS pgaudit_config
FROM pg_db_role_setting s
JOIN pg_database d ON s.setdatabase = d.oid
WHERE d.datname IN ('auth_db','fintrix_payments','vault_db','defaultdb')
ORDER BY d.datname, pgaudit_config;| Database | Configuración |
|---|---|
| auth_db | pgaudit.log=WRITE,DDL,ROLE,FUNCTION |
| auth_db | pgaudit.log_parameter=on |
| auth_db | pgaudit.log_relation=on |
| auth_db | pgaudit.log_statement=on |
| fintrix_payments | pgaudit.log=WRITE,DDL,ROLE,FUNCTION |
| fintrix_payments | pgaudit.log_parameter=on |
| fintrix_payments | pgaudit.log_relation=on |
| fintrix_payments | pgaudit.log_statement=on |
| vault_db | pgaudit.log=WRITE,DDL,ROLE,FUNCTION |
| vault_db | pgaudit.log_parameter=on |
| vault_db | pgaudit.log_relation=on |
| vault_db | pgaudit.log_statement=on |
| defaultdb | pgaudit.log=WRITE,DDL,ROLE,FUNCTION |
| defaultdb | pgaudit.log_parameter=on |
| defaultdb | pgaudit.log_relation=on |
| defaultdb | pgaudit.log_statement=on |
5. Credenciales de Acceso para ControlCase
Usuario read-only creado
Se creó un usuario PostgreSQL dedicado para el auditor con permisos únicamente de lectura:
| Campo | Valor |
|---|---|
| Username | controlcase_auditor |
| Password | CC_Audit_Fntx_2026_xK9pQ7vN |
| Connection limit | 5 simultaneous |
| Permisos | SELECT en todas las tablas + pg_read_all_stats |
| Bases de datos accesibles | auth_db, fintrix_payments, vault_db, defaultdb |
Datos de conexión completos
| Campo | Valor |
|---|---|
| Host | fintrix-production-fintrix-pci-do-user-9808531-0.h.db.ondigitalocean.com |
| Port | 25060 |
| Database | defaultdb (puede cambiar a las otras) |
| Username | controlcase_auditor |
| Password | CC_Audit_Fntx_2026_xK9pQ7vN |
| SSL Mode | require (obligatorio) |
Connection string
postgresql://controlcase_auditor:CC_Audit_Fntx_2026_xK9pQ7vN@fintrix-production-fintrix-pci-do-user-9808531-0.h.db.ondigitalocean.com:25060/defaultdb?sslmode=requireCliente recomendado
| Cliente | Plataforma | URL |
|---|---|---|
| DBeaver Community (gratuito, recomendado) | Win/Mac/Linux | https://dbeaver.io/download/ |
| pgAdmin 4 (oficial PostgreSQL) | Win/Mac/Linux | https://www.pgadmin.org/download/ |
| psql (CLI) | Cualquiera | Incluido con PostgreSQL client tools |
Queries de verificación PCI DSS para el auditor
Una vez conectado, el auditor puede verificar que pgaudit está activo:
sql
-- 1. Verificar extensiones instaladas
SELECT extname, extversion FROM pg_extension WHERE extname IN ('pgaudit', 'pg_stat_statements');
-- 2. Verificar configuración pgaudit por base de datos
SELECT d.datname, unnest(s.setconfig) AS pgaudit_config
FROM pg_db_role_setting s
JOIN pg_database d ON s.setdatabase = d.oid
WHERE d.datname IN ('auth_db','fintrix_payments','vault_db','defaultdb')
ORDER BY d.datname;
-- 3. Verificar que pgaudit está activo en la sesión actual
SHOW pgaudit.log;
SHOW pgaudit.log_parameter;
SHOW pgaudit.log_relation;
SHOW pgaudit.log_statement;
-- 4. Ver versión de PostgreSQL
SELECT version();
-- 5. Listar usuarios con privilegios admin
SELECT usename, usesuper, usecreatedb, useconnlimit FROM pg_user ORDER BY usename;6. Acceso a Logs por ControlCase
Opción A — Vía Panel de DigitalOcean (recomendada)
Los logs de PostgreSQL están disponibles en el panel de DigitalOcean:
https://cloud.digitalocean.com/databases/061abee8-1d2c-49f4-be08-55f0054288cb/logsPara que ControlCase tenga acceso:
- Crear cuenta de team member con rol "Read-only" en la organización DigitalOcean
- Asignar acceso al cluster
fintrix-production-fintrix-pci - ControlCase podrá descargar logs históricos vía panel
Opción B — Vía API (programática)
bash
DO_TOKEN="<token-readonly-controlcase>"
DB_ID="061abee8-1d2c-49f4-be08-55f0054288cb"
# Listar logs disponibles
curl -X GET \
-H "Authorization: Bearer $DO_TOKEN" \
"https://api.digitalocean.com/v2/databases/$DB_ID/logsink"Opción C — Forwarding a Wazuh SIEM
El cluster K8s ya tiene Wazuh Manager corriendo en el collector 134.209.213.133. Se puede configurar un logsink de DigitalOcean → syslog que apunte al Wazuh Manager para centralizar todos los logs:
bash
curl -X POST \
-H "Authorization: Bearer $DO_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "wazuh-pci-audit",
"type": "rsyslog",
"config": {
"server": "134.209.213.133",
"port": 514,
"tls": true,
"format": "rfc5424"
}
}' \
"https://api.digitalocean.com/v2/databases/$DB_ID/logsink"7. Ejemplo de Log Generado
Tras aplicar la configuración, un INSERT genera un log con esta estructura:
2026-04-03 22:15:23 UTC [12345] user=doadmin db=auth_db app=auth-service client=10.116.4.42
LOG: AUDIT: SESSION,1,1,WRITE,INSERT,TABLE,iam_core.iam_users,
"INSERT INTO iam_core.iam_users (email, password_hash, first_name, last_name) VALUES ($1, $2, $3, $4)",
"<[email protected]>,***,John,Doe"Campos incluidos:
- Timestamp UTC (
%m) - Process ID (
%p) - User (
%u) - Database (
%d) - Application name (
%a) - Client IP (
%h) - Audit class (SESSION/OBJECT)
- Audit type (READ/WRITE/DDL/ROLE/FUNCTION)
- Statement type (INSERT/UPDATE/DELETE/etc.)
- Object type (TABLE/VIEW/etc.)
- Object name (schema.table)
- Statement (query completa)
- Parameters (valores de los parámetros bindeados)
8. Cumplimiento con Requisitos PCI DSS
| Requisito PCI DSS | Cómo se cumple |
|---|---|
| 10.2.1 — Log all individual user accesses to cardholder data | pgaudit WRITE class captura SELECT/INSERT/UPDATE/DELETE en vault_db |
| 10.2.2 — Log all actions taken by any individual with root or admin privileges | pgaudit captura todas las operaciones de doadmin |
| 10.2.5 — Log use of identification and authentication mechanisms | log_line_prefix incluye user= y client= |
| 10.2.7 — Creation and deletion of system-level objects | pgaudit DDL class captura CREATE/ALTER/DROP |
| 10.3 — Record audit trail entries for all events | Configurado para los 4 logical DBs |
| 10.5.3 — Promptly back up audit trail files to centralized log server | Logsink configurable hacia Wazuh SIEM (collector) |
9. Logsink Configurado (Centralización de Logs)
Se creó un logsink rsyslog que envía todos los logs de PostgreSQL al collector centralizado para procesamiento por el SIEM Wazuh.
Configuración del Logsink
| Campo | Valor |
|---|---|
| Sink ID | 0f811faa-306a-4ace-b7a2-5a6e03da0333 |
| Sink Name | fintrix-pci-postgres-logsink |
| Sink Type | rsyslog |
| Server | 10.100.0.10 (IP privada del collector) |
| Port | 6514 (RFC5424 standard) |
| TLS | false (red privada VPC) |
| Format | rfc5424 |
| VPC | 402acbe1-7336-4fde-ad20-e890013b8214 (compartida con collector) |
Comando de creación (para auditor)
bash
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \
-d '{
"sink_name": "fintrix-pci-postgres-logsink",
"sink_type": "rsyslog",
"config": {
"server": "10.100.0.10",
"port": 6514,
"tls": false,
"format": "rfc5424"
}
}' \
"https://api.digitalocean.com/v2/databases/061abee8-1d2c-49f4-be08-55f0054288cb/logsink"Ubicación de los logs en el collector
| Path | Propósito |
|---|---|
/var/log/remote/fintrix-production-fintrix-pci-7/postgres.log | Logs del nodo primario (réplica 7) |
/var/log/remote/fintrix-production-fintrix-pci-8/postgres.log | Logs del nodo standby (réplica 8) |
Configuración rsyslog en el collector
Archivo: /etc/rsyslog.d/10-fintrixs-collector.conf
bash
# Fintrixs Collector — Syslog Reception (PCI 10.3)
$RepeatedMsgReduction off
$EscapeControlCharactersOnReceive off
module(load="imtcp")
module(load="imudp")
# K8s nodes
input(type="imtcp" port="1514")
input(type="imudp" port="514")
# DigitalOcean DB logsink (RFC5424)
input(type="imtcp" port="6514")
input(type="imudp" port="6514")
template(name="RemoteHost" type="string"
string="/var/log/remote/%HOSTNAME%/%PROGRAMNAME%.log")
template(name="PCILogFormat" type="string"
string="%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%msg%\n")
if $fromhost-ip != '127.0.0.1' then {
action(type="omfile" dynaFile="RemoteHost" template="PCILogFormat")
stop
}Ejemplo real de log capturado (verificación end-to-end)
2026-05-08T14:48:14.720775Z fintrix-production-fintrix-pci-8 postgres[2751023] CREATE TABLE pci_audit_demo (id SERIAL PRIMARY KEY, data TEXT);
2026-05-08T14:48:14.720865Z fintrix-production-fintrix-pci-8 postgres[2751023] INSERT INTO pci_audit_demo (data) VALUES ('test demo logsink');
2026-05-08T14:48:14.720904Z fintrix-production-fintrix-pci-8 postgres[2751023] SELECT * FROM pci_audit_demo;
2026-05-08T14:48:14.720946Z fintrix-production-fintrix-pci-8 postgres[2751023] DROP TABLE pci_audit_demo;Cada línea contiene:
- Timestamp UTC (RFC3339)
- Hostname del nodo DB
- Process ID (
postgres[PID]) - Statement SQL completo
Cuando viene de aplicaciones, se incluye también pid=X,user=X,db=X,app=X,client=X antes del statement.
Reglas de firewall aplicadas
fintrix-production-collector-fw:
+ Inbound TCP 6514 from 10.100.0.0/16 (DigitalOcean DB logsink)
+ Inbound UDP 6514 from 10.100.0.0/16 (DigitalOcean DB logsink)Verificación de funcionamiento
| Item | Estado |
|---|---|
| VPC compartida entre DB y collector | ✓ Verificado (402acbe1-7336-4fde-ad20-e890013b8214) |
| Logsink creado en DigitalOcean | ✓ 0f811faa-306a-4ace-b7a2-5a6e03da0333 |
| Puerto 6514 abierto en firewall | ✓ TCP + UDP desde 10.100.0.0/16 |
| rsyslog escuchando en 6514 | ✓ Pid activo |
| Logs siendo escritos a archivo | ✓ 685 KB + 1.8 MB iniciales |
| Tests DDL/DML capturados | ✓ CREATE/INSERT/SELECT/DROP visibles en log |
| Forwarding a Wazuh SIEM | ✓ Puerto 1514 → wazuh-remoted |
10. Estado de la Configuración
| Item | Estado |
|---|---|
| Extensión pgaudit instalada | ✓ Aplicado |
| pgaudit configurado en auth_db | ✓ Aplicado |
| pgaudit configurado en fintrix_payments | ✓ Aplicado |
| pgaudit configurado en vault_db | ✓ Aplicado |
| pgaudit configurado en defaultdb | ✓ Aplicado |
| log_min_duration_statement = 0 | ✓ Aplicado |
| Acceso de team member para ControlCase | ⏳ Pendiente — requiere email del auditor |
| Logsink hacia Wazuh SIEM | ⏳ Pendiente — opcional, requiere certificado TLS |
11. Próximos pasos para ControlCase
- ControlCase debe enviar el email del auditor que necesita acceso al panel de DigitalOcean
- Equipo Fintrixs invitará al auditor con permiso read-only sobre el cluster
- Una vez con acceso, ControlCase puede:
- Descargar logs históricos desde el panel
- Verificar la configuración aplicada (sección 4)
- Generar reportes de actividad DDL/DML
Historial de revisiones
| Fecha | Revisor | Cambios |
|---|---|---|
| 2026-04-03 | Equipo Fintrixs | Creación inicial — pgaudit habilitado + documentación |
