Skip to content

PCI DSS Pregunta 38 — Separación lógica entre entornos (Production vs Staging)

CampoValor
SolicitanteJosé David Álvarez — QSA ControlCase
Comentario QSA"Por favor proveer pantallazos con las configuraciones de red que confirmen la independencia de ambientes mencionada"
Fecha de extracción2026-05-27
Tipo de evidenciaVPCs + clusters + DBs separados + test de aislamiento ejecutado
EstadoRESUELTO — Staging environment desplegado, separación verificada en runtime
Paquete adjuntoq38-env-separation-20260527.tar.gz

Resumen ejecutivo: Fintrixs separa los entornos production y staging a nivel físico de red: 2 VPCs distintos en DigitalOcean (CIDR 10.100.0.0/16 para prod, 10.101.0.0/16 para staging), 2 clusters DOKS independientes, 2 bases de datos PostgreSQL Managed separadas, firewalls dedicados por entorno, y trusted sources de DB que rechazan cross-environment connections. Aislamiento verificado en runtime: ping y TCP desde un pod prod (10.100.0.16) hacia un nodo staging (10.101.0.3) resultan en 100% packet loss y timeout — DigitalOcean VPCs son redes L2 independientes sin posibilidad de peering. Costo adicional staging: ~$39/mes (1 nodo K8s + DB pequeña + VPC/firewall gratis).


1. Arquitectura de 2 entornos separados

┌───────────────────────────────────────────────────────────────────────────┐
│                    PRODUCTION (fintrix-production-*)                       │
├───────────────────────────────────────────────────────────────────────────┤
│  VPC:        fintrix-production-vpc       (10.100.0.0/16)                  │
│  Cluster:    fintrix-production-k8s       (K8s 1.34.8-do.0, 6 nodes)       │
│  Pools:      cde-pool + app-pool + system-pool                             │
│  Database:   fintrix-production-fintrix-pci  (PG 16, db-s-2vcpu-4gb)        │
│  Droplets:   collector, cdd, vapt, bitwarden, 6 k8s nodes                  │
│  Firewalls:  fintrix-production-{cde,app,dmz,mgmt,cdd,collector,vapt}-fw   │
│  Real data:  Cardholder data REAL (PCI scope), merchants, transactions      │
└───────────────────────────────────────────────────────────────────────────┘

                ╳   NO ROUTING — NO PEERING — NO CROSS-VPC TRAFFIC   ╳

┌───────────────────────────────────────────────────────────────────────────┐
│                       STAGING (fintrix-staging-*)                          │
├───────────────────────────────────────────────────────────────────────────┤
│  VPC:        fintrix-staging-vpc          (10.101.0.0/16)                  │
│  Cluster:    fintrix-staging-k8s          (K8s 1.34.8-do.0, 1 node)        │
│  Pools:      staging-pool                                                   │
│  Database:   fintrix-staging-fintrix-pci   (PG 16, db-s-1vcpu-1gb)          │
│  Droplets:   staging-pool-38lwy4                                           │
│  Firewalls:  fintrix-staging-app-fw  +  k8s-public-access-97577f4a         │
│  Data:       Synthetic only (NUNCA cardholder data REAL)                   │
└───────────────────────────────────────────────────────────────────────────┘

Architecture comparison


2. VPCs separados (separación de red física)

Listado real

bash
$ doctl vpcs list --format Name,Region,IPRange,ID --no-header | grep fintrix

fintrix-production-vpc   nyc1   10.100.0.0/16   402acbe1-7336-4fde-ad20-e890013b8214
fintrix-staging-vpc      nyc1   10.101.0.0/16   11e94855-7a24-452f-b648-2600731fd387
VPCCIDRIDMiembros
production10.100.0.0/16402acbe1-...10 droplets (incl. 6 K8s nodes)
staging10.101.0.0/1611e94855-...1 droplet (staging-pool-38lwy4)

Característica arquitectónica de DigitalOcean:

  • VPCs son redes L2 independientes en backplane privado
  • NO existe VPC peering disponible (limitación de DO platform)
  • Tráfico cross-VPC SOLO posible vía internet (public IPs + firewall traversal)
  • Tráfico intra-VPC fluye por backplane privado de DO (no internet)

VPC separation

Captura directa del panel DigitalOcean — Networking → VPC

DO VPCs list — prod y staging visibles

Miembros del VPC production

DO VPC production — 10 droplets miembros

Miembros del VPC staging

DO VPC staging — solo staging-pool node


3. Clusters K8s y Databases separados

Clusters

bash
$ doctl k8s cluster list --format Name,Region,VersionSlug --no-header

fintrix-production-k8s    nyc1    1.34.8-do.0 cluster PROD (6 nodes)
fintrix-staging-k8s       nyc1    1.34.8-do.0 cluster STAGING (1 node)
ProductionStaging
Nombrefintrix-production-k8sfintrix-staging-k8s
Cluster IDa19e81ac-537a-44ed-a228-8010f561a53097577f4a-346a-4008-841f-66dce3b4a921
K8s version1.34.8-do.01.34.8-do.0 (parity)
Nodepools3 (cde + app + system)1 (staging)
Nodes61
VPCfintrix-production-vpcfintrix-staging-vpc

Databases

bash
$ doctl databases list --format Name,Engine,Status,Region --no-header

fintrix-production-fintrix-pci    pg    online    nyc1 PROD DB
fintrix-staging-fintrix-pci       pg    online    nyc1 STAGING DB
ProductionStaging
Nombrefintrix-production-fintrix-pcifintrix-staging-fintrix-pci
DB ID061abee8-1d2c-49f4-be08-55f0054288cb75917799-1bf3-4cc3-85d6-71b9dba38e3d
EnginePostgreSQL 16PostgreSQL 16 (parity)
Sizedb-s-2vcpu-4gbdb-s-1vcpu-1gb
Storage60 GiB10 GiB
DataCardholder data REALSynthetic only

Clusters and DBs comparison

Captura directa del panel DigitalOcean — Kubernetes

Lista de clusters (ambos visibles en la cuenta)

DO K8s clusters list — prod y staging

Cluster production (overview)

DO K8s production cluster overview

Cluster staging (overview)

DO K8s staging cluster overview

Captura directa del panel DigitalOcean — Databases

DO Databases list — prod y staging


4. DB trusted sources (control crítico)

Cada base de datos permite conexiones solo desde su propio cluster — no cross-environment.

Production DB firewall

$ doctl databases firewalls list 061abee8-...  (PROD DB)

UUID                                    Type       Value
1cd4c5b2-e1e2-43d4-9f1f-...           k8s        a19e81ac-...-prod-cluster
4aa82dd4-e7e6-4735-8eac-...           ip_addr    10.100.10.0/24  (APP pool)

Staging DB firewall

$ doctl databases firewalls list 75917799-...  (STAGING DB)

UUID                                    Type    Value
6661a809-4bb0-46cb-9514-...           k8s     97577f4a-...-staging-cluster

Resultado: cross-environment access es IMPOSIBLE:

  • 🚫 PROD DB rechaza conexiones desde el staging cluster ID (97577f4a-...)
  • 🚫 STAGING DB rechaza conexiones desde el prod cluster ID (a19e81ac-...)
  • 🚫 Cualquier IP fuera de los trusted sources → connection refused

Database trusted sources

Captura directa del panel — Trusted Sources de cada DB

Production DB → Settings → Trusted Sources

DO Production DB trusted sources — solo cluster prod

Staging DB → Settings → Trusted Sources

DO Staging DB trusted sources — solo cluster staging

Observa: la lista de "Trusted Sources" de la PROD DB NO incluye el cluster staging (97577f4a-...) y la STAGING DB NO incluye el cluster prod (a19e81ac-...). Esto es enforcement técnico cross-environment a nivel de DigitalOcean Managed DBaaS.


5. Test EJECUTADO de aislamiento cross-VPC

Test en vivo desde un pod en producción (cluster fintrix-production-k8s, hostNetwork sobre nodo cde-38q702 = 10.100.0.16) intentando alcanzar el cluster staging (nodo en 10.101.0.3):

bash
$ kubectl run cross-vpc-test --image=nicolaka/netshoot \
    --overrides='{spec:{hostNetwork:true,nodeSelector:{kubernetes.io/hostname: cde-38q702}}}'

# Test 1: ICMP ping
$ kubectl exec cross-vpc-test -- ping -c 3 -W 5 10.101.0.3

PING 10.101.0.3 (10.101.0.3) 56(84) bytes of data.
--- 10.101.0.3 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2047ms BLOQUEADO

# Test 2: TCP a puerto 22
$ kubectl exec cross-vpc-test -- timeout 8 nc -zvw 5 10.101.0.3 22

nc: connect to 10.101.0.3 port 22 (tcp) timed out: Operation in progress   ← ✓ TIMEOUT

Conclusión técnica

TestResultadoInterpretación
Ping ICMP prod→staging100% packet lossSin ruta en routing table
TCP nc :22 prod→stagingTimeout 8sSin path L3 entre VPCs
DNS staging DB hostnameResolves (público)Conexión solo posible via internet+firewall

DO VPCs son redes L2 independientes en backplane privado; no existe route propagation entre VPCs y la plataforma DO no permite VPC peering. El aislamiento físico está garantizado por la arquitectura de red del cloud provider.

Cross-VPC isolation test


6. Costo y rationale del staging environment

RecursoSizeCost/mes
fintrix-staging-vpcVPC nyc1FREE
fintrix-staging-k8s (1 nodo)s-2vcpu-4gb$24/mes
fintrix-staging-fintrix-pcidb-s-1vcpu-1gb$15/mes
fintrix-staging-app-fwCloud FirewallFREE
Egress traffic~10 GB/mesFREE (incluido)
TOTAL~$39/mes

Justificación de la inversión

RazónImpacto
PCI v4 Req 6.5.3 mandata separación prod/pre-prodAudit-required
Evitar "shadow testing" contra producciónReduce audit findings
Smoke/integration tests sin tocar customer dataMitiga PR risk
Pre-prod validation antes de surge upgrade DOKS prodReduce production incidents
Rollback rehearsals + DR drills sin riesgo a clientesBuild operational muscle

ROI: 1 incidente PCI evitado >> $39/mes en 12 meses (>$468/año).

Cost and rationale


7. POL-005 — Reglas de flujo de datos prod ↔ staging

Prohibido absolutamente

AcciónPor qué
❌ Copiar production DB → staging DBContiene cardholder data (PCI Req 6.5.3.b)
❌ Copiar production logs → stagingPueden contener PII y PAN tokens
❌ Apuntar staging app a production DBCross-env DB connection
❌ Hardcoded production credentials en stagingPrivilege escalation path
❌ Manual SSH del developer a producción para "quick fixes"Bypass de SDLC

Permitido y recomendado

AcciónMecanismo
✓ Synthetic data generator para stagingscripts/seed-staging.sh
✓ E2E smoke tests en staging con mock dataGitHub Actions matrix
✓ Integration tests CI desplegados temporalmentePR-triggered deploy
✓ Performance tests + chaos engineeringLitmus + k6 en staging
✓ Rollback rehearsals con snapshots de stagingdoctl databases snapshot

Controles técnicos que lo enforzan

ControlImplementación
DB trusted sourcesProd DB rechaza staging cluster ID
VPC isolationSin routes entre 10.100/16 ↔ 10.101/16
Service accounts separadosProd SA no tiene staging perms
Secrets scopingProduction secrets NO existen en staging (Vault)

Data flow rules


8. Cumplimiento PCI DSS Q38 — mapping

Requisito PCI v4Control FintrixsStatus
Req 6.5.3.a Pre-prod environments separated from prodVPC 10.100/16 vs 10.101/16 + clusters + DBs separados
Req 6.5.3.b Live PANs NOT used in pre-prodPOL-005 + DB trusted sources + synthetic data only
Req 6.5.3.1 Separation of roles and dataK8s RBAC + DB credentials separados por entorno
Req 6.5.4 Separate dev/test/prod dataSynthetic seeds en staging, NUNCA copy de prod
Req 6.4.6 Emergency changes documentedBranch protection + admin override audited

PCI compliance mapping


9. Cómo replicar la verificación

bash
# 1. Listar VPCs
doctl vpcs list --format Name,Region,IPRange,ID --no-header | grep fintrix

# 2. Listar clusters
doctl k8s cluster list --format Name,Region,VersionSlug,Status.State --no-header

# 3. Listar databases
doctl databases list --format Name,Engine,Status,Region --no-header

# 4. Trusted sources de cada DB
doctl databases firewalls list <PROD_DB_ID>
doctl databases firewalls list <STAGING_DB_ID>

# 5. Droplets por VPC
doctl compute droplet list --format Name,VPCUUID --no-header | \
  awk '$2=="402acbe1-..." {print "PROD:", $1}; $2=="11e94855-..." {print "STAGING:", $1}'

# 6. Test cross-VPC isolation
kubectl run isolation-test --image=nicolaka/netshoot \
  --overrides='{"spec":{"hostNetwork":true,"nodeSelector":{...prod node...}}}'
kubectl exec isolation-test -- ping -c 3 <staging-node-private-ip>

10. Paquete de evidencia descargable

📥 Descargar evidencia completa (q38-env-separation-20260527.tar.gz)

Contenido:

q38-env-separation/
├── 00-README.txt              ← Resumen ejecutivo
├── 01-resource-comparison.txt VPCs + clusters + DBs prod vs staging
├── 02-k8s-clusters.json       JSON completo de DOKS clusters
├── 03-databases.json          JSON completo de databases
├── 04-vpcs.json               JSON completo de VPCs
├── 05-firewalls.json          JSON completo de Cloud Firewalls
└── 06-droplets.json           Droplets con su VPC assignment

11. Conclusión para el QSA

  1. Separación lógica + física verificada: 2 VPCs DigitalOcean en nyc1 con CIDR no-overlapping (10.100/16 prod, 10.101/16 staging), sin posibilidad de peering, sin route propagation.

  2. Infraestructura completa duplicada por entorno:

    • Cluster K8s separado (fintrix-production-k8s vs fintrix-staging-k8s)
    • PostgreSQL DB separada (fintrix-production-fintrix-pci vs fintrix-staging-fintrix-pci)
    • Firewalls dedicados
    • Naming convention clara: fintrix-{environment}-*
  3. DB trusted sources rechazan cross-environment connections — control técnico verificable vía doctl databases firewalls list.

  4. Test de aislamiento ejecutado en vivo: ping y TCP desde pod prod hacia nodo staging → 100% packet loss + timeout.

  5. POL-005 prohíbe explícitamente copy de production data hacia staging (PCI Req 6.5.3.b satisfecho con control técnico + procedural).

  6. Decisión arquitectónica documentada: staging deployed 2026-05-27 (~$39/mes) como remediation del gap PCI v4 Req 6.5.3.

Evidencia auditable extraída en vivo el 2026-05-27 y empaquetada en el tarball adjunto.


Historial de revisiones

FechaRevisorCambios
2026-05-27Gabriel Ureña (CTO Fintrixs)Creación inicial — staging environment desplegado, separación de red verificada via cross-VPC isolation test

Documentación Confidencial — Solo para uso interno y auditoría PCI DSS