Test case per i modelli di ARM
Questo articolo descrive i test eseguiti con il toolkit di test del modello per i modelli di Azure Resource Manager (modelli di ARM). Fornisce esempi che superano o non superano il test e includono il nome di ogni test. Per ulteriori informazioni su come eseguire i test o su come eseguire un test specifico, vedere Parametri di test.
Usare lo schema corretto
Nome test: Lo schema DeploymentTemplate è corretto
Nel modello è necessario specificare un valore di schema valido.
L'esempio seguente ha esito negativo perché lo schema non è valido.
{
"$schema": "https://schema.management.azure.com/schemas/2019-01-01/deploymentTemplate.json#",
}
L'esempio seguente mostra un avviso perché la versione dello schema 2015-01-01
è deprecata e non viene conservata.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
}
L'esempio seguente ha esito positivo usando uno schema valido.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
}
La proprietà del modello schema
deve essere impostata su uno degli schemi seguenti:
https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#
https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#
https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#
https://schema.management.azure.com/schemas/2019-08-01/tenantDeploymentTemplate.json#
https://schema.management.azure.com/schemas/2019-08-01/managementGroupDeploymentTemplate.json
I parametri dichiarati devono essere usati
Nome test: è necessario fare riferimento ai parametri
Questo test trova i parametri che non vengono usati nel modello o i parametri che non vengono usati in un'espressione valida.
Per ridurre la confusione nel modello, eliminare tutti i parametri definiti ma non usati. L'eliminazione dei parametri inutilizzati semplifica le distribuzioni di modelli perché non è necessario fornire valori superflui.
In Bicep usare la regola Linter senza parametri inutilizzati.
L'esempio seguente ha esito negativo perché nell'espressione che fa riferimento a un parametro manca la parentesi quadra iniziale ([
).
"resources": [
{
"location": " parameters('location')]"
}
]
Nell'esempio seguente ha esito positivo perché l'espressione è valida.
"resources": [
{
"location": "[parameters('location')]"
}
]
I parametri sicuri non possono avere un valore predefinito hardcoded
Nome test: I parametri della stringa sicura non possono avere un valore predefinito
Non fornire un valore predefinito hardcoded per un parametro sicuro nel modello. Un parametro secure può avere una stringa vuota come valore predefinito o usare la funzione newGuid in un'espressione.
I tipi secureString
o secureObject
vengono usati nei parametri che contengono valori sensibili, ad esempio password. Quando un parametro usa un tipo sicuro, il valore del parametro non viene registrato né archiviato nella cronologia di distribuzione. Questa azione impedisce a un utente malintenzionato di individuare il valore sensibile.
Quando si specifica un valore predefinito, tale valore è individuabile da chiunque possa accedere al modello o alla cronologia di distribuzione.
In Bicep usare la regola Linter : impostazione predefinita del parametro sicuro.
L'esempio seguente ha esito negativo.
"parameters": {
"adminPassword": {
"defaultValue": "HardcodedPassword",
"type": "secureString"
}
}
L'esempio successivo ha esito positivo.
"parameters": {
"adminPassword": {
"type": "secureString"
}
}
L'esempio seguente ha esito positivo perché viene usata la funzione newGuid
.
"parameters": {
"secureParameter": {
"type": "secureString",
"defaultValue": "[newGuid()]"
}
}
Gli URL di ambiente non possono essere hardcoded
Nome test: DeploymentTemplate non deve contenere Uri hardcoded
Non creare codici complessi per gli URL nel modello. Usare invece la funzione environment per ottenere dinamicamente questi URL durante la distribuzione. Per un elenco degli host URL bloccati, vedere il test case.
In Bicep usare la regola Linter senza URL dell'ambiente hardcoded.
L'esempio seguente ha esito negativo perché l'URL è hardcoded.
"variables":{
"AzureURL":"https://management.azure.com"
}
Il test ha esito negativo anche quando viene usato con concat o uri.
"variables":{
"AzureSchemaURL1": "[concat('https://','gallery.azure.com')]",
"AzureSchemaURL2": "[uri('gallery.azure.com','test')]"
}
L'esempio seguente ha esito positivo.
"variables": {
"AzureSchemaURL": "[environment().gallery]"
}
La posizione usa il parametro
Nome test: la posizione non deve essere hardcoded
Per impostare la posizione di una risorsa, i modelli devono avere un parametro denominato location
con il tipo impostato su string
. Nel modello principale, azuredeploy.json o mainTemplate.json, questo parametro può essere predefinito sulla posizione del gruppo di risorse. Nei modelli collegati o annidati, il parametro posizione non deve avere una posizione predefinita.
Gli utenti del modello possono avere accesso limitato alle aree in cui possono creare risorse. Una posizione di risorsa hardcoded potrebbe impedire agli utenti di creare una risorsa. L'espressione "[resourceGroup().location]"
potrebbe bloccare gli utenti se il gruppo di risorse è stato creato in un'area alla quale l'utente non può accedere. Gli utenti bloccati non possono usare il modello.
Specificando un parametro location
che per impostazione predefinita corrisponde alla posizione del gruppo di risorse, gli utenti possono usare il valore predefinito quando serve, ma anche specificare una posizione diversa.
In Bicep usare la regola Linter: nessuna espressione di posizione al di fuori dei valori predefiniti dei parametri.
L'esempio seguente ha esito negativo perché la location
della risorsa è impostata su resourceGroup().location
.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2021-02-01",
"name": "storageaccount1",
"location": "[resourceGroup().location]",
"kind": "StorageV2",
"sku": {
"name": "Premium_LRS",
"tier": "Premium"
}
}
]
}
L'esempio successivo usa un parametro location
ma ha esito negativo perché il parametro, per impostazione predefinita, corrisponde a una posizione hardcoded.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location": {
"type": "string",
"defaultValue": "westus"
}
},
"variables": {},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2021-02-01",
"name": "storageaccount1",
"location": "[parameters('location')]",
"kind": "StorageV2",
"sku": {
"name": "Premium_LRS",
"tier": "Premium"
}
}
],
"outputs": {}
}
L'esempio seguente ha esito positivo quando il modello viene usato come modello principale. Creare un parametro che, per impostazione predefinita, corrisponde alla posizione del gruppo di risorse, ma consente agli utenti di fornire un valore diverso.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Location for the resources."
}
}
},
"variables": {},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2021-02-01",
"name": "storageaccount1",
"location": "[parameters('location')]",
"kind": "StorageV2",
"sku": {
"name": "Premium_LRS",
"tier": "Premium"
}
}
],
"outputs": {}
}
Nota
Se l'esempio precedente viene usato come modello collegato, il test ha esito negativo. Se usato come modello collegato, rimuovere il valore predefinito.
Le risorse devono avere la posizione
Nome test: le risorse devono avere la posizione
La posizione di una risorsa deve essere impostata su un'espressione di modello o global
. L'espressione di modello usa in genere il parametrolocation
descritto in La posizione usa il parametro.
In Bicep usare la regola Linter - senza posizioni hardcoded.
L'esempio seguente ha esito negativo perché la location
non è un'espressione o global
.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"functions": [],
"variables": {},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2021-02-01",
"name": "storageaccount1",
"location": "westus",
"kind": "StorageV2",
"sku": {
"name": "Premium_LRS",
"tier": "Premium"
}
}
],
"outputs": {}
}
L'esempio seguente ha esito positivo perché la risorsa location
è impostata su global
.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"functions": [],
"variables": {},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2021-02-01",
"name": "storageaccount1",
"location": "global",
"kind": "StorageV2",
"sku": {
"name": "Premium_LRS",
"tier": "Premium"
}
}
],
"outputs": {}
}
Anche l'esempio successivo ha esito positivo perché il parametro location
usa un'espressione. La risorsa location
usa il valore dell'espressione.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Location for the resources."
}
}
},
"variables": {},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2021-02-01",
"name": "storageaccount1",
"location": "[parameters('location')]",
"kind": "StorageV2",
"sku": {
"name": "Premium_LRS",
"tier": "Premium"
}
}
],
"outputs": {}
}
Le dimensioni della macchina virtuale usano il parametro
Nome test: le dimensioni della macchina virtuale devono essere un parametro
Non codificare in modo rigido hardwareProfile
l'oggettovmSize
. Il test ha esito negativo quando hardwareProfile
viene omesso o contiene un valore hardcoded. Specificare un parametro in modo che gli utenti del modello possano modificare le dimensioni della macchina virtuale distribuita. Per ulteriori informazioni, vedere Microsoft.Compute virtualMachines.
L'esempio seguente ha esito negativo perché il hardwareProfile
valore dell’oggetto vmSize
è hardcoded.
"resources": [
{
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "2020-12-01",
"name": "demoVM",
"location": "[parameters('location')]",
"properties": {
"hardwareProfile": {
"vmSize": "Standard_D2_v3"
}
}
}
]
L'esempio ha esito positivo quando un parametro specifica un valore per vmSize
:
"parameters": {
"vmSizeParameter": {
"type": "string",
"defaultValue": "Standard_D2_v3",
"metadata": {
"description": "Size for the virtual machine."
}
}
}
Quindi, hardwareProfile
usa un'espressione per vmSize
per fare riferimento al valore del parametro:
"resources": [
{
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "2020-12-01",
"name": "demoVM",
"location": "[parameters('location')]",
"properties": {
"hardwareProfile": {
"vmSize": "[parameters('vmSizeParameter')]"
}
}
}
]
I valori min e max sono numeri
Nome test: i valori min e max sono numeri
Quando si definisce un parametro con minValue
e maxValue
, specificarli come numeri. È necessario usare minValue
e maxValue
come coppia o il test non riesce.
L'esempio seguente ha esito negativo perché minValue
e maxValue
sono stringhe.
"exampleParameter": {
"type": "int",
"minValue": "0",
"maxValue": "10"
}
L'esempio seguente ha esito negativo perché viene usato solo minValue
.
"exampleParameter": {
"type": "int",
"minValue": 0
}
L'esempio seguente ha esito positivo perché minValue
e maxValue
sono numeri.
"exampleParameter": {
"type": "int",
"minValue": 0,
"maxValue": 10
}
Parametro artefatti definito correttamente
Nome test: parametro artefatti
Quando si includono parametri per _artifactsLocation
e _artifactsLocationSasToken
, usare le impostazioni predefinite e i tipi corretti. Per superare questo test devono essere soddisfatte le condizioni seguenti:
- Se si specifica un parametro, è necessario specificare l'altro.
_artifactsLocation
deve essere unstring
._artifactsLocation
deve avere un valore predefinito nel modello principale._artifactsLocation
non può avere un valore predefinito in un modello annidato._artifactsLocation
deve avere"[deployment().properties.templateLink.uri]"
oppure l'URL del repository grezzo per il valore predefinito._artifactsLocationSasToken
deve essere unsecureString
._artifactsLocationSasToken
può avere solo una stringa vuota per il valore predefinito._artifactsLocationSasToken
non può avere un valore predefinito in un modello annidato.
In Bicep usare la regola Linter - parametri degli artefatti.
Le variabili dichiarate devono essere usate
Nome test: È necessario fare riferimento alle variabili
Questo test trova le variabili che non vengono usate nel modello o non vengono usate in un'espressione valida. Per ridurre la confusione nel modello, eliminare tutte le variabili definite ma non usate.
È necessario fare riferimento alle variabili che usano l'elemento copy
per iterare i valori. Per ulteriori informazioni, vedere Iterazione delle variabili nei modelli di ARM.
In Bicep usare la regola Linter - senza variabili inutilizzate.
L'esempio seguente ha esito negativo perché non viene fatto riferimento alla variabile che usa l'elemento copy
.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"itemCount": {
"type": "int",
"defaultValue": 5
}
},
"variables": {
"copy": [
{
"name": "stringArray",
"count": "[parameters('itemCount')]",
"input": "[concat('item', copyIndex('stringArray', 1))]"
}
]
},
"resources": [],
"outputs": {}
}
L'esempio seguente ha esito negativo perché nell'espressione che fa riferimento a una variabile manca la parentesi quadra iniziale ([
).
"outputs": {
"outputVariable": {
"type": "string",
"value": " variables('varExample')]"
}
}
Nell'esempio seguente ha esito positivo perché viene fatto riferimento alla variabile in outputs
.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"itemCount": {
"type": "int",
"defaultValue": 5
}
},
"variables": {
"copy": [
{
"name": "stringArray",
"count": "[parameters('itemCount')]",
"input": "[concat('item', copyIndex('stringArray', 1))]"
}
]
},
"resources": [],
"outputs": {
"arrayResult": {
"type": "array",
"value": "[variables('stringArray')]"
}
}
}
Nell'esempio seguente ha esito positivo perché l'espressione è valida.
"outputs": {
"outputVariable": {
"type": "string",
"value": "[variables('varExample')]"
}
}
La variabile dinamica non deve usare concat
Nome test: I riferimenti a variabili dinamiche non devono usare Concat
A volte è necessario costruire in modo dinamico una variabile in base al valore di un'altra variabile o parametro. Non usare la funzione concat quando si imposta il valore. Usare invece un oggetto che includa le opzioni disponibili e ottenere in modo dinamico una delle proprietà dall'oggetto durante la distribuzione.
L'esempio seguente ha esito positivo. La variabile currentImage
viene impostata dinamicamente durante la distribuzione.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"osType": {
"type": "string",
"allowedValues": [
"Windows",
"Linux"
]
}
},
"variables": {
"imageOS": {
"Windows": {
"image": "Windows Image"
},
"Linux": {
"image": "Linux Image"
}
},
"currentImage": "[variables('imageOS')[parameters('osType')].image]"
},
"resources": [],
"outputs": {
"result": {
"type": "string",
"value": "[variables('currentImage')]"
}
}
}
Usare la versione recente dell'API
Nome test: apiVersions deve essere recente
La versione dell'API per ogni risorsa deve usare una versione recente hardcoded come stringa. Il test valuta la versione dell'API nel modello rispetto alle versioni del provider di risorse nella cache del toolkit. Una versione dell'API che risalga a meno di due anni dalla data in cui è stato eseguito il test è considerata recente. Non usare una versione di anteprima quando è disponibile una versione più recente.
Un avviso che segnala di non aver trovato una versione dell'API indica solo che la versione non è inclusa nella cache del toolkit. L'uso, consigliato, della versione più recente di un'API può generare l'avviso.
Ulteriori informazioni sulla cache del toolkit.
In Bicep usare la regola Linter - usare le versioni API recenti.
L'esempio seguente ha esito negativo perché la versione dell'API ha più di due anni.
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2019-06-01",
"name": "storageaccount1",
"location": "[parameters('location')]"
}
]
L'esempio seguente ha esito negativo perché viene usata una versione di anteprima quando è disponibile una versione più recente.
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2020-08-01-preview",
"name": "storageaccount1",
"location": "[parameters('location')]"
}
]
L'esempio seguente ha esito positivo perché si tratta di una versione recente e non di una versione di anteprima.
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2021-02-01",
"name": "storageaccount1",
"location": "[parameters('location')]"
}
]
Usare la versione dell'API hardcoded
Nome test: Provider apiVersions non consentiti
La versione dell'API per un tipo di risorsa determina quali proprietà sono disponibili. Fornire una versione dell'API hardcoded nel modello. Non recuperare una versione dell'API determinata durante la distribuzione perché non sarebbero note le proprietà disponibili.
L'esempio seguente ha esito negativo.
"resources": [
{
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "[providers('Microsoft.Compute', 'virtualMachines').apiVersions[0]]",
...
}
]
L'esempio seguente ha esito positivo.
"resources": [
{
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "2020-12-01",
...
}
]
Le proprietà non possono essere vuote
Nome test: il modello non deve contenere spazi vuoti
Non impostare proprietà hardcoded su un valore vuoto. I valori vuoti includono stringhe, oggetti o matrici null e vuoti. Se una proprietà è impostata su un valore vuoto, rimuovere tale proprietà dal modello. È possibile impostare una proprietà su un valore vuoto durante la distribuzione, ad esempio tramite un parametro.
La proprietà template
in un modello annidato può includere proprietà vuote. Per ulteriori informazioni sui modelli annidati, vedere Distribuzioni di Microsoft.Resources.
L'esempio seguente ha esito negativo perché sono presenti proprietà vuote.
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2021-01-01",
"name": "storageaccount1",
"location": "[parameters('location')]",
"sku": {},
"kind": ""
}
]
L'esempio seguente ha esito positivo perché le proprietà includono valori.
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2021-01-01",
"name": "storageaccount1",
"location": "[parameters('location')]",
"sku": {
"name": "Standard_LRS",
"tier": "Standard"
},
"kind": "Storage"
}
]
Usare le funzioni ID risorsa
Nome test: gli ID devono essere derivati da ResourceID
Quando si specifica un ID risorsa, usare una delle funzioni ID risorsa. Le funzioni consentite sono:
Non usare la funzione concat per creare un ID risorsa.
In Bicep usare la regola Linter : usare le funzioni ID risorsa.
L'esempio seguente ha esito negativo.
"networkSecurityGroup": {
"id": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/networkSecurityGroups/', variables('networkSecurityGroupName'))]"
}
L'esempio successivo ha esito positivo.
"networkSecurityGroup": {
"id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
}
La funzione ResourceId ha parametri corretti
Nome test: ResourceIds non deve contenere
Quando si generano ID risorsa, non usare funzioni non necessarie per i parametri facoltativi. Per impostazione predefinita, la funzione resourceId usa la sottoscrizione e il gruppo di risorse correnti. Non è necessario specificare tali valori.
L'esempio seguente ha esito negativo perché non è necessario specificare l'ID sottoscrizione e il nome del gruppo di risorse correnti.
"networkSecurityGroup": {
"id": "[resourceId(subscription().subscriptionId, resourceGroup().name, 'Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
}
L'esempio successivo ha esito positivo.
"networkSecurityGroup": {
"id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
}
Questo test si applica a:
Per reference
e list*
, il test ha esito negativo quando si usa concat
per costruire l'ID risorsa.
Procedure consigliate per dependsOn
Nome test: Procedure consigliate per DependsOn
Quando si impostano le dipendenze di distribuzione, non usare la funzione se per testare una condizione. Se una risorsa dipende da una risorsa che viene distribuita in modo condizionale, impostare la dipendenza come si farebbe con qualsiasi risorsa. Quando una risorsa condizionale non viene distribuita, Azure Resource Manager la rimuove automaticamente dalle dipendenze necessarie.
L'elemento dependsOn
non può iniziare con una funzione concat .
In Bicep usare regola Linter - nessuna voce dependsOn non necessaria.
L'esempio seguente ha esito negativo perché contiene una funzione if
.
"dependsOn": [
"[if(equals(parameters('newOrExisting'),'new'), variables('storageAccountName'), '')]"
]
L'esempio seguente ha esito negativo perché inizia con concat
.
"dependsOn": [
"[concat(variables('storageAccountName'))]"
]
L'esempio seguente ha esito positivo.
"dependsOn": [
"[variables('storageAccountName')]"
]
Le distribuzioni annidate o collegate non possono usare il debug
Nome test: Le risorse di distribuzione non devono essere debug
Quando si definisce un modello annidato o collegato con il tipo di risorsa Microsoft.Resources/deployments
, è possibile abilitare il debug. Il debug viene usato quando si deve testare un modello, ma può mostrare informazioni riservate. Prima che il modello venga usato nell'ambiente di produzione, disattivare il debug. È possibile rimuovere l'oggetto debugSetting
o modificare la proprietà detailLevel
in none
.
L'esempio seguente ha esito negativo.
"debugSetting": {
"detailLevel": "requestContent"
}
L'esempio seguente ha esito positivo.
"debugSetting": {
"detailLevel": "none"
}
I nomi utente amministratore non possono essere un valore letterale
Nome test: adminUsername non deve essere un valore letterale
Quando si imposta un adminUserName
, non usare un valore letterale. Creare un parametro per il nome utente e usare un'espressione per fare riferimento al valore del parametro.
In Bicep usare la regola Linter - nome utente amministratore non deve essere letterale.
L'esempio seguente ha esito negativo con un valore letterale.
"osProfile": {
"adminUserName": "myAdmin"
}
L'esempio seguente ha esito positivo con un'espressione.
"osProfile": {
"adminUsername": "[parameters('adminUsername')]"
}
Usare l'immagine più recente della macchina virtuale
Nome test: le immagini delle macchine virtuali devono usare la versione più recente
Questo test è disabilitato, ma il risultato mostra che l’esito è stato positivo. La procedura consigliata consiste nel controllare il modello per i criteri seguenti:
Se il modello include una macchina virtuale con un'immagine, assicurarsi che sia usata la versione più recente dell'immagine.
In Bicep usare la regola Linter - usare immagine stabile della macchina virtuale.
Usare immagini stabili di macchine virtuali
Nome test: Le macchine virtuali non devono essere in anteprima
Le macchine virtuali non devono usare immagini di anteprima. Il test controlla per storageProfile
verificare che imageReference
non usi una stringa contenente anteprima. E tale anteprima non viene usata nelle imageReference
proprietà offer
, sku
o version
.
Per ulteriori informazioni sulla proprietà imageReference
, vedere Microsoft.Compute virtualMachines e Microsoft.Compute virtualMachineScaleSets.
In Bicep usare la regola Linter - usare immagine stabile della macchina virtuale.
L'esempio seguente ha esito negativo perché imageReference
è una stringa che contiene anteprima.
"properties": {
"storageProfile": {
"imageReference": "latest-preview"
}
}
L'esempio seguente ha esito negativo quando anteprimaviene usata in offer
, sku
o version
.
"properties": {
"storageProfile": {
"imageReference": {
"publisher": "Canonical",
"offer": "UbuntuServer_preview",
"sku": "16.04-LTS-preview",
"version": "preview"
}
}
}
L'esempio seguente ha esito positivo.
"storageProfile": {
"imageReference": {
"publisher": "Canonical",
"offer": "UbuntuServer",
"sku": "16.04-LTS",
"version": "latest"
}
}
Non usare l'estensione ManagedIdentity
Nome test: ManagedIdentityExtension non deve essere usata
Non applicare l'estensione ManagedIdentity
a una macchina virtuale. L'estensione è stata deprecata nel 2019 e non deve più essere usata.
Gli output non possono includere segreti
Nome test: gli output non devono contenere segreti
Non includere valori nella sezione outputs
che potenzialmente mostra segreti. Ad esempio, proteggere i parametri di tipo secureString
o secureObject
, o le funzioni list* come listKeys
.
L'output di un modello viene archiviato nella cronologia di distribuzione, perciò un utente malintenzionato potrebbe trovare tali informazioni.
In Bicep usare la regola Linter - gli output non devono contenere segreti.
L'esempio seguente ha esito negativo perché include un parametro sicuro in un valore di output.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"secureParam": {
"type": "secureString"
}
},
"functions": [],
"variables": {},
"resources": [],
"outputs": {
"badResult": {
"type": "string",
"value": "[concat('this is the value ', parameters('secureParam'))]"
}
}
}
L'esempio seguente ha esito negativo perché usa una funzione list* negli output.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageName": {
"type": "string"
}
},
"functions": [],
"variables": {},
"resources": [],
"outputs": {
"badResult": {
"type": "object",
"value": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageName')), '2021-02-01')]"
}
}
}
Usare protectedSettings per i segreti commandToExecute
Nome test: CommandToExecute deve usare ProtectedSettings per i segreti
Per le risorse con tipo CustomScript
, usare il protectedSettings
crittografato quando commandToExecute
include dati segreti, ad esempio una password. Ad esempio, i dati segreti possono essere usati in parametri sicuri di tipo secureString
o secureObject
, funzioni list* come listKeys
, o script personalizzati.
Non usare i dati segreti nell'oggetto settings
perché usa testo in chiaro. Per ulteriori informazioni, vedere Microsoft.Compute virtualMachines/extensions, Windowso Linux.
In Bicep usare la regola Linter - usare protectedSettings per i segreti commandToExecute.
L'esempio seguente ha esito negativo perché settings
usa commandToExecute
con un parametro sicuro.
"parameters": {
"adminPassword": {
"type": "secureString"
}
}
...
"properties": {
"type": "CustomScript",
"settings": {
"commandToExecute": "[parameters('adminPassword')]"
}
}
L'esempio seguente ha esito negativo perché settings
usa commandToExecute
con una funzionelistKeys
.
"properties": {
"type": "CustomScript",
"settings": {
"commandToExecute": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageName')), '2021-02-01')]"
}
}
L'esempio seguente ha esito positivo perché protectedSettings
usa commandToExecute
con un parametro sicuro.
"parameters": {
"adminPassword": {
"type": "secureString"
}
}
...
"properties": {
"type": "CustomScript",
"protectedSettings": {
"commandToExecute": "[parameters('adminPassword')]"
}
}
L'esempio seguente ha esito positivo perché protectedSettings
usa commandToExecute
con una funzione listKeys
.
"properties": {
"type": "CustomScript",
"protectedSettings": {
"commandToExecute": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageName')), '2021-02-01')]"
}
}
Usare le versioni api recenti nelle funzioni di riferimento
Nome test: apiVersions deve essere recente nelle funzioni di riferimento
La versione dell'API usata in una funzione di riferimento deve essere recente e non una versione in anteprima. Il test valuta la versione dell'API nel modello rispetto alle versioni del provider di risorse nella cache del toolkit. Una versione dell'API che risalga a meno di due anni dalla data in cui è stato eseguito il test è considerata recente.
Un avviso che segnala di non aver trovato una versione dell'API indica solo che la versione non è inclusa nella cache del toolkit. L'uso, consigliato, della versione più recente di un'API può generare l'avviso.
Ulteriori informazioni sulla cache del toolkit.
L'esempio seguente ha esito negativo perché la versione dell'API ha più di due anni.
"outputs": {
"stgAcct": {
"type": "string",
"value": "[reference(resourceId(parameters('storageResourceGroup'), 'Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2019-06-01')]"
}
}
L'esempio seguente ha esito negativo perché la versione dell'API è una versione in anteprima.
"outputs": {
"stgAcct": {
"type": "string",
"value": "[reference(resourceId(parameters('storageResourceGroup'), 'Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2020-08-01-preview')]"
}
}
L'esempio seguente ha esito positivo perché la versione dell'API ha meno di due anni e non è una versione in anteprima.
"outputs": {
"stgAcct": {
"type": "string",
"value": "[reference(resourceId(parameters('storageResourceGroup'), 'Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2021-02-01')]"
}
}
Usare il tipo e il nome nelle funzioni resourceId
Nome test: le risorse non devono essere ambigue
Questo test è disabilitato, ma il risultato mostra che l’esito è stato positivo. La procedura consigliata consiste nel controllare il modello per i criteri seguenti:
Un resourceId deve includere un tipo di risorsa e un nome di risorsa. Questo test trova tutte le funzioni resourceId
del modello e verifica che la risorsa venga usata nel modello con la sintassi corretta. In caso contrario, la funzione è considerata ambigua.
Ad esempio, una funzione resourceId
è considerata ambigua:
- Quando non viene trovata una risorsa nel modello e non viene specificato un gruppo di risorse.
- Se una risorsa include una condizione e un gruppo di risorse non è specificato.
- Se una risorsa correlata contiene alcuni segmenti di nome ma non tutti. Ad esempio, una risorsa figlio contiene più segmenti di nome. Per ulteriori informazioni, vedere commenti resourceId.
Usare l'ambito interno per i parametri sicuri della distribuzione annidata
Nome test: Parametri sicuri nelle distribuzioni annidate
Usare l'oggetto expressionEvaluationOptions
del modello annidato con ambito inner
per valutare le espressioni che contengono parametri sicuri di tipo secureString
o secureObject
o funzioni list* , ad esempio listKeys
. Se viene usato l'ambito outer
, le espressioni vengono valutate in testo non crittografato nell'ambito del modello padre. Il valore sicuro è quindi visibile a chiunque abbia accesso alla cronologia di distribuzione. Il valore predefinito di expressionEvaluationOptions
è outer
.
Per ulteriori informazioni sui modelli annidati, vedere Distribuzioni di Microsoft.Resources e Ambito di valutazione delle espressioni nei modelli annidati.
In Bicep usare la regola Linter - parametri sicuri nella distribuzione annidata.
L'esempio seguente ha esito negativo perché expressionEvaluationOptions
usa l’ambito outer
per valutare parametri sicuri o funzionilist*
.
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2021-04-01",
"name": "nestedTemplate",
"properties": {
"expressionEvaluationOptions": {
"scope": "outer"
}
}
}
]
L'esempio seguente ha esito positivo perché expressionEvaluationOptions
usa l'ambito inner
per valutare parametri sicuri o funzioni list*
funzioni.
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2021-04-01",
"name": "nestedTemplate",
"properties": {
"expressionEvaluationOptions": {
"scope": "inner"
}
}
}
]
Passaggi successivi
- Per informazioni sull'esecuzione del toolkit di test, vedere Usare il toolkit di test dei modelli di ARM.
- Per un modulo Learn che consideri l'uso del toolkit di test, vedere Visualizzare in anteprima le modifiche e convalidare le risorse di Azure usando le simulazioni e il toolkit di test dei modelli di ARM.
- Per testare i file dei parametri, vedere Test case per i file di parametri.
- Per i test createUiDefinition, vedere Test case per createUiDefinition.json.
- Per informazioni su test per tutti i file, consultare Test case per tutti i file.