Su AZ-400 la domanda non è “come si legge un secret da Key Vault”, ma “dato questo requisito di sicurezza, dove deve vivere il segreto, chi può leggerlo e come impedisco che finisca in un log o in un artefatto”. Le leve architetturali sono quattro: Azure Key Vault come store centrale, la workload identity federation per eliminare del tutto i segreti di autenticazione, i secure file per il materiale sensibile che è un file e non una stringa, e il design della pipeline per contenere l’esposizione. Diamo per acquisiti i meccanismi di base e concentriamoci sulle decisioni e sui trade-off.

Key Vault in pipeline: task o variable group linkato

Esistono due modi per portare un secret di Key Vault dentro Azure Pipelines, e la scelta non è cosmetica.

Il task Azure Key Vault (AzureKeyVault@2) legge i secret a runtime tramite una service connection e li espone come variabili di pipeline. Il parametro SecretsFilter accetta un elenco di nomi oppure l’asterisco: l’asterisco è comodo in demo e sbagliato in produzione, perché porta sull’agent l’intero contenuto del vault. Il design corretto è un vault per ambiente con un filtro esplicito sui soli secret che quel job usa davvero. All’identità della service connection servono i permessi Get e List sui secret, non di più: nel modello RBAC il ruolo mirato è Key Vault Secrets User, non un Contributor sul vault.

Il variable group linkato al vault mappa solo i nomi dei secret, mai i valori: la pipeline recupera i valori aggiornati dal vault a runtime. È la scelta giusta quando lo stesso insieme di segreti serve a più pipeline, perché la rotazione nel vault si propaga senza toccare le definizioni. Due limiti da conoscere per l’esame. Primo: se aggiungi o elimini secret nel vault, il variable group non si aggiorna da solo, va rieditato — la rotazione del valore è trasparente, il cambio di inventario no. Secondo: l’integrazione col variable group supporta solo i secret, non chiavi crittografiche né certificati, anche se Key Vault li gestisce.

C’è poi un vincolo di rete che decide architetture intere: i vault con modello di permessi RBAC sono supportati quando il vault è raggiungibile su endpoint pubblico, mentre i vault RBAC dietro private endpoint non lo sono, perché Azure DevOps non rientra fra i trusted services. Se il requisito impone il private endpoint, la strada documentata è il modello Vault access policy.

Autenticazione senza segreti: federation e OIDC

Il salto di qualità architetturale non è custodire meglio la credenziale, ma non averla. Con la workload identity federation la service connection Azure Resource Manager non contiene alcun client secret: l’esecuzione presenta un token firmato dall’issuer di fiducia e Microsoft Entra ID lo scambia con un access token di breve durata, sulla base di una federated credential registrata sull’identità (issuer più subject identifier).

La prima decisione è quale identità federare. Una managed identity assegnata dall’utente è preferibile quando non hai i permessi per creare service principal nel tenant, o quando il tenant di Azure DevOps è diverso da quello della sottoscrizione target; l’app registration resta l’alternativa. In entrambi i casi i permessi stanno su due piani distinti: in Azure DevOps serve il ruolo di amministratore sulla service connection, in Azure serve chi può creare la federated credential (per una managed identity, il ruolo Managed Identity Federated Credential Contributor o equivalente) e chi assegna il ruolo sulla risorsa target. È una separazione di responsabilità voluta: si può modificare la connection senza poter allargare l’accesso in Azure.

Attenzione al punto di aggiornamento più probabile in una domanda d’esame: le service connection basate sull’issuer Azure DevOps sono in deprecazione a favore dell’issuer Microsoft Entra, e la risposta corretta per una connection segnalata come deprecata è convertirla, non crearne una sostitutiva. La deprecazione riguarda le connection idonee in cloud pubblico con app single-tenant o managed identity; restano fuori perimetro le connection verso cloud non pubblici e quelle che usano applicazioni multitenant.

In GitHub Actions lo stesso principio passa da OpenID Connect. Il provider OIDC di GitHub emette un JWT per ogni run, il workflow lo richiede dichiarando il permesso id-token: write e lo scambia con il cloud provider (per Azure, tramite l’action azure/login) ottenendo una credenziale di breve durata valida per la durata del job. Il permesso non concede accesso alle risorse: autorizza solo a richiedere e usare il token. Il vero controllo di sicurezza è la claim sub, che identifica il contesto di esecuzione — repository più branch, tag, pull request o environment — e che va usata per restringere quali workflow possono assumere quale identità. Design consigliato: federated credential distinte per ambiente, con l’environment di produzione protetto, invece di una singola credential legata al repository che qualunque branch potrebbe sfruttare.

Secure file: quando il segreto è un file

Non tutto il materiale sensibile è una stringa. Certificati di firma, provisioning profile Apple, keystore Android, chiavi SSH sono file, e la libreria secure file di Azure Pipelines è il posto dove metterli. I file sono cifrati a riposo sul server, hanno un limite di 10 MB ciascuno e si consumano con il task DownloadSecureFile@1, che espone il percorso locale allo step successivo.

Il punto architetturale è che un secure file è una risorsa protetta: puoi limitarne l’uso con pipeline permissions, ruoli di sicurezza della library e approvals and checks. È questo, più della cifratura, a renderlo diverso dal commit del certificato nel repository: un gate di autorizzazione per pipeline. Design tipico: file di firma della produzione autorizzati esplicitamente alla sola pipeline di release, con approvazione, mai in open access. Nota che diventa vincolo di design: dopo il caricamento il contenuto non è modificabile, per aggiornarlo si elimina e si ricarica — la rotazione di un certificato è una procedura, non un edit.

Progettare contro la fuga nei log

Il masking non è una rete di sicurezza, è una mitigazione con limiti documentati, e l’esame li conosce.

  • Le variabili secret non vengono decifrate automaticamente in variabili d’ambiente per gli script: vanno mappate esplicitamente con il blocco env dello step. Chi si aspetta il comportamento delle variabili normali scrive pipeline che falliscono in modo silenzioso.
  • Mai passare un segreto sulla riga di comando: alcuni sistemi operativi registrano gli argomenti dei comandi. La forma corretta è la variabile d’ambiente mappata.
  • Il masking non copre le sottostringhe: se il segreto è abc123, la stringa abc non viene mascherata. Di conseguenza un segreto non deve contenere dati strutturati: dato un JSON messo in un unico secret, i valori interni non vengono mascherati. La regola di design è un secret per valore atomico, non un blob di configurazione. La stessa raccomandazione vale per i secret di GitHub Actions.
  • Impostare un segreto da script con il logging command e il flag issecret è il metodo meno sicuro: va riservato al debug, mentre la produzione usa UI, variable group o Key Vault.
  • Non basta proteggere il log: artefatti, file di configurazione generati e messaggi di errore sono canali di fuga quanto lo standard output.

Trappole tipiche d’esame

  • “Più pipeline devono usare gli stessi segreti e la rotazione nel vault deve propagarsi senza modificare le pipeline”variable group linkato a Key Vault, che mappa i nomi e legge i valori a runtime; non copiare i valori in variabili di pipeline.
  • “Dopo aver aggiunto un nuovo secret nel vault la pipeline non lo vede” → il variable group non si aggiorna automaticamente sull’inventario: va rieditato per includere il nuovo nome.
  • “Il vault deve essere raggiungibile solo via private endpoint e va linkato a un variable group” → il modello RBAC dietro private endpoint non è supportato; ripiegare su Vault access policy o su un percorso di accesso interno alla rete.
  • “Eliminare le credenziali long-lived dalla service connection verso Azure”workload identity federation con managed identity o app registration; se la connection esistente usa l’issuer Azure DevOps deprecato, convertirla, non ricrearla.
  • “Solo i workflow che deployano nell’environment di produzione devono poter accedere alla sottoscrizione” → federated credential con claim sub vincolata all’environment, più id-token: write nel workflow; non un secret di repository.
  • “Un certificato di firma va usato in build senza finire nel repository, con accesso limitato a una sola pipeline”secure file più DownloadSecureFile@1, con pipeline permissions e checks; non un file nel repo né una variabile.
  • “Un valore riservato compare nei log nonostante sia marcato come secret” → tipicamente dato strutturato in un unico secret, sottostringa, o passaggio su riga di comando; scomporre in secret atomici e mappare via env.