DIEGO CECATO / NOTE DAL CAMPO

Il container è certificato. Il kernel no: dove si rompe davvero la compliance FIPS

diego cecato//
Il container è certificato. Il kernel no: dove si rompe davvero la compliance FIPS — cover Diego Cecato

Un container può essere costruito correttamente, usare pacchetti certificati e fallire comunque appena incontra il kernel sbagliato. È quello che Canonical ha raccontato il 28 settembre 2026 a proposito di un’incompatibilità emersa durante una migrazione FedRAMP: immagini Ubuntu Pro 22.04 FIPS che funzionavano su un kernel Ubuntu FIPS smettevano di funzionare su kernel Linux standard, come quelli che si incontrano in ambienti Kubernetes gestiti.

La causa tecnica è piccola abbastanza da sembrare quasi banale: libgcrypt20-fips dipendeva da GRND_RESEED_ONLY, un flag specifico dei kernel Ubuntu FIPS che non esiste nel kernel Linux mainline. Quando la libreria invocava getrandom() con quel flag, il kernel sottostante restituiva un errore. Il container, perfettamente coerente con il proprio ambiente di origine, falliva.

Il punto interessante però non è il flag. È l’assunzione che quel flag rende visibile: la compliance non è una proprietà che si può incollare a un singolo artefatto e poi trasportare indisturbata attraverso l’infrastruttura. È una proprietà del sistema e, soprattutto, delle relazioni tra i suoi componenti.

Il problema era nello spazio tra due componenti corretti

Secondo la ricostruzione tecnica pubblicata da Canonical, il cliente stava usando immagini Ubuntu Pro 22.04 FIPS in una migrazione soggetta a requisiti FedRAMP. Il container non era stato assemblato male e il problema non dipendeva da una configurazione applicativa sbagliata. La stessa immagine funzionava su un kernel Jammy FIPS.

Il guasto compariva quando il container veniva eseguito sopra un kernel che non implementava GRND_RESEED_ONLY. In altre parole, i due lati dell’interfaccia avevano aspettative diverse: il package dava per disponibile una capacità che il kernel non prometteva.

Questa distinzione è importante anche perché i container non portano con sé un kernel indipendente: condividono quello dell’host. La stessa documentazione Ubuntu dedicata a FIPS nei container ricorda che il kernel validato vive sull’host e che i moduli nello spazio utente operano dentro quel contesto. L’immagine può quindi essere riproducibile byte per byte, mentre il comportamento effettivo cambia per una dipendenza che sta fuori dall’immagine.

“È nel container” non significa “è isolato”

Abbiamo trasformato il container in un’unità di distribuzione molto comoda. Da qui nasce facilmente una scorciatoia mentale: se l’applicazione e le sue librerie sono dentro l’immagine, allora l’ambiente è sotto controllo. Non è così. Il container isola parecchie cose, ma continua a dipendere dal kernel, dalle syscall, dalle capability, dall’architettura della macchina, dalle policy di sicurezza e da altre proprietà del runtime.

Questa storia lo mostra con particolare chiarezza perché la dipendenza nascosta non produceva soltanto un problema funzionale. Toccava un percorso di conformità crittografica. Canonical spiega di aver dovuto correggere libgcrypt20-fips, gnutls28 e ubuntu-fips in modo compatibile con kernel standard, senza trasformare il fix in una modifica tale da imporre un nuovo lungo ciclo di certificazione.

La soluzione è stata validata prima con pacchetti forniti al cliente tramite un PPA privato e poi distribuita nei repository jammy-fips-updates e noble-fips-updates. Per chi usa immagini FIPS 22.04 o 24.04, Canonical indica quindi quei repository come canale degli aggiornamenti corretti.

La compliance è una proprietà composita

Qui conviene separare un fatto da una conclusione architetturale. Il fatto è specifico: una libreria FIPS assumeva l’esistenza di un flag del kernel Ubuntu e questa assunzione rompeva l’esecuzione su kernel mainline. La conclusione è più generale: verificare separatamente i componenti non basta a verificare il sistema che nasce componendoli.

Vale per FIPS, ma il principio è familiare a chiunque abbia dovuto tenere insieme software reale. Un’API può essere corretta e il client può essere corretto, ma basta una diversa interpretazione di un campo per rompere il processo. Un database può essere sano e un’applicazione può essere sana, ma una differenza nell’isolamento transazionale produce comunque un bug. Un container può essere certificato e il runtime può essere perfettamente legittimo, ma la combinazione dei due può non rispettare l’assunzione su cui uno dei componenti è stato costruito.

È anche il motivo per cui considero pericoloso ragionare per etichette: “certificato”, “managed”, “serverless”, “zero trust”, “enterprise”. Le etichette descrivono proprietà utili, ma non sostituiscono l’analisi delle interfacce. Un sistema non eredita automaticamente tutte le garanzie dei suoi pezzi.

Il vero inventario non è dei componenti, ma delle assunzioni

Quando si progetta un ambiente regolamentato, l’inventario classico dice quali immagini, librerie, versioni e servizi stiamo usando. Serve, ma è incompleto. A fianco dovrebbe esserci un inventario meno comodo: quali proprietà di un layer vengono date per scontate dal layer sopra?

  • Quali syscall o flag del kernel sono richiesti dalle librerie?
  • Quali garanzie crittografiche dipendono dall’host e quali stanno davvero nello user space?
  • Quali differenze introduce il passaggio da nodi controllati a servizi managed?
  • Quali aggiornamenti possono cambiare un confine che oggi consideriamo stabile?
  • Quali test verificano la composizione reale, non soltanto i singoli artefatti?

È meno elegante di una checklist con cinque spunte verdi, ma è molto più vicino a come si rompono davvero i sistemi.

Testare la matrice, non il caso felice

Da questo episodio ricaverei una regola operativa semplice: se una garanzia deve sopravvivere al cambio di infrastruttura, va testata nella matrice delle infrastrutture realmente supportate. Non basta validare l’immagine su un host noto e assumere che Kubernetes gestito sia soltanto un altro posto in cui avviarla. È la stessa disciplina che uso quando parlo di ottimizzare le risorse partendo dalla misura e dall’isolamento del problema: prima si rende osservabile il confine che può rompersi, poi si automatizza.

Per un workload di questo tipo la matrice dovrebbe almeno distinguere release dell’immagine, famiglia del kernel host, runtime e servizio managed. Non perché ogni combinazione debba diventare un progetto infinito, ma perché le combinazioni dichiarate come supportate devono avere un test che eserciti proprio i confini rilevanti: inizializzazione crittografica, accesso alle syscall richieste e comportamento in FIPS mode.

Il test di integrazione, in questo caso, non è un livello di qualità aggiuntivo. È il luogo in cui la proprietà che ci interessa diventa osservabile.

Il bug più costoso spesso è un’assunzione invisibile

Canonical ha corretto un problema concreto. La lezione che resta è più utile del singolo fix: nei sistemi complessi, i guasti peggiori non sono necessariamente dentro un componente. Spesso sono nello spazio tra due componenti che, presi singolarmente, sembrano perfettamente corretti.

La compliance rende questo fenomeno più evidente perché obbliga a dare un nome preciso alle garanzie. Ma la stessa logica vale nell’architettura software quotidiana. Se una proprietà importante dipende da più layer, allora va progettata, testata e osservata come proprietà cross-layer. Altrimenti abbiamo soltanto una collezione di pezzi “a posto” e la speranza che, messi insieme, continuino a esserlo.

Domande frequenti

Perché un container FIPS può fallire su un kernel diverso?

Perché il container condivide il kernel dell’host. Se una libreria nel container dipende da una syscall, da un flag o da un comportamento presente solo in alcuni kernel, l’immagine può essere corretta ma la combinazione con l’host può comunque fallire.

Che ruolo aveva GRND_RESEED_ONLY nel problema descritto da Canonical?

libgcrypt20-fips dipendeva da GRND_RESEED_ONLY, un flag disponibile nei kernel Ubuntu FIPS ma assente nei kernel Linux mainline. Su questi ultimi la chiamata getrandom() con quel flag falliva.

La certificazione del container basta a garantire la compliance del sistema?

No. La compliance dipende anche dall’interazione tra container, kernel host, runtime e pacchetti crittografici. Le garanzie vanno quindi verificate sulla composizione reale dei layer, non solo sui singoli componenti.

Come si riduce il rischio di incompatibilità simili?

Occorre testare le combinazioni di immagine, kernel, runtime e piattaforma realmente dichiarate come supportate, esercitando in particolare i confini che influenzano le proprietà crittografiche e di compliance.