IT-Admin.tech

Proteggere i runner CI/CD: isolamento delle credenziali, pulizia sicura del workspace e protezione della catena di build

Architekturdiagramm einer CI/CD-Pipeline mit Ephemeral-VM-Runnern, OIDC-Tokenflow, HSM-basiertem Signierdienst und...
Diagramm zeigt Trennung: Ephemeral Runner, internes Mirror, Artefakt-Repository und HSM/Signierdienst — so minimieren Sie Blast Radius bei kompromittierten Builds.

Proteggere i runner CI/CD non è un espediente di sicurezza, ma un compito operativo sostenibile: i runner prelevano codice sorgente, costruiscono artefatti e spesso hanno accesso a credenziali, cache e alla rete interna. Per amministratori e operatori è cruciale ridurre la superficie di attacco in modo misurabile e disporre di percorsi chiari per verifiche e rollback. Questa guida fornisce misure concrete, passaggi di verifica e troubleshooting per l’isolamento delle credenziali, un robusto cleanup del workspace e la protezione della catena di build.

Perché i runner sono un vettore d’attacco critico

I runner sono ambienti di esecuzione per job CI/CD (build, test, packaging). Un runner compromesso può:

  • esfiltrare secret (token, chiavi SSH, credenziali cloud).
  • alterare artefatti o firmarli in modo manipolato.
  • eseguire avvelenamento della cache (cache poisoning) e influenzare così le build successive.
  • permettere pivoting nella rete interna.

Distinzione importante: trusted-builds (ad es. branch protetti o release) versus untrusted-builds (fork, PR esterni, contributi pubblici). Per gli untrusted-build vale l’assunzione operativa: il job è potenzialmente maligno.

Principi fondamentali: privilegi minimi, isolamento, tracciabilità

Attuate l’indurimento lungo tre obiettivi misurabili:

  • Obiettivo di isolamento: nessun job deve poter vedere lo stato di un altro job.
  • Obiettivo credenziali: i job ricevono solo le credenziali strettamente necessarie, preferibilmente a breve durata.
  • Obiettivo integrità: origine e immutabilità di dipendenze e artefatti devono essere tracciabili.

Questi obiettivi possono essere operacionalizzati, testati e sottoposti ad audit.

Isolamento delle credenziali: implementazione, motivi e insidie tipiche

Isolamento delle credenziali significa: niente token statici e universali. Segmentate le identità per fase di pipeline (Build, Package, Release, Deploy) e per contesto. Utilizzate token a breve durata (TTL in minuti/ore) tramite OIDC, STS (Security Token Service) o lease di HashiCorp Vault. Le credenziali a breve durata limitano il blast radius in caso di compromissione e semplificano il revocation.

Opzioni tecniche e loro impiego

OIDC (OpenID Connect) è un protocollo per l’emissione di token a breve durata; collega i sistemi CI con Cloud-IAM o Vault senza secret persistenti. KMS/HSM (Key Management Service / Hardware Security Module) conserva le chiavi private al di fuori dei runner. Vault offre secret dinamici (es. credenziali di database su base lease). Ogni opzione impone requisiti operativi: OIDC richiede token-claim affidabili, Vault necessita di alta disponibilità e policy di accesso ben definite.

Esempio: Vault-Policy per il push di pacchetti

Hcl
# Vault policy (HCL) - erlaubt Token zum Schreiben in ein internes Artefakt-Repo
path "secret/data/ci/artifacts/*" {
  capabilities = ["create", "update", "read"]
}

Perché funziona: Vault emette token a durata limitata e la policy restringe i percorsi. Quando fallisce: se i runner persistono il token di Vault (ad es. nella cache) o se le policy sono definite troppo ampie.

Firma limitata da policy tramite servizio di firma

Le chiavi private di firma non devono risiedere su runner ordinari. Un servizio di firma (un servizio interno che utilizza KMS/HSM per firmare) riceve gli hash degli artefatti, verifica le policy (ad es. che la build provenga da un branch protetto) e poi firma. L’operazione di firma richiede log di audit separati e autenticazione rigorosa.

Proteggere i runner CI/CD: isolamento a livello infrastrutturale

Scegliere l’isolamento in base a rischio ed economicità:

  • Host-Runner: Veloce, ma solo per job fully-trusted.
  • Container-Runner: Buone pRESTazioni, ma solo con rootless/politiche di mount stringenti.
  • Ephemeral VM/Instance-Runner: Isolamento massimo; per job VM nuova o snapshot. Costi più alti, sicurezza massima.

I runner effimeri sono particolarmente raccomandati per build untrusted: al termine l’istanza viene distrutta, impedendo la persistenza.

Esempio: Kubernetes-Runner come Ephemeral-Job

Yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: runner-job-{{ .RunID }}
spec:
  template:
    spec:
      securityContext:
        runAsUser: 1000
        runAsGroup: 1000
        fsGroup: 1000
      containers:
      - name: builder
        image: registry.internal/runner-image:stable
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: ["ALL"]
      RESTartPolicy: Never
  backoffLimit: 0

Perché aiuta: Kubernetes consente Namespaces, NetworkPolicies e Pod Security Context per limitare. Attenzione: configurazioni RBAC o di volume errate possono compromettere l’isolamento.

Pulizia sicura del workspace: robusta e resistente alle manomissioni

Una pulizia difettosa permette la persistenza. I problemi nascono da handle aperti, filesystem montati, trucchi con symlink e ACL RESTrittive. Una pulizia robusta implementa più strati di protezione: workspace dedicati, normalizzazione della ownership, –one-file-system durante la cancellazione e run di verifica con audit logging.

Linux: Cleanup avanzato incluso controllo degli handle

Shell
#!/usr/bin/env bash
set -euo pipefail
JOB_DIR="$1"
RUNNER_UID=1001
RUNNER_GID=1001

# 1) Terminare i processi che operano in JOB_DIR
fuser -k -TERM -m "$JOB_DIR" || true
sleep 1
fuser -k -KILL -m "$JOB_DIR" || true

# 2) Normalizzare ownership e permessi
chown -R "${RUNNER_UID}:${RUNNER_GID}" "$JOB_DIR" 2>/dev/null || true
chmod -R u+rwX,go-rwx "$JOB_DIR" 2>/dev/null || true

# 3) Controllare mountpoint nel jobdir
mountpoints=$(findmnt -n -o TARGET --target "$JOB_DIR" || true)
if [ -n "$mountpoints" ]; then
  echo "Found mounts: $mountpoints" >&2
  # Option: detach mounts safely or warn and abort
fi

# 4) Eseguire la cancellazione in modo sicuro
rm -rf --one-file-system "$JOB_DIR"

Perché fuser è necessario: handle di file aperti impediscono la cancellazione; i processi devono essere terminati correttamente. Lo script può fallire se un job ha avviato processi di sistema che lo script non può terminare — per questo logging e livelli di allerta sono importanti.

Windows: Handle, piano di reboot e interazione con antivirus

Su Windows i lock da parte di servizi e AV sono comuni. Integrare il cleanup con controlli degli handle (Sysinternals Handle/Process Explorer), retry e un percorso di reboot pianificato nel caso la cancellazione non sia possibile. I soli retry non bastano sempre per lock ostinati — documentate una procedura di rollback.

Sicurezza della catena di build: sorgenti pacchetti, cache e firma

Proteggete la catena di build isolando le sorgenti dei pacchetti, utilizzando proxy con allow-list, cache controllate e policy sugli artefatti immutabili.

Mirror interni e RESTrizione dell’egress

Oltre alle allow-list per gli endpoint dei pacchetti, i runner dovrebbero avere egress limitato alle destinazioni definite: VCS, mirror, repository artefatti, KMS/servizio di firma. Le Egress-ACL riducono le possibilità di esfiltrazione/connessioni verso infrastrutture di command-and-control. Testate le modifiche inizialmente in monitor-mode (solo logging) prima di bloccare.

Rafforzamento del repository artefatti

Impostate write-policy (non-overwrite), retention-policy e require-signed-artifact-flag quando il vostro repository le supporta. I log di audit devono mostrare chi e quando ha pubblicato un artefatto. Esempio di regola: „Le release possono essere pubblicate solo dopo la firma da parte del servizio di firma“.

Strategie di cache contro il poisoning

Separare le cache per zone di fiducia e per progetto. Evitare cache condivise scrivibili per job non attendibili. Utilizzare invalidazione TTL e hash di cache registrati per rilevare il poisoning.

Indurimento di rete e host: misure concrete

Trattate i Runner come componenti di infrastruttura critica:

  • propri segmenti di rete o VLAN
  • Egress-ACLs definite
  • firewall host e processo di patching
  • monitoraggio e log centralizzati

Esempio: regola iptables semplice per l'egress (VM-Runner)

Shell
# Erlaube nur DNS, HTTP(S) zu mirror.example und signing.example
iptables -A OUTPUT -m owner --uid-owner runner -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT -m owner --uid-owner runner -p tcp -d mirror.example --dport 443 -j ACCEPT
iptables -A OUTPUT -m owner --uid-owner runner -p tcp -d signing.example --dport 443 -j ACCEPT
iptables -A OUTPUT -m owner --uid-owner runner -j DROP

Perché aiuta: anche se un job tenta di stabilire comunicazioni dannose, l'egress rimane limitato. Attenzione: DNS-over-HTTPS e altri percorsi di elusione possono aggirare questo approccio — testare e monitorare.

Testing, audit e validazione

Garantire le misure con test automatizzati e audit:

  • Job di audit regolari che provano a eseguire, da un Runner, azioni non permesse (solo in una rete di test isolata!).
  • Audit post-job: verificare la persistenza del workspace, handle aperti, processi attivi.
  • Analisi dei log: ricerca di esfiltrazione di token o connessioni di egress anomale.

Esempio di script di test: Post-Cleanup-Validation

Shell
#!/usr/bin/env bash
# Prüft, ob ein Job-Verzeichnis nach Cleanup noch existiert
JOB_DIR="$1"
if [ -e "$JOB_DIR" ]; then
  echo "CLEANUP FAILED: $JOB_DIR still exists" >&2
  ls -la "$JOB_DIR" >&2
  exit 2
fi
# Prüfe auf aktive Prozesse des Runner-User
if pgrep -u runner >/dev/null; then
  echo "ACTIVE PROCESSES FOUND" >&2
  ps -u runner -o pid,cmd
  exit 3
fi
exit 0

Insidie tipiche e risoluzione dei problemi

1) Segreti inseriti per errore nel log di build

Causa: stampe di debug o mancato mascheramento. Misure: abilitare il mascheramento dei log CI, non esporre variabili sensibili in chiaro. Verificare automaticamente i log alla ricerca di pattern (API key, bearer token) con un job di scanner.

2) Uso improprio di container privilegiati

Causa: container privilegiati o inoltro del socket Docker. Misure: build senza privilegi di root (rootless), evitare mount del socket dell'host, usare Buildkit/remote daemon. Test: il job prova a creare nuovi container sull'host (solo in ambiente di test!).

3) Chiavi di firma sui Runner

Causa: praticità invece di sicurezza — i team posizionano le chiavi localmente. Misure: centralizzare i servizi di firma, conservare le chiavi solo in HSM/KMS. Contromisura: rotazione immediata e invalidamento di tutte le chiavi potenzialmente compromesse.

Strategia di rollback e di emergenza

Introdurre le modifiche in modo graduale:

  1. Modalità monitor: solo logging, nessun blocco.
  2. Chiusura graduale delle aree di Egress/policy.
  3. Operare in parallelo pool di Runner vecchi e nuovi; switch tramite feature-flag/route.
  4. Token Break-Glass per le emergenze con breve durata e audit.

Importante: documenti i passaggi di rollback e li testi regolarmente in una esecuzione di prova isolata.

Checklist pratica: implementazione in 90–180 minuti

  • Inventariare i token attivi e verificare i permessi per ogni fase della pipeline.
  • Migrare i job non attendibili su pool di runner separati o Ephemeral-VMs.
  • Estendere gli script di cleanup: process-kill, chown, chmod, –one-file-system, Post‑Validation.
  • Auditare il processo di firma e pianificare la movimentazione delle chiavi in HSM/KMS.
  • Creare Egress-ACLs in Monitor-Mode e osservare il traffico.
  • Audit-Job: tentativi di eseguire azioni non autorizzate dai runner (in isolamento).

Conclusione

Mettere in sicurezza i runner CI/CD significa coniugare praticabilità con sicurezza misurabile. Date priorità alla separazione delle credenziali per fase della pipeline (con token a breve vita), al cleanup garantito dei workspace (o agli Ephemeral-Runner) e alla firma tramite un servizio di firma o HSM/KMS. Completa il tutto con RESTrizioni di egress, monitoring e audit test regolari. Con un’introduzione graduale, fasi in Monitor-Mode e percorsi di rollback testati, la sicurezza RESTa gestibile e operativamente affidabile.

FAQ

Qual è l’errore principale nel mettere in sicurezza i runner CI/CD?

L’errore più comune è l’uso di un token permanente e troppo permissivo per tutte le fasi della pipeline. Un job compromesso ottiene così troppo potere. È meglio separare per fase (Build, Package, Release, Deploy) e usare token a breve durata, legati al contesto.

Un container da solo è sufficiente come isolamento per build non attendibili?

Un container da solo è sufficiente solo se privilegi, mount e rete sono strettamente limitati. Particolarmente pericolosi sono i container privilegiati o il passthrough del Docker-Socket. Per build non attendibili le Ephemeral-VMs o job Kubernetes fortemente isolati sono più robusti.

Come mi assicuro che il cleanup del workspace funzioni davvero?

Utilizzi workspace di job dedicati, normalizzi proprietà e permessi prima della cancellazione e cancelli con –one-file-system. In caso di Windows interrompa gli handle dei processi dell’utente del job e lavori con ritentativi. Audit post‑job automatizzati verificano se RESTano residui.

Perché la chiave privata di firma non deve risiedere sul runner?

Se la chiave risiede su runner standard, un job compromesso può firmare artefatti manipolati. È preferibile la firma tramite HSM/KMS o un servizio di firma separato che firmi solo in contesti concreti verificati dalle policy.

Come gestire la perdita di pRESTazioni dovuta a un isolamento più marcato?

Separi le cache per zone di fiducia e per progetto, utilizzi mirror interni e immagini di runner warm-started (Snapshots). In questo modo mantiene le pRESTazioni senza introdurre rischi di cache‑poisoning.

Quali verifiche dovrebbero essere incluse in un audit-job per i runner?

Gli audit-job dovrebbero tentare di stabilire connessioni di egress non autorizzate, ottenere accesso in scrittura ad altri workspace, testare l’accesso alle API di firma senza claim validi e verificare che il post-cleanup non lasci file o processi. Eseguire questi test solo in ambienti isolati.

Mettere in sicurezza i runner CI/CD: operatività, monitoring e integrazione

Le misure tecniche sono efficaci solo quanto il loro esercizio. Pianificate monitoring, metriche e integrazioni già all’introduzione dell’indurimento dei Runner, in modo che la sicurezza rimanga ripetibile e misurabile.

Metriche e alert importanti:

  • Cleanup-Failure-Rate: percentuale di job in cui la validazione post-job è fallita. Definire una soglia e generare un allarme prima che i deficit di pulizia diventino persistenti.
  • Vault-Lease‑Errors e OIDC-Token‑Failures: indicano problemi con credenziali a breve durata o claim errati.
  • Connessioni Egress insolite per pool di Runner: incrementi improvvisi indicano esfiltrazione o tentativi di elusione.
  • Richieste di firma per ora e errori di firma: deviazioni possono indicare pipeline compromesse o errori di policy.

Indicazioni per l’integrazione:

  • IAM/IdP: Collegare il CI come client OAuth/OIDC agli Identity‑Provider esistenti (es. AD, Okta). In questo modo audit e ciclo di vita degli utenti restano gestibili in modo centrale.
  • Secrets-Backends: utilizzare Vault/KMS in modo dinamico; automatizzare il rinnovo dei lease e la rotazione. Documentare le rotazioni di emergenza e testare il percorso di revoca delle chiavi.
  • Repository di artefatti: integrare le signing‑policy con attestazioni (metadati di build, SBOM). Questo rende verificabile la provenienza e facilita le analisi di incidente.

Runbook e pratiche di rollback:

  • Redigere un runbook conciso: passi per isolare un pool di Runner, rotazione delle chiavi, interruttore di disabilitazione per il servizio di firma e rollback su Runner in warm‑standby.
  • Eseguire test di chaos regolari in una zona di test (cleanup-fail, blocco Egress) e valutare i processi operativi rispetto a SLA concreti.

Conclusione: esercizio e integrazione non sono pensieri secondari. Buone metriche, rotazione automatizzata e runbook coordinati rendono la sicurezza CI/CD robusta e gestibile nella pratica quotidiana.

Per questo argomento sono importanti anche la Supply-Chain-Security e la protezione della catena di build. Il contributo inquadra questi aspetti in modo comprensibile e mostra su cosa concentrarsi nella pratica quotidiana.