Su AZ-400 l’Infrastructure as Code non è un esercizio di sintassi: è una strategia. La domanda non è “come dichiaro uno storage account”, ma “dato questo requisito di governance, velocità e conformità, quale combinazione di linguaggio, pipeline ed enforcement regge”. Diamo per acquisiti i meccanismi base e concentriamoci sulle decisioni di design e sui trade-off.

La strategia viene prima del linguaggio

Una strategia IaC si regge su tre pilastri, e il linguaggio è l’ultimo dei tre.

Source control come unica fonte di verità. Se una risorsa esiste in Azure ma non nel repository, non è infrastruttura: è debito. Il repository IaC eredita quindi il rigore del codice applicativo — branch policy, pull request obbligatorie, revisori designati sui percorsi sensibili. Anche la granularità è una scelta: repository separati per piattaforma e workload allineano i confini del codice a quelli di ownership, al costo di versionare l’interfaccia fra i due.

Autenticazione delle pipeline. Il pattern corrente è OpenID Connect con workload identity federation: la pipeline non conserva credenziali a lunga vita, ma presenta un token emesso dal provider OIDC che Azure scambia per un access token a breve durata. Su GitHub Actions significa configurare federated credential sull’applicazione Microsoft Entra ID, con almeno una condizione che impedisca a repository non attendibili di richiedere token per le tue risorse. Il trade-off rispetto a un service principal con secret è a senso unico: niente rotazione, esposizione ridotta in caso di compromissione.

Test e validazione automatizzati. Qui va sfatata una confusione ricorrente. L’ARM template test toolkit (arm-ttk) verifica se un template segue le pratiche raccomandate — parametri sicuri, location non hardcoded, API version recenti — non se il deployment andrà a buon fine; sono raccomandazioni, non requisiti. Ed è disponibile solo per template ARM: per i file Bicep l’equivalente è il linter Bicep. La validazione semantica passa invece dall’operazione what-if, che confronta il template con lo stato corrente e mostra risorse e proprietà che verranno create, aggiornate o eliminate. Gate tipico: linter e test statici sulla pull request, what-if come step di approvazione prima della produzione.

ARM template o Bicep: quando la scelta è davvero una scelta

Bicep è una astrazione trasparente sopra il template ARM JSON: la CLI lo transpila in JSON al deployment, e resource type, API version e proprietà valide in un template ARM restano valide in Bicep. Da qui il criterio decisionale: la scelta non è fra due motori, ma fra due esperienze di authoring sopra lo stesso motore.

I vantaggi che pesano in fase di design sono la modularità (moduli riusabili al posto dei template linked e nested), la gestione automatica delle dipendenze tramite nomi simbolici, che rende superfluo gran parte di dependsOn, e una struttura del file più libera, con parametri, variabili e output dichiarabili ovunque anziché confinati nella rispettiva sezione. Bicep supporta inoltre immediatamente tutte le versioni preview e GA dei servizi Azure: appena un resource provider introduce nuovi tipi e API version puoi usarli, senza attendere aggiornamenti del tooling.

Il punto che l’esame ama è lo stato: né ARM né Bicep mantengono un file di stato, perché Azure lo conserva lato servizio. Questo elimina un’intera classe di problemi operativi — lock, storage remoto, drift fra stato e realtà — che chi arriva da altri strumenti tende a proiettare su Bicep. Per migrare l’esistente c’è decompile: buon punto di partenza, non output finale da mettere in produzione senza revisione.

Deployment stack aggiunge un livello che né i template né i moduli danno da soli: gestisce un insieme di risorse come unità coesa, con ciclo di vita esplicito. Due parametri concentrano la decisione. actionOnUnmanage (detachAll, deleteResources, deleteAll) stabilisce cosa succede a una risorsa rimossa dal template — per default viene scollegata, non eliminata. denySettingsMode (none, denyDelete, denyWriteAndDelete) crea una deny assignment che protegge le risorse gestite da modifiche fuori pipeline. Due limiti: le deny settings valgono sulle operazioni control plane e non sul data plane (un secret dentro un key vault gestito non è coperto) e riguardano le risorse dichiarate esplicitamente, non quelle create implicitamente da un servizio. Gli stack esistono a scope resource group, subscription o management group, e vanno collocati allo scope padre rispetto alle risorse protette, così che meno principal possano alterarne la deny assignment.

Configuration drift: Automation State Configuration o Machine Configuration

Il template porta la macchina all’esistenza; la sua configurazione interna è un problema diverso, e qui il blueprint ha una risposta ormai univoca.

Azure Automation State Configuration sarà ritirato il 30 settembre 2027, con transizione indicata verso Azure Machine Configuration; la variante Linux è già stata ritirata nel 2023. In uno scenario che chieda una scelta a lungo termine questo è dirimente: ogni nuovo design punta su Machine Configuration, e l’uso legittimo di State Configuration è governare il parco esistente durante la migrazione.

Azure Machine Configuration, funzionalità di Azure Policy, verifica o configura le impostazioni del sistema operativo come codice, sia su macchine Azure sia su macchine ibride Arc-enabled — ed è questo il motivo architetturale principale per sceglierlo quando il parco macchine non è solo Azure. Le assegnazioni possono essere orchestrate su scala da Azure Policy oppure create manualmente per macchina. La decisione di design sta nella modalità di enforcement: Audit si limita a riportare lo stato, Apply and Monitor applica la configurazione e poi osserva le derive, Apply and Autocorrect riporta attivamente la macchina in conformità quando il drift si verifica. Il trade-off è il consueto: l’autocorrezione elimina il drift ma può sovrascrivere interventi manuali legittimi, quindi conviene partire in Audit, misurare il non conforme e promuovere ad apply in modo controllato. Vincoli da ricordare: il limite di 50 guest assignment per macchina e il supporto ai VMSS Flex ma non ai VMSS Uniform.

Self-service governato con Azure Deployment Environments

Il requisito ricorrente è: “gli sviluppatori devono creare ambienti on-demand senza che il team di piattaforma sia un collo di bottiglia, e senza accesso alle subscription”. Il modello si articola allora su dev center (contenitore di progetti con impostazioni comuni), project (un team o una funzione di business, associato a un solo dev center), catalog (template curati, ospitati su un repository GitHub o di Azure DevOps Services), environment definition (template IaC più un file di manifesto) e environment type, definiti sul dev center e poi ristretti per progetto, con subscription di destinazione configurabile per progetto e per tipo.

Il meccanismo che rende questa una risposta di design è l’identità: il deployment è eseguito da una managed identity del dev center o del progetto, per conto dello sviluppatore. L’identità va autorizzata sui cataloghi e riceve accesso Contributor e User Access Administrator sulle subscription di destinazione; lo sviluppatore non ha accesso diretto a quelle subscription. È elevazione di privilegio incapsulata: il permesso vive nell’identità della piattaforma, non nell’utente. Ogni ambiente nasce per default in un proprio resource group, su cui i membri del progetto ricevono accesso Contributor. Lato RBAC i ruoli rilevanti includono DevCenter Project Admin (gestisce environment type e catalog del progetto) e Deployment Environments User (crea ambienti): senza quest’ultimo non c’è self-service.

Una nota di realtà: la documentazione dichiara Azure Deployment Environments in maintenance mode, senza nuove funzionalità previste, pur restando disponibili le capacità esistenti. Resta materia d’esame, ma in una valutazione architetturale reale è un fattore da pesare.

Come cade all’esame

  • “Serve validare i template nella pipeline; il team usa Bicep”linter Bicep, non arm-ttk, che è disponibile solo per template ARM.
  • “Prima del deploy in produzione bisogna vedere cosa cambierà sulle risorse esistenti” → operazione what-if come gate di approvazione, non un semplice deploy di prova.
  • “La pipeline non deve conservare credenziali a lunga vita”OIDC con workload identity federation e federated credential condizionata sull’app Entra ID, non un service principal con secret in un variable group.
  • “Le risorse di un ambiente vanno gestite come un’unità e non devono essere modificabili fuori dalla pipeline”deployment stack con denySettingsMode appropriato; copre il control plane e le sole risorse esplicite. Se invece una risorsa rimossa dal template non deve essere distrutta, actionOnUnmanage resta a detachAll, che è il predefinito.
  • “Impostazioni del sistema operativo conformi anche su server on-premises”Azure Machine Configuration con macchine Arc-enabled; State Configuration non è la scelta per un design nuovo, dato il ritiro annunciato. Se le macchine devono anche tornare conformi da sole dopo una modifica manuale, la modalità è Apply and Autocorrect.
  • “Gli sviluppatori devono creare ambienti da template approvati senza permessi sulle subscription”Azure Deployment Environments, deployment eseguito dalla managed identity del dev center o progetto, con il ruolo Deployment Environments User sugli sviluppatori.