La regola security group che ha sopravvissuto al ticket
Una porta PostgreSQL aperta temporaneamente per il debug è rimasta in produzione per sei settimane dopo la chiusura del ticket. Il database non è mai stato compromesso, e questo l'ha quasi peggiorato.

Il ticket diceva “accesso temporaneo a RDS di staging per test di migrazione.” Qualcuno
ha aggiunto una regola inbound sul security group del database: TCP 5432 da un IP ufficio
con /32. La migrazione è finita giovedì. La regola è rimasta. Lunedì qualcuno l’ha
allargata a 0.0.0.0/0 mentre debuggava un problema VPN, ha testato la connettività, si è
distratto con un deploy e non l’ha mai ristretta.
L’abbiamo trovata sei settimane dopo durante un audit di routine, non perché qualcosa fosse andato storto.
Come è rimasta aperta
Tre cose dovevano fallire insieme, e tutte e tre sono fallite.
La prima è stata il processo. Il ticket aveva una checkbox “rimuovi accesso temporaneo” e nessuno l’ha spuntata, perché il lavoro era andato avanti e l’accesso sembrava innocuo. Era staging, i dati erano anonimizzati, il rischio sembrava astratto.
La seconda è che la regola è stata aggiunta nella console AWS, non in Terraform. I successivi
tre terraform plan non hanno mostrato drift su quel security group perché Terraform non
aveva mai posseduto quella regola. Il plan era pulito. I plan puliti rassicurano e a volte
mentono.
La terza è stato il monitoraggio. Avevamo GuardDuty, Security Hub, una scansione settimanale. Nessuno era configurato per avvisare su “nuova regola ingress su security group RDS.” Avrebbero rilevato lo sfruttamento. Non guardavano la finestra aperta.
Com’era fatta la regola
Più o meno così, accanto alle regole legittime:
Type Protocol Port Source
PostgreSQL TCP 5432 0.0.0.0/0 ← quella che nessuno possedeva
PostgreSQL TCP 5432 sg-app-prod ← quella vera
PostgreSQL TCP 5432 sg-bastion ← quella vera
Il database aveva ancora Publicly accessible: No. La subnet era privata. Ma il security
group è il cancello, e l’avevamo lasciato sbloccato verso internet perché 0.0.0.0/0 non
si cura del tuo design di subnet.
Cosa abbiamo cambiato
Quel giorno: rimossa la regola, ruotata la password del database, esportati gli eventi CloudTrail delle sei settimane (niente di sospetto, piccole misericordie).
Quella settimana:
- Importato il security group in Terraform così la prossima modifica manuale appare come drift.
- Aggiunta una regola EventBridge su
AuthorizeSecurityGroupIngressper ogni SG collegato a RDS. Messaggio Slack, non pager. Volevamo segnale senza gridare al lupo a ogni cambio legittimo del bastion. - Documentato l’accesso via bastion come unico percorso approvato per connessioni umane al database.
L’abitudine rimasta:
lifecycle {
prevent_destroy = true
}
sull’istanza RDS, e un check CI che fallisce se una risorsa aws_security_group_rule usa
cidr_blocks = ["0.0.0.0/0"] sulla porta 5432. Grezzo. Intercetta l’errore che abbiamo
davvero fatto.
La parte a cui continuo a pensare
Nessuno è stato negligente nel modo che calza in una narrativa da cattivo. La gente andava veloce, la regola funzionava, l’app era a posto, la dashboard era verde. Il modo di fallire è stato noioso: modifica manuale, ticket chiuso, plan Terraform pulito, nessun incidente che scateni una revisione.
I postmortem di solito iniziano quando qualcosa si rompe. Questo è iniziato perché qualcosa non si è rotto, ed è esattamente per questo che l’esposizione è durata abbastanza da contare.
Se la tua unica prova che la sicurezza funziona è che nessuno ti ha ancora attaccato, stai misurando fortuna, non postura.