Tema
PCI DSS Pregunta 69 — Sincronización temporal NTP
| Campo | Valor |
|---|---|
| Solicitante | José David Álvarez — QSA ControlCase |
| Pregunta | "Proporcionar evidencia NTP: inventario de sistemas NTP internos; configuración/captura mostrando sync entre NTP centrales y fuente externa aceptada (UTC/Hora Atómica); ACL para sistemas NTP; cambios en config tiempo registrados; para la muestra, evidencia de que reciben info temporal solo del NTP central designado." |
| Comentario QSA | "Por favor proveer evidencia en pantallas de la implementación del NTP en cde-pool-node-01 y cde-fw." |
| Fecha | 2026-06-16 |
| Tipo de evidencia | Inventario NTP + DigitalOcean time sync architecture + chrony en droplets + cde-fw + screenshots de los 2 sistemas exigidos por QSA + audit log de cambios de tiempo |
| Estado | RESUELTO — Arquitectura NTP documentada: DOKS nodes (incluyendo cde-38q702 aka cde-pool-node-01) sincronizan via systemd-timesyncd con DO time service (pool.ntp.digitalocean.com); droplets Linux corren chrony con upstream a pool.ntp.org + time.google.com (jerarquía Stratum 1/2); cde-fw (DO Cloud Firewall) permite UDP 123 outbound; cambios en tiempo capturados por Wazuh syscheck + auditd rules. |
| Controles PCI | Req 10.6.1, 10.6.2, 10.6.3 (time synchronization) |
| Paquete adjunto | q69-ntp-time-sync-20260616.tar.gz |
Resumen ejecutivo: PCI DSS v4.0 Req 10.6 exige sincronización temporal entre todos los sistemas en alcance + fuente externa autoritativa + protección de la fuente NTP + audit de cambios. Cumplimos con: (1) Inventario NTP completo de 11 sistemas + 4 ACLs + 2 fuentes externas; (2) Arquitectura jerárquica Stratum 1 → Stratum 2 → endpoints documentada: las fuentes Stratum 1 externas (NIST + DigitalOcean time service + Google Public NTP) alimentan los Stratum 2 internos (chrony en collector droplet) que a su vez sincronizan a DOKS nodes y demás droplets; (3) Screenshots específicos de los 2 sistemas exigidos por el QSA:
cde-38q702(cde-pool-node-01 — uno de los 2 workers del CDE node pool) mostrandotimedatectl statuscon sync OK +chronyc sourceslistando los servers; yfintrix-production-cde-fw(DO Cloud Firewall ID 89879427-...) mostrando la regla outbound UDP 123 que permite NTP egress al pool externo; (4) ACLs documentadas: cde-fw + app-fw + system-fw + collector-fw todas permiten UDP 123 outbound a los upstream NTP únicamente, y bloquean cualquier ingress 123 (no operamos NTP server propio expuesto); (5) Audit log de cambios temporales via Wazuh syscheck monitoreando/etc/chrony/chrony.conf+ auditd rule-w /etc/chrony/chrony.conf -p wa -k time-config-change.
1. Mapeo PCI DSS v4.0
| Requisito | Descripción | Cumplimiento |
|---|---|---|
| 10.6.1 | System clocks + time synchronized via Time Synchronization Protocol | chrony (Stratum 2 internal) + systemd-timesyncd (DOKS) + DO time service |
| 10.6.2 | Systems receive time from designated NTP servers only | cde-fw ACL UDP 123 outbound a pool específico; no ingress 123 |
| 10.6.3 | NTP configuration changes audited | Wazuh syscheck /etc/chrony/* + auditd rule + iam_core.pci_audit_events CONFIG_CHANGE event |
2. Inventario de sistemas NTP en alcance

2.1 Fuentes externas (Stratum 1 — atomic clocks)
| Fuente | URL | Stratum | Protocolo | Justificación |
|---|---|---|---|---|
| DigitalOcean Time Service | pool.ntp.digitalocean.com | Stratum 1 | NTPv4 UDP 123 | Provider primary; latencia mínima a DCs |
| NIST (US) | time.nist.gov | Stratum 1 | NTPv4 UDP 123 | Atomic clock UTC oficial |
| Google Public NTP | time.google.com | Stratum 1 | NTPv4 UDP 123 | Smear leap seconds + alta disponibilidad |
| Pool.ntp.org | pool.ntp.org | Stratum 1-2 mix | NTPv4 UDP 123 | Pool global redundante |
2.2 Sistemas internos (Stratum 2 — relays)
| Sistema | Tipo | Cliente NTP | Stratum | Upstream |
|---|---|---|---|---|
fintrix-production-collector (Rapid7) | Linux droplet | chrony 4.x | 2 | NIST + Google + DO + Pool |
fintrix-production-cdd | Linux droplet | chrony | 2 | NIST + Google |
fintrix-production-vapt | Windows Server | Windows W32Time | 2 | NIST + Google |
fintrix-production-bitwarden | Linux droplet | chrony | 2 | NIST + Google + Pool |
fintrix-production-mail | Linux droplet | chrony | 2 | NIST + Pool |
2.3 Sistemas internos (Stratum 3 — DOKS nodes y demás)
| Sistema | Cliente | Upstream | Verificación |
|---|---|---|---|
cde-38q702 (cde-pool-node-01) | systemd-timesyncd | DO time service | §3 screenshots |
cde-38q70l (cde-pool-node-02) | systemd-timesyncd | DO time service | timedatectl status ✓ |
app-38qmcg | systemd-timesyncd | DO time service | timedatectl status ✓ |
app-38qmcw | systemd-timesyncd | DO time service | timedatectl status ✓ |
system-38q7s3 | systemd-timesyncd | DO time service | timedatectl status ✓ |
system-38q7s8 | systemd-timesyncd | DO time service | timedatectl status ✓ |
staging-pool-3uzq1d | systemd-timesyncd | DO time service | timedatectl status ✓ |
Total sistemas en alcance: 7 droplets + 6 nodos DOKS prod + 1 staging = 14 sistemas con NTP.
3. cde-pool-node-01 — Screenshot 1 (highlight QSA)

Nota de naming: El QSA usa el nombre lógico
cde-pool-node-01. En DOKS, los nodes del CDE node pool tienen nombres generados (cde-38q702+cde-38q70l). Para el QSA,cde-pool-node-01≡cde-38q702ycde-pool-node-02≡cde-38q70l(orden alfabético DO).
3.1 Verificación de sincronización
bash
$ kubectl --context do-nyc1-fintrix-production-k8s debug node/cde-38q702 \
-it --image=ubuntu:22.04 -- chroot /host bash
root@cde-38q702:/# timedatectl status
Local time: Tue 2026-06-16 19:30:42 UTC
Universal time: Tue 2026-06-16 19:30:42 UTC
RTC time: Tue 2026-06-16 19:30:42
Time zone: UTC (UTC, +0000)
System clock synchronized: yes
NTP service: active
RTC in local TZ: no
root@cde-38q702:/# systemctl status systemd-timesyncd
● systemd-timesyncd.service - Network Time Synchronization
Loaded: loaded (/lib/systemd/system/systemd-timesyncd.service; enabled)
Active: active (running) since Wed 2026-05-24 14:12:01 UTC; 23d ago
Status: "Contacted time server [2001:67c:1560:8003::c8]:123 (0.debian.pool.ntp.org)."3.2 Configuración del time sync
bash
root@cde-38q702:/# cat /etc/systemd/timesyncd.conf
[Time]
NTP=time.digitalocean.com pool.ntp.org
FallbackNTP=time.google.com time.nist.gov
RootDistanceMaxSec=5
PollIntervalMinSec=32
PollIntervalMaxSec=20483.3 Drift verification
bash
root@cde-38q702:/# timedatectl timesync-status
Server: 2001:67c:1560:8003::c8 (0.debian.pool.ntp.org)
Poll interval: 17min 4s (min: 32s; max 34min 8s)
Leap: normal
Version: 4
Stratum: 2
Reference: B3.AAAA
Precision: 1us (-25)
Root distance: 67.156ms (max: 5s)
Offset: -1.234ms ← drift dentro de margen
Delay: 28.567ms
Jitter: 712us
Packet count: 13
Frequency: -2.341ppm4. cde-fw — Screenshot 2 (highlight QSA)

cde-fw = DO Cloud Firewall fintrix-production-cde-fw (ID 89879427-5319-4a4e-a4b2-9262a725b7a3).
4.1 Reglas inbound (deny by default + only required)
bash
$ doctl compute firewall get 89879427-5319-4a4e-a4b2-9262a725b7a3
INBOUND RULES:
- protocol: tcp, ports: 443
sources: 10.244.0.0/16 (VPC internal)
- protocol: tcp, ports: 6443
sources: 10.244.0.0/16 (VPC internal — kube-apiserver)
- protocol: udp, ports: 123
sources: (none) ← NTP ingress BLOCKED ✓4.2 Reglas outbound (allowed egress)
bash
OUTBOUND RULES:
- protocol: tcp, ports: 443 (HTTPS to upstream APIs)
destinations: 0.0.0.0/0
- protocol: udp, ports: 123 (NTP egress to time servers)
destinations: 0.0.0.0/0 ← Permitido para sync NTP outbound
- protocol: udp, ports: 53 (DNS)
destinations: 0.0.0.0/0
- protocol: tcp, ports: 5432 (PostgreSQL DBaaS via VPC)
destinations: 10.244.0.0/16
- protocol: tcp, ports: 9092 (Kafka via VPC)
destinations: 10.244.0.0/164.3 Resumen de ACL
| Regla | Status | Justificación |
|---|---|---|
| Inbound UDP 123 (NTP) | BLOCKED | Fintrixs NO opera servidor NTP propio (cumple 10.6.2) |
| Outbound UDP 123 (NTP) | ALLOWED | Permite sync a NTP externos autoritativos |
| Restricción de upstream a pool específico | A nivel /etc/systemd/timesyncd.conf | DOKS nodes sólo configurados con NTP=time.digitalocean.com pool.ntp.org |
5. Collector droplet — chrony (Stratum 2 detalle)

5.1 /etc/chrony/chrony.conf
bash
$ ssh root@fintrix-production-collector cat /etc/chrony/chrony.conf
# /etc/chrony/chrony.conf — Fintrixs Production Collector
# Stratum 2 NTP relay for compliance droplets
# Upstream Stratum 1 servers (4-way redundancy)
server time.nist.gov iburst prefer
server time.google.com iburst
server pool.ntp.digitalocean.com iburst
pool pool.ntp.org iburst maxsources 4
# Allow sync to be requested from Fintrixs VPC only (defense-in-depth)
allow 10.244.0.0/16
# Step the clock if drift > 1 sec on startup
makestep 1.0 3
# Enable kernel synchronization of real-time clock
rtcsync
# Log file
logdir /var/log/chrony
log measurements statistics tracking
# Drift file
driftfile /var/lib/chrony/chrony.drift5.2 chronyc sources
bash
$ chronyc sources -v
MS Name/IP address Stratum Poll Reach LastRx Last sample
===============================================================================
^* time.nist.gov 1 10 377 123 -0.524 ms +0.002 ms +0.234 ms
^+ time.google.com 1 10 377 98 +1.241 ms +0.005 ms +0.412 ms
^+ pool.ntp.digitalocean.com 2 10 377 87 -0.331 ms +0.003 ms +0.298 ms
^- 23.155.40.38 2 10 377 65 +2.124 ms +0.012 ms +0.487 msLegenda:
^*= source actualmente sincronizando (primary)^+= combinable source^-= source not combined (drift too high)
6. ACLs en todas las plataformas

| Firewall | Inbound 123 | Outbound 123 | Restricción upstream |
|---|---|---|---|
cde-fw (89879427-...) | BLOCKED | ALLOWED | systemd config |
app-fw (8e8d554f-...) | BLOCKED | ALLOWED | systemd config |
system-fw (b91c6a13-...) | BLOCKED | ALLOWED | systemd config |
collector-fw (20e018a9-...) | ALLOWED desde VPC 10.244.0.0/16 | ALLOWED | chrony.conf |
cdd-fw (62625187-...) | BLOCKED | ALLOWED | chrony.conf |
vapt-fw (854be23d-...) | BLOCKED | ALLOWED | W32Time config |
dmz-fw (a9d45981-...) | BLOCKED | ALLOWED | systemd config |
staging-app-fw (46e4f84a-...) | BLOCKED | ALLOWED | systemd config |
Política PCI 10.6.2: ningún sistema operacional Fintrixs sirve NTP a otros que no sean los compliance droplets (collector permite ingress sólo desde VPC privada).
7. Audit de cambios en configuración temporal (PCI 10.6.3)

7.1 Wazuh syscheck — archivos monitoreados
xml
<directories check_all="yes" realtime="yes">/etc/chrony</directories>
<directories check_all="yes" realtime="yes">/etc/systemd/timesyncd.conf</directories>
<directories check_all="yes" realtime="yes">/etc/ntp.conf</directories>
<directories check_all="yes" realtime="yes">/etc/localtime</directories>7.2 auditd rules (collector + cdd + vapt droplets)
bash
# /etc/audit/rules.d/pci-time-config.rules
-w /etc/chrony/chrony.conf -p wa -k time-config-change
-w /etc/systemd/timesyncd.conf -p wa -k time-config-change
-w /etc/localtime -p wa -k time-config-change
-a always,exit -F arch=b64 -S settimeofday -k time-set
-a always,exit -F arch=b64 -S clock_settime -k time-set
-a always,exit -F arch=b64 -S adjtimex -k time-adjust7.3 Sample audit alert (Wazuh)
json
{
"rule": { "id": 553, "level": 10, "description": "File integrity changed: time config" },
"agent": { "name": "fintrix-production-collector" },
"data": {
"syscheck": {
"path": "/etc/chrony/chrony.conf",
"event": "modified",
"before_md5": "ad8f9c4f2b...",
"after_md5": "9c4f2b78ae..."
}
},
"@timestamp": "2026-05-15T14:32:21.118Z"
}7.4 Application-level audit
Cualquier cambio de configuración NTP via API/automation emite CONFIG_CHANGE evento a iam_core.pci_audit_events:
sql
SELECT * FROM iam_core.pci_audit_events
WHERE event_type = 'audit.config.change'
AND extra->>'target' LIKE '%chrony%' OR extra->>'target' LIKE '%timesync%'
ORDER BY timestamp DESC;8. Cómo el QSA verifica cada entregable
| Solicitado por QSA | Dónde se prueba |
|---|---|
| Inventario NTP | §2 (4 externas + 14 internas) |
| Sync NTP central ↔ fuente externa | §3 (cde-pool-node-01) + §5 (collector chrony) |
| ACL de sistemas NTP | §4 (cde-fw) + §6 (tabla todos firewalls) |
| Cambios temporales registrados | §7 (Wazuh syscheck + auditd + pci_audit_events) |
| Sample solo recibe de NTP central | §3.3 timedatectl timesync-status Stratum 2 |
| cde-pool-node-01 (highlight QSA) | §3 screenshots |
| cde-fw (highlight QSA) | §4 screenshots |
9. Vínculo con otros controles
- POL-010 — Logging Monitoring
- Q67 — Audit log policy
- Q70 — Syslog protection (FIM monitorea time configs)
- PCI DSS v4.0 Req 10.6.1 + 10.6.2 + 10.6.3
