ConTodo ERP — Ciberseguridad, RBAC Multi-Tenant, Auditoría y Readiness SOC 2 / ISO 27001
ConTodo ERP — Arquitectura de Seguridad Cloud-Native Multi-Tenant
Propósito. Definir el modelo de seguridad de ConTodo, un ERP SaaS multi-tenant para PYMEs y medianas de Perú y LATAM, sobre el stack objetivo Ruby on Rails + PostgreSQL + Redis + Sidekiq desplegado en AWS (ECS, RDS, S3, CloudFront, Route53, WAF). El documento cubre RBAC granular, auditoría inmutable, cifrado at-rest/in-transit con gestión de llaves, aislamiento de tenants, modelo de amenazas STRIDE, controles OWASP Top 10, matriz de riesgos y la hoja de ruta de readiness SOC 2 Type II e ISO/IEC 27001:2022.
Disclaimer anti-overclaiming. No declaramos "compliance" sino readiness: tener un control diseñado no es lo mismo que tener evidencia de su operación efectiva durante un período de observación (SOC 2 Type II exige 6–12 meses de evidencia). Toda afirmación de seguridad aquí es una decisión de diseño con costo y supuestos explícitos; la seguridad absoluta no existe, se gestiona riesgo residual aceptable. La pieza menos reversible es el modelo de aislamiento de tenants: una fuga cross-tenant en un ERP contable es un evento de extinción de marca.
1. Contexto, supuestos y superficie de exposición
| # | Supuesto | Valor / Justificación |
|---|---|---|
| S1 | Tenant = persona jurídica (RUC) | El límite de confianza primario es el tenant_id. Toda decisión de autorización lo evalúa primero. |
| S2 | Datos críticos | Planillas (PII de trabajadores DNI/CUSPP), certificados digitales SUNAT (.pfx), claves SOL, CPE/PLE/SIRE, estados financieros, cuentas bancarias para tesorería. |
| S3 | Marco legal | Ley 29733 (Protección de Datos Personales, Perú) + D.S. 003-2013-JUS; LGPD (Brasil), Ley 21719 (Chile 2026), Ley 1581 (Colombia) en expansión LATAM. |
| S4 | Residencia de datos | AWS sa-east-1 (São Paulo) preferida por latencia y argumento comercial de residencia regional. |
| S5 | Equipo seguridad inicial | 0 dedicados → 1 Security Engineer + responsabilidad compartida (DevSecOps). La operabilidad es restricción de primer orden. |
| S6 | Modelo de tenancy | Shared schema con tenant_id + PostgreSQL Row-Level Security (RLS) como red de seguridad de base de datos (defensa en profundidad). |
| S7 | Objetivo compliance | SOC 2 Type II (requisito de venta enterprise) + ISO 27001 (palanca LATAM/licitaciones). |
Superficie de ataque principal: API REST/JSON Rails (autenticada), SPA React (token en memoria), endpoints de integración SUNAT/OSE, webhooks de pasarelas (Yape/Plin/Niubiz), jobs Sidekiq, panel de administración interno (back-office), y el bucket S3 de documentos (CPE XML, PDFs, certificados).
2. RBAC multi-tenant: roles y permisos granulares
2.1 Modelo conceptual
ConTodo usa RBAC con scoping multi-tenant y soporte ABAC selectivo (atributos para reglas finas como "solo su sucursal", "monto ≤ X"). La unidad atómica de autorización es el permiso (recurso:acción), no el rol. Los roles son colecciones de permisos; los usuarios reciben roles dentro del scope de un tenant (y opcionalmente de una sucursal).
Entidades:
- Permiso (
permission): tuplarecurso:acción— p.ej.factura:emitir,kardex:ajustar,planilla:aprobar,banco:conciliar. Catálogo cerrado versionado en código (seed), no editable por el cliente. - Rol (
role): agrupación nombrada de permisos. Hay roles de sistema (inmutables:super_adminde plataforma,ownerde tenant) y roles personalizados por tenant. - Asignación (
membership):usuario × tenant × rol × scope_sucursal. Un usuario puede pertenecer a varios tenants (contador externo) con roles distintos en cada uno. - Política contextual (ABAC): condiciones evaluadas en runtime (sucursal propia, límite de monto, horario, segregación de funciones).
2.2 Catálogo de roles base por defecto
| Rol | Scope | Permisos representativos | Principio aplicado |
|---|---|---|---|
Plataforma: super_admin | Global (ConTodo) | Operación de infraestructura; sin acceso a datos de negocio del tenant en claro salvo break-glass auditado | Mínimo privilegio + break-glass |
Tenant owner | Tenant | Todo dentro del tenant, gestión de usuarios y facturación SaaS | Único rol que crea otros admins |
admin_empresa | Tenant | Config empresa, usuarios, roles (excepto crear owners) | Delegación controlada |
contador | Tenant | Contabilidad, EE.FF., PLE/SIRE, asientos; lectura de ventas/compras | Segregación: registra, no aprueba pagos |
tesorero | Tenant/sucursal | Tesorería, conciliación, aprobación de pagos | Segregación con contador |
vendedor | Sucursal | Emitir CPE de su sucursal, CRM, lectura de inventario | ABAC por sucursal + límite de descuento |
almacenero | Almacén | Kardex (movimientos), recepciones, despachos; no ajustes valorizados | Ajuste de valor requiere contador |
rrhh | Tenant | Personal, contratos, planillas (cálculo); aprobación = owner/admin | Doble control de planilla |
auditor (read-only) | Tenant | Lectura total + acceso al audit log; cero escritura | Para revisores/clientes Big Four |
2.3 Segregación de funciones (SoD)
Reglas SoD codificadas y validadas en tiempo de asignación de roles (no solo en runtime):
| Combinación prohibida | Riesgo mitigado |
|---|---|
compra:registrar + pago:aprobar | Pago fraudulento a proveedor ficticio |
proveedor:crear + pago:aprobar | Proveedor fantasma + autopago |
planilla:calcular + planilla:aprobar | Pago indebido de remuneraciones |
asiento:registrar + periodo:cerrar | Ocultamiento de errores contables |
2.4 Diagrama del modelo de permisos
2.5 Enforcement en Rails
- Autorización:
Punditcon políticas por recurso. Cada policy scope fuerzawhere(tenant_id: Current.tenant_id); ninguna query de negocio puede emitirse sin tenant en el contexto (Currentattributes, set en middleware tras autenticar). - Tenant resolution: subdominio (
acme.contodo.app) o claim del JWT →set_current_tenant. Mismatch entre tenant del token y del recurso = 403 + alerta de seguridad. - Doble candado de DB: además de Pundit, PostgreSQL RLS con
current_setting('app.current_tenant')aplicado por conexión, de modo que un bug de lógica de aplicación no basta para filtrar datos de otro tenant.
3. Auditoría: audit log inmutable
| Atributo | Decisión |
|---|---|
| Qué se registra | Login/logout, cambios de rol/permiso, CRUD de entidades financieras (CPE, asientos, pagos), accesos a PII (planillas), exportaciones, acciones de super_admin, break-glass. |
| Esquema del evento | event_id (uuid), tenant_id, actor_id, actor_ip, action, resource_type, resource_id, before, after (jsonb), request_id, occurred_at, signature |
| Inmutabilidad | Tabla audit_events append-only: revocado UPDATE/DELETE al rol de la app vía GRANT; trigger que bloquea modificación; encadenamiento hash (cada evento incluye prev_hash → tamper-evidence tipo blockchain ligero). |
| Almacenamiento secundario | Réplica a S3 con Object Lock (modo Compliance, WORM) + envío a CloudWatch/SIEM. Retención 1 año caliente, 7 años en Glacier (alineado a plazos tributarios SUNAT). |
| Acceso | Solo rol auditor y security; toda lectura del log se audita a su vez (meta-auditoría). |
El encadenamiento hash permite detectar manipulación; el S3 Object Lock WORM la previene. Doble garantía deliberada: SOC 2 (CC7.x) e ISO 27001 A.8.15 exigen logs protegidos contra alteración.
4. Cifrado y gestión de llaves
| Capa | Control | Detalle |
|---|---|---|
| In-transit (externo) | TLS 1.3 | CloudFront + ACM, HSTS max-age=63072000; includeSubDomains; preload, cifrados modernos, OCSP stapling. |
| In-transit (interno) | TLS / mTLS | RDS rds.force_ssl=1; Redis TLS (in-transit encryption); mTLS entre servicios en ECS donde aplique. |
| At-rest (DB) | AES-256 KMS | RDS encryption (CMK por entorno); snapshots cifrados. |
| At-rest (objetos) | SSE-KMS | S3 con CMK, bucket key habilitado para reducir costo de KMS; sin objetos públicos (Block Public Access ON). |
| Application-level | Cifrado de campo | Active Record Encryption (AEAD) para PII y secretos: DNI, CUSPP, cuentas bancarias, claves SOL, certificados .pfx. Cifrado determinístico solo donde se necesita búsqueda exacta; no determinístico por defecto. |
| Secretos | AWS Secrets Manager | Credenciales de DB, claves SUNAT/OSE, tokens de pasarelas; rotación automática; sin secretos en código ni en variables de entorno en claro. |
| Gestión de llaves | AWS KMS | CMK por dominio (DB, S3, app); rotación anual automática; políticas de key con separación de funciones; CloudTrail sobre cada uso de llave. |
Decisión justificada (alternativa descartada): se evaluó cifrado por-tenant con CMK independiente (BYOK). Se descarta para el MVP por costo operativo de KMS (miles de llaves) y complejidad; se reserva como add-on enterprise para clientes que lo exijan contractualmente. El cifrado a nivel de aplicación sobre PII cubre el riesgo dominante (exposición de la base) sin esa complejidad.
5. Aislamiento de tenants (defensa en profundidad)
Capas: (1) aplicación — Current.tenant_id obligatorio + scopes Pundit; (2) base de datos — RLS por sesión; (3) almacenamiento — prefijos S3 por tenant tenant/<id>/... con políticas IAM/condiciones; (4) jobs — Sidekiq propaga tenant_id en el payload y lo re-establece en Current antes de ejecutar (un job sin tenant aborta). Tests de aislamiento automatizados en CI: cada endpoint se prueba con dos tenants para verificar que A no ve datos de B (regresión cross-tenant es bloqueante de merge).
6. Modelo de amenazas STRIDE
| Amenaza (STRIDE) | Escenario en ConTodo | Control |
|---|---|---|
| Spoofing | Robo de sesión, suplantación de tenant en JWT | MFA/2FA, JWT corto + refresh rotatorio, validación de claim tenant_id, rate-limit en login, detección de credential stuffing |
| Tampering | Alteración de asientos, kardex o audit log | RLS, integridad de DB, audit log encadenado por hash + WORM, firmas de payload de webhooks |
| Repudiation | "Yo no aprobé ese pago" | Audit log inmutable con actor/IP/request_id, doble control SoD, sello temporal |
| Information Disclosure | Fuga cross-tenant, exposición de PII/certificados | Aislamiento multicapa, cifrado de campo, S3 sin acceso público, principio de mínimo privilegio |
| Denial of Service | Abuso de API, scraping, ataque volumétrico | AWS WAF (rate-based rules), CloudFront, autoscaling ECS, límites por tenant (quotas), Shield Standard |
| Elevation of Privilege | Bug de autorización, IDOR, escalamiento a super_admin | Pundit deny-by-default, validación SoD en asignación, separación de plano de plataforma vs. tenant, revisión de PR de seguridad |
7. Controles OWASP Top 10 (2021)
| OWASP | Riesgo | Control en ConTodo |
|---|---|---|
| A01 Broken Access Control | IDOR, salto de tenant | Pundit deny-by-default + RLS + tests cross-tenant en CI |
| A02 Cryptographic Failures | PII/secretos expuestos | TLS 1.3, KMS, Active Record Encryption, Secrets Manager |
| A03 Injection | SQLi, XSS | ActiveRecord parametrizado, escape React por defecto, CSP estricta, strong_params |
| A04 Insecure Design | Falta de threat modeling | STRIDE, SoD, threat model por epic en diseño |
| A05 Security Misconfiguration | Buckets abiertos, headers laxos | IaC (Terraform) revisado, S3 Block Public Access, secure_headers, baseline CIS |
| A06 Vulnerable Components | Gema/lib con CVE | Dependabot, bundler-audit, SCA en CI, SBOM |
| A07 Identification & Auth Failures | Brute force, sesiones débiles | Devise + MFA, lockout, política de contraseñas, refresh rotatorio |
| A08 Software & Data Integrity | Supply chain, deploy malicioso | Firmas de imagen, CI/CD con OIDC (sin llaves estáticas), aprobación de deploy a prod |
| A09 Logging & Monitoring Failures | Ataque no detectado | Audit log + CloudWatch + alertas + SIEM, runbooks de IR |
| A10 SSRF | Webhooks/integraciones SUNAT abusadas | Allowlist de destinos, validación de URL, egress controlado por SG |
8. Matriz de riesgos
| ID | Riesgo | Probabilidad | Impacto | Nivel | Mitigación | Control / Framework |
|---|---|---|---|---|---|---|
| R01 | Fuga de datos cross-tenant (IDOR/bug de scope) | Media | Crítico | Alto | RLS + Pundit + tests cross-tenant en CI bloqueantes | OWASP A01 / SOC2 CC6.1 / ISO A.5.15 |
| R02 | Compromiso de certificado digital SUNAT (.pfx) o clave SOL | Baja | Crítico | Alto | Cifrado de campo + Secrets Manager + acceso mínimo + auditoría de uso | ISO A.8.24 / Ley 29733 |
| R03 | Exfiltración de PII de planillas (DNI/CUSPP) | Media | Alto | Alto | Cifrado AEAD, RBAC rrhh, masking en logs, DLP en exportaciones | Ley 29733 / SOC2 CC6.x |
| R04 | Escalamiento de privilegios a super_admin | Baja | Crítico | Alto | Separación plano plataforma/tenant, break-glass auditado, MFA obligatorio | OWASP A01/STRIDE-E |
| R05 | Manipulación del audit log para ocultar fraude | Baja | Alto | Medio | Append-only + hash chain + S3 Object Lock WORM | ISO A.8.15 / SOC2 CC7.2 |
| R06 | Credential stuffing / robo de sesión | Alta | Alto | Alto | MFA, rate-limit, refresh rotatorio, detección de anomalías | OWASP A07 |
| R07 | Dependencia vulnerable (CVE en gema/npm) | Alta | Medio | Medio | Dependabot, bundler-audit, SCA en CI, SLA de parcheo | OWASP A06 |
| R08 | Ransomware / pérdida de datos | Baja | Crítico | Alto | Backups cifrados PITR, snapshots inmutables, DR cross-AZ, RPO≤5min/RTO≤1h | SOC2 A1.2 / ISO A.8.13 |
| R09 | Misconfiguración de S3 (bucket público) | Media | Crítico | Alto | Block Public Access org-wide, Config rules, IaC revisado | OWASP A05 |
| R10 | DoS / abuso de API | Media | Medio | Medio | WAF rate-limit, quotas por tenant, autoscaling, Shield | OWASP/STRIDE-D |
| R11 | Insider malicioso (empleado ConTodo) | Baja | Alto | Medio | Mínimo privilegio, JIT access, auditoría, background checks, SoD | SOC2 CC1.x / ISO A.6.1 |
| R12 | SSRF vía integraciones SUNAT/OSE/webhooks | Baja | Alto | Medio | Allowlist destinos, egress SG, validación URL | OWASP A10 |
| R13 | Incumplimiento Ley 29733 (consentimiento/derechos ARCO) | Media | Alto | Alto | Registro de tratamiento, flujos ARCO, DPA con subprocesadores | Ley 29733 |
| R14 | Pérdida/rotación fallida de llaves KMS | Baja | Crítico | Medio | KMS rotación automática, política multi-administrador, backups de envelope | ISO A.8.24 |
Escala de nivel: combinación probabilidad × impacto. Alto = requiere mitigación antes de GA o compensación documentada. Medio = mitigación planificada con SLA. El riesgo residual aceptado se firma por el responsable de seguridad y se revisa trimestralmente.
9. SOC 2 readiness (Trust Services Criteria)
| TSC | Criterio | Estado de diseño en ConTodo |
|---|---|---|
| Security (CC) | Control de acceso, gestión de cambios, monitoreo | RBAC+RLS, CI/CD con aprobaciones, audit log, SIEM — diseñado |
| Availability (A) | Backups, DR, capacity | PITR, multi-AZ, autoscaling, SLA 99.9% — diseñado |
| Confidentiality (C) | Clasificación y cifrado de datos confidenciales | Cifrado de campo, KMS, controles de acceso — diseñado |
| Processing Integrity (PI) | Procesamiento completo/exacto | Validaciones contables, conciliación, idempotencia de jobs — parcial |
| Privacy (P) | Tratamiento de datos personales | Flujos ARCO, registro de tratamiento — en diseño |
Camino: (1) política de seguridad de la información y de aceptable use; (2) implementar controles CC6–CC9; (3) Type I (diseño en un punto en el tiempo, ~mes 6); (4) ventana de observación 6–12 meses; (5) Type II (auditoría con evidencia de operación). Plataformas de compliance (Vanta/Drata) automatizan la recolección de evidencia y reducen el esfuerzo manual ~60–70%.
10. ISO/IEC 27001:2022 readiness
| Fase | Entregable |
|---|---|
| Alcance del SGSI | ConTodo SaaS, infraestructura AWS, equipo de ingeniería |
| Liderazgo | Política del SGSI aprobada por dirección, roles definidos |
| Evaluación de riesgos | Esta matriz (sección 8) como base del Risk Treatment Plan |
| Declaración de aplicabilidad (SoA) | Mapeo de los 93 controles del Anexo A (4 temas: Organizacional, Personas, Físico, Tecnológico) |
| Controles clave | A.5.15 (acceso), A.8.13 (backup), A.8.15 (logging), A.8.24 (cripto), A.8.28 (codificación segura) |
| Auditoría | Interna → Certificación Etapa 1 (documental) y Etapa 2 (operación) |
ISO 27001 es palanca comercial fuerte en licitaciones públicas peruanas y contratos LATAM; comparte ~80% de controles con SOC 2, por lo que se persiguen en paralelo.
11. Recomendaciones priorizadas
- Bloqueante GA: tests de aislamiento cross-tenant en CI + RLS activado (R01).
- Bloqueante GA: MFA obligatorio para roles administrativos y manejo seguro de certificados SUNAT (R02, R06).
- Mes 1–3: audit log inmutable con hash chain + S3 Object Lock; pipeline DevSecOps (SCA, SAST, dependabot).
- Mes 3–6: SOC 2 Type I + arranque del SGSI ISO 27001; flujos ARCO Ley 29733.
- Mes 6–12: ventana de observación SOC 2 Type II; pentest externo anual; programa de bug bounty privado.
Conclusión. La seguridad de ConTodo se construye sobre tres pilares no negociables: aislamiento multicapa de tenants (app + RLS + storage), auditoría inmutable y verificable, y cifrado de PII/secretos con gestión de llaves disciplinada. El riesgo dominante de un ERP contable multi-tenant es la fuga cross-tenant; por eso se trata con doble candado y verificación automatizada. La readiness SOC 2 + ISO 27001 no es un fin en sí: es la formalización auditable de controles que, en cualquier caso, este producto necesita para ser vendible a empresas que confían su contabilidad y sus planillas a la nube.