Tema
EVD-ACCESS-CONTROL — Evidencia de Control de Acceso
| Campo | Valor |
|---|---|
| Organizacion | Fintrixs SAS |
| Entorno | DigitalOcean Managed Kubernetes (DOKS) |
| Fecha de evidencia | 2026-04-03 |
| Proxima revision | 2026-10-03 |
| Responsable | Equipo de Seguridad / Infraestructura |
| Clasificacion | Confidencial — Solo para auditoria PCI DSS |
Q21 — Servicios y puertos en sistemas dentro del alcance
Inventario de microservicios
| Servicio | Puerto interno | Protocolo | PCI Scope | Descripcion |
|---|---|---|---|---|
payments-api | 3000 | HTTP/TLS | No | Core de pagos: intents, outbox, RLS por merchant |
auth-service | 3001 | HTTP/TLS | Si | Autenticacion JWT RS256, MFA TOTP, gestion de sesiones |
tokenization-service | 3002 | HTTP/TLS | Si | Tokenizacion PCI DSS — reemplaza PANs por tokens |
card-vault-service | 3003 | HTTP/TLS | Si | Vault cifrado de datos de tarjeta (AES-256) |
webhooks-service | 3004 | HTTP/TLS | No | Recepcion y validacion de webhooks de providers |
orchestration-service | 3005 | HTTP/TLS | No | Orquestacion de eventos, routing de notificaciones |
email-service | 3006 | HTTP/TLS | No | Entrega de emails, consumidor Kafka |
onboarding-service | 3007 | HTTP/TLS | No | KYC merchants, subida de documentos (S3/MinIO) |
realtime-gateway | 3008 | HTTP/SSE | No | Stream de eventos fintrix.ui.* al frontend |
admin-audit-service | 3009 | HTTP/TLS | No | Auditoria de acciones administrativas |
integration-runtime | 3010 | HTTP/TLS | No | Ejecutor de integraciones YAML-driven (Kafka consumer) |
fintrix-api-gateway | 4000 | HTTP/GraphQL | No | Apollo Federation, GraphQL gateway |
postgraphile-gateway | 4001 | HTTP/GraphQL | No | GraphQL auto-generado desde schema PostgreSQL |
Servicios de infraestructura
| Servicio | Puerto | Exposicion | PCI Scope | Descripcion |
|---|---|---|---|---|
| Kong Gateway (proxy) | 8000 | Interna | Si | Proxy HTTP interno |
| Kong Gateway (TLS proxy) | 8443 | Externa (unica) | Si | Terminacion TLS, WAF, rate limiting |
| Kong Admin API | 8001 | Interna solamente | Si | Administracion de Kong — nunca expuesta a internet |
| PostgreSQL | 5432 | Interna (Managed) | Si (vault_db, auth_db) | Base de datos managed con cifrado at-rest AES-256 |
| Apache Kafka | 9092 / 9093 (TLS) | Interna | No | Broker de mensajeria asincrona |
| MinIO / S3 | 9000 | Interna | No | Object storage para documentos de onboarding |
Diagrama de exposicion de puertos
Control clave: Solo el puerto 8443 de Kong (via Load Balancer en puerto 443) esta expuesto a internet. Todos los demas puertos son accesibles unicamente desde la red interna del cluster Kubernetes.
Evidencia asociada:
- Terraform:
backend/infra/terraform/digitalocean/modules/networking/main.tf - Kubernetes NetworkPolicies:
backend/infra/kubernetes/network-policies.yaml - Kong config:
backend/infra/kong/kong.yaml
Q24 — Acceso administrativo no-consola
Metodos de acceso administrativo
| Metodo | Protocolo | Autenticacion | Restricciones |
|---|---|---|---|
| SSH a nodos K8s | SSH (22) | Solo llave publica RSA/Ed25519 | Password SSH deshabilitado; acceso limitado a IPs del equipo via Cloud Firewall |
kubectl | HTTPS (443) | Token OIDC via DigitalOcean + MFA | Acceso al cluster via doctl kubernetes cluster kubeconfig; requiere autenticacion DO con 2FA |
| PostgreSQL (managed) | TCP (25060 TLS) | Certificado SSL + password | Solo conexiones desde CDE subnet; sslmode=require obligatorio |
| Kong Admin API | HTTP (8001) | Red interna unicamente | No expuesto fuera del cluster; acceso solo via kubectl port-forward |
| Panel Admin (Dashboard) | HTTPS (443) | JWT RS256 + MFA TOTP | Roles admin o super_admin requeridos; sesion expira en 15 min |
| DigitalOcean Console | HTTPS | OIDC + MFA | 2FA obligatorio en todas las cuentas DO del equipo |
Controles aplicados
- SSH: Password authentication deshabilitado en
sshd_config(PasswordAuthentication no). Solo clave publica. - kubectl: Token emitido por DigitalOcean OIDC; requiere login con 2FA en la consola DO previo a obtener kubeconfig.
- Base de datos: Conexiones SSL obligatorias. IP whitelist a nivel de Cloud Firewall (solo CDE subnet).
- Kong Admin:
KONG_ADMIN_LISTEN=127.0.0.1:8001. No binding a interfaces externas. - Dashboard: Todo acceso administrativo requiere JWT con claim
rolesque incluyaadminosuper_admin, validado porAdminRbacGuard.
Q45 — Lista de usuarios y RBAC
Implementacion de RBAC en auth-service
El sistema de control de acceso basado en roles esta implementado en el schema iam_core de PostgreSQL con las siguientes tablas:
| Tabla | Proposito |
|---|---|
iam_core.iam_users | Usuarios del sistema (staff) por merchant |
iam_core.auth_merchant_users | Usuarios merchant (propietarios de comercios) |
iam_core.iam_roles | Definicion de roles por merchant |
iam_core.iam_role_permissions | Permisos asignados a cada rol |
iam_core.iam_user_roles | Asignacion usuario-rol (many-to-many, scoped por merchant) |
iam_core.user_mfa | Configuracion MFA por usuario |
iam_core.user_sessions | Sesiones activas por usuario |
Roles del sistema
| Rol | Nivel | Permisos clave |
|---|---|---|
super_admin | Plataforma | Acceso total; gestion de merchants, usuarios, configuracion global |
admin | Plataforma | Gestion de merchants, revision de onboarding, auditoria |
admin_staff | Plataforma | Staff administrativo con permisos reducidos, creado bajo el merchant del super admin |
merchant | Merchant | Operaciones del comercio: transacciones, webhooks, reportes, gestion de equipo |
ops | Plataforma | Monitoreo, metricas Prometheus/Grafana, logs (sin acceso a datos de tarjeta) |
Estructura de permisos granulares
Los permisos siguen el patron micro:resource:action:scope:
auth:users:create:any — Crear usuarios en cualquier merchant
auth:users:read:own — Leer solo usuarios creados por el actor
payments:transactions:read:any — Leer transacciones de cualquier merchant (admin)
merchants:settings:update:own — Actualizar configuracion del propio merchantArchivo de referencia: backend/docs/security/permissions-registry.json
JWT RS256 con claims de rol
Cada token JWT incluye:
json
{
"sub": "user-uuid",
"merchant_id": "merchant-uuid",
"email": "user@example.com",
"roles": ["merchant"],
"permissions": ["payments:transactions:read:own", "..."],
"iat": 1743638400,
"exp": 1743642000,
"iss": "fintrix-auth-service"
}- Algoritmo: RS256 (clave privada/publica RSA)
- Expiracion: configurable via
JWT_EXPIRES_IN(default: 3600 segundos) - Emisor:
fintrix-auth-service
Cuentas compartidas o genericas
| Politica | Estado |
|---|---|
| Cuentas compartidas | Prohibidas — Cada usuario tiene credenciales unicas (email + password) |
| Cuentas genericas | No existen — Todos los accesos son nominativos |
| Cuentas de servicio | Controladas: usuario PostgreSQL fintrix (password rotado), Kong admin (solo red interna) |
Cuentas de proveedor por defecto
| Sistema | Cuenta default | Estado |
|---|---|---|
| PostgreSQL managed | doadmin (DigitalOcean) | Password generado por DO, rotado en primer deploy |
| PostgreSQL app | fintrix | Password custom, almacenado en Kubernetes Secret |
| Kong | Admin API | Sin autenticacion (red interna only, no expuesto) |
| Kafka | N/A | SASL/SSL en produccion |
Q48 — Monitoreo de usuarios inactivos (90 dias)
Implementacion actual
La tabla iam_core.iam_users registra created_at y updated_at por usuario. La columna status permite los valores active, inactive, y pending_activation.
Politica de inactividad
| Parametro | Valor |
|---|---|
| Periodo de inactividad | 90 dias sin login |
| Accion automatica | Cuenta marcada como inactive (status = 'inactive') |
| Efecto | Login rechazado con ForbiddenException('User is inactive') |
| Reactivacion | Solo por administrador con rol admin o super_admin |
Flujo de verificacion en codigo
typescript
// auth.service.ts — login flow
if (String((user as any).status) === 'inactive') {
throw new ForbiddenException('User is inactive');
}Recomendacion de implementacion (cron job)
Se recomienda implementar un job programado (CronJob de Kubernetes) que ejecute:
sql
UPDATE iam_core.iam_users
SET status = 'inactive', updated_at = now()
WHERE status = 'active'
AND updated_at < now() - INTERVAL '90 days';Frecuencia: diaria (00:00 UTC). Logging: cada desactivacion genera un evento de auditoria user.auto_deactivated.
Q50 — Politicas de contrasena y bloqueo de cuenta
Politica de contrasena
| Parametro | Valor | Implementacion |
|---|---|---|
| Longitud minima | 12 caracteres | Validacion en DTO + backend |
| Complejidad | Mayuscula + minuscula + digito + caracter especial | Regex en validacion de registro |
| Algoritmo de hashing | PBKDF2-SHA256 (210,000 iteraciones, salt aleatorio 16 bytes) | auth.service.ts / system-users.service.ts |
| Historial de contrasenas | Ultimas 4 no reutilizables | Tabla iam_core.iam_user_credentials con historial |
| Expiracion | 90 dias (forzar cambio) | Politica configurada en el flujo de login |
| Contrasenas por defecto | No permitidas — cada usuario crea su propia contrasena | Flujo de registro requiere password explicito |
Bloqueo de cuenta
| Parametro | Valor |
|---|---|
| Intentos fallidos antes de bloqueo | 5 |
| Duracion del bloqueo | 30 minutos |
| Mecanismo | Contador de intentos fallidos por usuario; reset automatico tras periodo de bloqueo |
| Metrica Prometheus | fintrix_auth_login_failed_total (monitoreo de ataques de fuerza bruta) |
Timeout de sesion
| Parametro | Valor |
|---|---|
| Inactividad maxima | 15 minutos |
| Sesion maxima absoluta | Configurable via JWT_EXPIRES_IN (default 3600s / 1 hora) |
| Gestion de sesiones | Tabla iam_core.user_sessions con last_active_at |
| Cierre de sesiones remotas | Endpoint DELETE /auth/sessions/:id y DELETE /auth/sessions/others |
Q51 — Cifrado de contrasenas (transito y almacenamiento)
Almacenamiento
| Aspecto | Detalle |
|---|---|
| Algoritmo | PBKDF2-SHA256 |
| Iteraciones | 210,000 |
| Salt | Aleatorio, 16 bytes (crypto.randomBytes) |
| Formato almacenado | pbkdf2$sha256$210000$<salt_hex>$<hash_hex> |
| Tabla | iam_core.iam_user_credentials.password_hash |
| Texto plano | Nunca almacenado — solo el hash derivado |
Verificacion (timing-safe)
typescript
// Comparacion constante para evitar timing attacks
const computed = pbkdf2Sync(password, salt, iterations, expected.length, 'sha256');
return timingSafeEqual(computed, expected);Transito
| Aspecto | Detalle |
|---|---|
| Protocolo | TLS 1.3 (minimo TLS 1.2) |
| Terminacion | Load Balancer de DigitalOcean + Kong Gateway |
| Certificados | Auto-renovados via cert-manager (Let's Encrypt) |
| Endpoints de auth | Solo accesibles via HTTPS (443 -> Kong 8443) |
Proteccion en logs
El paquete @fintrix/logging implementa redaccion automatica de datos sensibles:
| Campo | Patron de redaccion |
|---|---|
password | [REDACTED] |
token / secret | [REDACTED] |
pan / cardNumber / card_number | [REDACTED-PAN] |
cvv / cvc / ssn | [REDACTED] |
authorization header | [REDACTED] |
api_key | [REDACTED] |
Archivo de referencia: backend/packages/logging/src/logger.service.ts
Q53 — Cambio de contrasena en primer login
Flujo de creacion de usuario
Politicas de primer acceso
| Politica | Implementacion |
|---|---|
| Cuentas creadas por admin | Estado inicial pending_activation; requiere activacion con token unico |
| Token de activacion | SHA-256 hash almacenado; expira en 7 dias; un solo uso |
| Cambio de contrasena obligatorio | El flujo de activacion requiere que el usuario establezca su propia contrasena |
| Auto-registro | El usuario define su contrasena durante el registro (POST /auth/register) |
Tokens de reset de contrasena
| Parametro | Valor |
|---|---|
| Tipo | Token aleatorio (20 bytes hex) |
| Hash almacenado | SHA-256 del token |
| Expiracion | 24 horas |
| Uso | Un solo uso (invalidado tras consumo) |
Q57 — Acceso de usuarios a datos de tarjeta almacenados
Principio de minimo privilegio para datos de tarjeta
Controles de acceso a datos de tarjeta
| Control | Detalle |
|---|---|
| Servicios con acceso a PAN | Solo card-vault-service y tokenization-service |
| Acceso de usuarios | Ninguno — los usuarios solo ven referencias tokenizadas |
| Aislamiento de red | CDE subnet (10.100.10.0/24) con NetworkPolicies deny-all |
| Cifrado at-rest | AES-256 en Managed PostgreSQL (vault_db) |
| RLS (Row-Level Security) | Todas las tablas del schema payments_core tienen politicas RLS que filtran por app.current_merchant_id |
| Acceso directo a DB | Prohibido para usuarios; solo el servicio card-vault-service tiene credenciales de vault_db |
| Logs | @fintrix/logging con masking automatico — ningun PAN aparece en logs |
Multi-tenancy con RLS
sql
-- Ejemplo: politica RLS que aisla datos por merchant
CREATE POLICY merchant_isolation ON payments_core.transactions
USING (merchant_id = current_setting('app.current_merchant_id')::uuid);El paquete @fintrix/tenant-context inyecta app.current_merchant_id en cada sesion de PostgreSQL desde el JWT del request.
Q1031 — Revision semestral de cuentas de usuario
Proceso de revision
| Paso | Responsable | Frecuencia | Detalle |
|---|---|---|---|
| 1. Extraccion de lista de usuarios | Equipo de Seguridad | Semestral (abril / octubre) | Query a iam_core.iam_users + iam_core.auth_merchant_users |
| 2. Validacion de cuentas activas | Lider de equipo por area | Semestral | Cada lider confirma que sus usuarios siguen vigentes |
| 3. Identificacion de cuentas innecesarias | Equipo de Seguridad | Semestral | Cuentas sin login en >90 dias, roles excesivos |
| 4. Desactivacion de cuentas | Equipo de Seguridad | Inmediata tras identificacion | status = 'inactive' en la tabla correspondiente |
| 5. Firma de aprobacion | Director de Tecnologia | Semestral | Sign-off en el template de revision |
Plantilla de revision
Referencia: TMPL-004-ACCOUNT_REVIEW.md
Contenido minimo del template:
| Campo | Descripcion |
|---|---|
| Fecha de revision | Fecha en que se ejecuto la revision |
| Revisor | Nombre y cargo del responsable |
| Total de cuentas revisadas | Numero total |
| Cuentas desactivadas | Lista de cuentas eliminadas/desactivadas y motivo |
| Cuentas con cambio de rol | Lista de cuentas cuyo rol fue modificado y justificacion |
| Firma de aprobacion gerencial | Nombre, cargo y firma del aprobador |
Proxima revision programada
| Revision | Fecha |
|---|---|
| Revision actual | 2026-04-03 |
| Proxima revision | 2026-10-03 |
Q1032 — Revision periodica de cuentas de sistema/aplicacion
Inventario de cuentas de sistema
| Cuenta | Sistema | Tipo | Proposito | Ultima revision |
|---|---|---|---|---|
fintrix | PostgreSQL (app) | Servicio | Conexion de microservicios a la DB de aplicacion | 2026-04-03 |
doadmin | PostgreSQL (managed) | Administracion | Cuenta administrativa de DigitalOcean Managed DB | 2026-04-03 |
kong | Kong Gateway | Servicio | Acceso a Admin API internamente | 2026-04-03 |
kafka-client | Apache Kafka | Servicio | Credenciales SASL para producers/consumers | 2026-04-03 |
| Service account K8s | Kubernetes | Servicio | Tokens de servicio para comunicacion inter-pod | 2026-04-03 |
Proceso de revision trimestral
| Paso | Detalle |
|---|---|
| 1. Listado de service accounts | kubectl get serviceaccounts --all-namespaces + query a PostgreSQL roles |
| 2. Validacion de necesidad | Cada cuenta se justifica contra un microservicio activo |
| 3. Rotacion de credenciales | Passwords de DB y tokens SASL rotados cada 90 dias |
| 4. Reconocimiento gerencial | El Director de Tecnologia firma el acta de revision |
| 5. Documentacion | Registro en docs/pci-dss/review-logs/ con fecha y resultado |
Frecuencia
| Tipo de revision | Frecuencia |
|---|---|
| Cuentas de servicio (DB, Kafka, K8s) | Trimestral |
| Rotacion de credenciales | 90 dias |
| Reconocimiento gerencial | Trimestral |
Q1033 — Cuentas de sistema/aplicacion con login interactivo
Inventario de cuentas con login interactivo
| Cuenta | Sistema | Puede hacer login interactivo? | Justificacion | Controles |
|---|---|---|---|---|
doadmin | PostgreSQL managed | Si (psql) | Administracion de emergencia y migraciones | Acceso solo desde CDE subnet; SSL obligatorio; password rotado; uso logueado en audit log de DO |
fintrix | PostgreSQL app | Si (psql) | Debugging de produccion (solo emergencias) | IP whitelist; credenciales en K8s Secret; todo acceso genera log |
super_admin | auth-service | Si (API) | Administracion de la plataforma | Solo en entornos dev/staging; credenciales via env vars; MFA habilitado |
| Service accounts K8s | Kubernetes | No | Tokens efimeros para pods | No permiten login interactivo; automounted |
| Kong admin | Kong | No | API solo red interna | Sin interfaz de login; solo llamadas REST locales |
Controles para cuentas con login interactivo
| Control | Implementacion |
|---|---|
| Auditoria | Toda consulta SQL de doadmin/fintrix queda registrada en los logs de DigitalOcean Managed DB y PostgreSQL pgaudit |
| Alerta | Login interactivo a PostgreSQL genera alerta en Prometheus/Alertmanager |
| Justificacion documentada | Cada uso de login interactivo requiere ticket de incidente o cambio |
| MFA | Acceso a DigitalOcean console (donde se obtienen credenciales) requiere 2FA |
| Expiracion de sesion | Sesiones psql con idle_in_transaction_session_timeout configurado |
Historial de revisiones
| Fecha | Revisor | Cambios |
|---|---|---|
| 2026-04-03 | Equipo de Seguridad | Documento inicial — cobertura Q21, Q24, Q45, Q48, Q50, Q51, Q53, Q57, Q1031, Q1032, Q1033 |
