Condividi tramite


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 hardwareProfilel'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 hardwareProfilevalore 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 un string.
  • _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 un secureString.
  • _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, skuo 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, skuo 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