Casos de teste para modelos do ARM
Este artigo descreve os testes que são executados com o kit de ferramentas de teste de modelo para modelos do ARM (modelos do Azure Resource Manager). Ele fornece exemplos de aprovação ou reprovação no teste e inclui o nome de cada teste. Para obter mais informações sobre como executar testes, ou um teste específico, confira Parâmetros de teste.
Usar o esquema correto
Nome do teste: o esquema deploymenttemplate está correto
No modelo, você deve especificar um valor de esquema válido.
O exemplo a seguir é reprovado porque o esquema é inválido.
{
"$schema": "https://schema.management.azure.com/schemas/2019-01-01/deploymentTemplate.json#",
}
O exemplo a seguir exibe um aviso porque a versão do esquema 2015-01-01
foi preterida e não mantida.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
}
O exemplo a seguir é aprovado usando um esquema válido.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
}
A propriedade schema
do modelo deve ser definida para um dos seguintes esquemas:
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
Parâmetros declarados devem ser usados
Nome do teste: parâmetros devem ser referenciados
Este teste localiza parâmetros que não são usados no modelo ou que não são usados em uma expressão válida.
Para reduzir a confusão no modelo, exclua todos os parâmetros definidos, mas não usados. A eliminação de parâmetros não utilizados simplifica as implantações de modelos porque você não precisa fornecer valores desnecessários.
No Bicep, use a regra do Linter – sem parâmetros não utilizados.
O exemplo a seguir é reprovado porque a expressão que faz referência a um parâmetro está faltando o colchete inicial ([
).
"resources": [
{
"location": " parameters('location')]"
}
]
O exemplo a seguir é aprovado porque a expressão é válida.
"resources": [
{
"location": "[parameters('location')]"
}
]
Parâmetros seguros não podem ter padrão embutido em código
Nome do teste: parâmetros seguros de cadeia de caracteres não podem ter padrão
Não forneça um valor padrão inserido no código para um parâmetro seguro no modelo. Um parâmetro seguro pode ter uma cadeia de caracteres vazia como valor padrão ou usar a função newGuid em uma expressão.
Você usa os tipos secureString
ou secureObject
em parâmetros que contêm valores confidenciais, como senhas. Quando um parâmetro usa um tipo seguro, o valor do parâmetro não é registrado ou armazenado no histórico de implantação. Essa ação impede que um usuário mal-intencionado descubra o valor confidencial.
Quando você fornece um valor padrão, esse valor é detectável por qualquer pessoa que tenha acesso ao modelo ou ao histórico de implantação.
No Bicep, use a regra do Linter – padrão de parâmetro seguro.
O exemplo a seguir é reprovado.
"parameters": {
"adminPassword": {
"defaultValue": "HardcodedPassword",
"type": "secureString"
}
}
O exemplo a seguir é aprovado.
"parameters": {
"adminPassword": {
"type": "secureString"
}
}
O exemplo a seguir é aprovado porque a função newGuid
é usada.
"parameters": {
"secureParameter": {
"type": "secureString",
"defaultValue": "[newGuid()]"
}
}
As URLs de ambiente não podem ser embutidas em código
Nome do teste: deploymenttemplate não deve conter URI inserido no código
Não use URLs de ambiente embutidas em código em seu modelo. Em vez disso, use a função de ambiente para obter essas URLs dinamicamente durante a implantação. Para obter uma lista dos hosts de URL que estão bloqueados, confira o caso de teste.
No Bicep, use a regra do Linter – nenhuma URL de ambiente codificada.
O exemplo a seguir é reprovado porque a URL está embutida no código.
"variables":{
"AzureURL":"https://management.azure.com"
}
O teste também reprova quando usado com concat ou URI.
"variables":{
"AzureSchemaURL1": "[concat('https://','gallery.azure.com')]",
"AzureSchemaURL2": "[uri('gallery.azure.com','test')]"
}
O exemplo a seguir é aprovado.
"variables": {
"AzureSchemaURL": "[environment().gallery]"
}
O local usa parâmetro
Nome do teste: local não deve ser inserido em código
Para definir a localização de um recurso, seus modelos devem ter um parâmetro denominado location
com o tipo definido como string
. No modelo principal, azuredeploy.jsno ou mainTemplate.json, esse parâmetro pode usar como padrão o local do grupo de recursos. Em modelos vinculados ou aninhados, o parâmetro de local não deve ter um local padrão.
Os usuários do modelo podem ter acesso limitado a regiões em que podem criar recursos. Um local de recurso em código pode impedir que os usuários criarem um recurso. A expressão "[resourceGroup().location]"
pode bloquear usuários se o grupo de recursos foi criado em uma região que o usuário não pode acessar. Os usuários bloqueados não podem usar o modelo.
Ao fornecer um parâmetro de location
que usa como padrão o local do grupo de recursos, os usuários podem usar o valor padrão quando for conveniente, mas também especificar um local diferente.
No Bicep, use a Regra linter – sem expressões de localização fora dos valores padrão do parâmetro.
O exemplo a seguir é reprovado porque o location
do recurso está definido como 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"
}
}
]
}
O próximo exemplo usa um parâmetro location
, mas é reprovado porque o padrão do parâmetro é um local embutido em código.
{
"$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": {}
}
O exemplo a seguir é aprovado quando o modelo é usado como o modelo principal. Crie um parâmetro que usa como padrão o local do grupo de recursos, mas permite que os usuários forneçam um valor diferente.
{
"$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": {}
}
Observação
Se o exemplo anterior for usado como um modelo vinculado, o teste será reprovado. Quando usado como um modelo vinculado, remova o valor padrão.
Os recursos devem ter o local
Nome do teste: recursos devem ter o local
O local de um recurso deve ser definido como uma expressão de modelo ou global
. A expressão do modelo normalmente usaria o parâmetro location
descrito em Locais de uso do parâmetro.
No Bicep, use a regra do Linter – nenhum local codificado.
O exemplo a seguir é reprovado porque location
não é uma expressão ou 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": {}
}
O exemplo a seguir é aprovado porque o recurso location
está definido como 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": {}
}
O próximo exemplo também é aprovado porque o parâmetro location
usa uma expressão. O recurso location
usa o valor da expressão.
{
"$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": {}
}
O tamanho da VM usa o parâmetro
Nome do teste: tamanho da VM deve ser um parâmetro
Não faça o embutimento em código de vmSize
do hardwareProfile
. O teste é reprovado quando o hardwareProfile
é omitido ou contém um valor embutido em código. Forneça um parâmetro para que os usuários do modelo possam modificar o tamanho da máquina virtual implantada. Para obter mais informações, confira Microsoft.Compute virtualMachines.
O exemplo a seguir é reprovado porque o objeto vmSize
de hardwareProfile
é um valor embutido em código.
"resources": [
{
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "2020-12-01",
"name": "demoVM",
"location": "[parameters('location')]",
"properties": {
"hardwareProfile": {
"vmSize": "Standard_D2_v3"
}
}
}
]
O exemplo é aprovado quando um parâmetro especifica um valor para vmSize
:
"parameters": {
"vmSizeParameter": {
"type": "string",
"defaultValue": "Standard_D2_v3",
"metadata": {
"description": "Size for the virtual machine."
}
}
}
Em seguida, hardwareProfile
usa uma expressão a fim de que vmSize
faça referência ao valor do parâmetro:
"resources": [
{
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "2020-12-01",
"name": "demoVM",
"location": "[parameters('location')]",
"properties": {
"hardwareProfile": {
"vmSize": "[parameters('vmSizeParameter')]"
}
}
}
]
Os valores mínimo e máximo são números
Nome do teste: valor mínimo e máximo são números
Ao definir um parâmetro com minValue
e maxValue
, especifique-os como números. Você deve usar minValue
e maxValue
como um par ou o teste será reprovado.
O exemplo a seguir é reprovado porque minValue
e maxValue
são cadeias de caracteres.
"exampleParameter": {
"type": "int",
"minValue": "0",
"maxValue": "10"
}
O exemplo a seguir é reprovado apenas porque minValue
é usado.
"exampleParameter": {
"type": "int",
"minValue": 0
}
O exemplo a seguir é aprovado porque minValue
e maxValue
são números.
"exampleParameter": {
"type": "int",
"minValue": 0,
"maxValue": 10
}
Parâmetro de artefatos definido corretamente
Nome do teste: parâmetro de artefatos
Ao incluir parâmetros para _artifactsLocation
e _artifactsLocationSasToken
, use os padrões e tipos corretos. As seguintes condições devem ser atendidas para passar neste teste:
- Se você fornecer um parâmetro, deverá fornecer o outro.
_artifactsLocation
deve ser umstring
._artifactsLocation
deve ter um valor padrão no modelo principal._artifactsLocation
não pode ter um valor padrão em um modelo aninhado._artifactsLocation
deve ter"[deployment().properties.templateLink.uri]"
ou a URL do repositório bruto como valor padrão._artifactsLocationSasToken
deve ser umsecureString
._artifactsLocationSasToken
só pode ter uma cadeia de caracteres vazia como valor padrão._artifactsLocationSasToken
não pode ter um valor padrão em um modelo aninhado.
No Bicep, use a regra do Linter – parâmetros de artefatos.
Variáveis declaradas devem ser usadas
Nome do teste: variáveis devem ser referenciadas
Este teste localiza variáveis que não são usadas no modelo ou que não são usadas em uma expressão válida. Para reduzir a confusão no modelo, exclua todas as variáveis definidas, mas não usadas.
Variáveis que usam o elemento copy
para iterar valores devem ser referenciadas. Para obter mais informações, confira Iteração de variável em modelos do ARM.
No Bicep, use a regra do Linter – nenhuma variável não utilizada.
O exemplo a seguir é reprovado porque a variável que usa o elemento copy
não é referenciada.
{
"$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": {}
}
O exemplo a seguir é reprovado porque a expressão que faz referência a uma variável está sem o colchete inicial ([
).
"outputs": {
"outputVariable": {
"type": "string",
"value": " variables('varExample')]"
}
}
O exemplo a seguir é aprovado porque a variável é referenciada em 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')]"
}
}
}
O exemplo a seguir é aprovado porque a expressão é válida.
"outputs": {
"outputVariable": {
"type": "string",
"value": "[variables('varExample')]"
}
}
A variável dinâmica não deve usar concat
Nome do teste: referências de variável dinâmica não devem usar concat
Às vezes, você precisa construir dinamicamente uma variável com base no valor de outra variável ou parâmetro. Não use a função concat ao definir o valor. Em vez disso, use um objeto que inclua as opções disponíveis e obtenha dinamicamente uma das propriedades do objeto durante a implantação.
O exemplo a seguir é aprovado. A variável currentImage
é definida dinamicamente durante a implantação.
{
"$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')]"
}
}
}
Usar a versão recente de API
Nome do teste: apiVersions deve ser recente
A versão da API para cada recurso deve usar uma versão recente codificada como cadeia de caracteres. O teste avalia a versão da API em seu modelo em relação às versões do provedor de recursos no cache do kit de ferramentas. Uma versão da API com menos de dois anos a partir da data em que o teste foi executado é considerada recente. Não use uma versão de visualização quando uma versão mais recente estiver disponível.
Um aviso de que uma versão da API não foi encontrada apenas indica que a versão não está incluída no cache do kit de ferramentas. Usar a versão mais recente de uma API, que é recomendada, pode gerar o aviso.
Saiba mais sobre o cache do kit de ferramentas.
No Bicep, use a regra do Linter – usar versões recentes da API.
O exemplo a seguir é reprovado porque a versão da API tem mais de dois anos.
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2019-06-01",
"name": "storageaccount1",
"location": "[parameters('location')]"
}
]
O exemplo a seguir é reprovado porque uma versão de visualização é usada quando uma versão mais recente está disponível.
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2020-08-01-preview",
"name": "storageaccount1",
"location": "[parameters('location')]"
}
]
O exemplo a seguir é aprovado porque é uma versão recente que não é de visualização.
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2021-02-01",
"name": "storageaccount1",
"location": "[parameters('location')]"
}
]
Usar versão de API embutida em código
Nome do teste: provedores apiVersions não são permitidos
A versão de API para um tipo de recurso determina quais propriedades estão disponíveis. Forneça uma versão de API inserida em código no modelo. Não recupere uma versão da API determinada durante a implantação porque você não sabe quais propriedades estão disponíveis.
O exemplo a seguir é reprovado.
"resources": [
{
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "[providers('Microsoft.Compute', 'virtualMachines').apiVersions[0]]",
...
}
]
O exemplo a seguir é aprovado.
"resources": [
{
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "2020-12-01",
...
}
]
As propriedades não podem estar vazias
Nome do teste: modelo não deve conter espaços em branco
Não use propriedades embutidas em código em um valor vazio. Os valores vazios incluem cadeias de caracteres, objetos ou matrizes nulos e vazios. Se uma propriedade for definida com um valor vazio, remova-a do seu modelo. Você pode definir uma propriedade com um valor vazio durante a implantação, como por meio de um parâmetro.
A propriedade template
em um modelo aninhado pode incluir propriedades vazias. Para obter mais informações sobre modelos aninhados, confira Implantações do Microsoft.Resources.
O exemplo a seguir é reprovado porque existem propriedades vazias.
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2021-01-01",
"name": "storageaccount1",
"location": "[parameters('location')]",
"sku": {},
"kind": ""
}
]
O exemplo a seguir é aprovado porque as propriedades incluem valores.
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2021-01-01",
"name": "storageaccount1",
"location": "[parameters('location')]",
"sku": {
"name": "Standard_LRS",
"tier": "Standard"
},
"kind": "Storage"
}
]
Usar funções de ID do recurso
Nome do teste: IDs devem ser derivadas de ResourceIDs
Ao especificar uma ID do recurso, use uma das funções de ID de recurso. As funções permitidas são:
Não use a função concat para criar uma ID do recurso.
No Bicep, use a regra do Linter – usar funções de ID de recurso.
O exemplo a seguir é reprovado.
"networkSecurityGroup": {
"id": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/networkSecurityGroups/', variables('networkSecurityGroupName'))]"
}
O exemplo a seguir é aprovado.
"networkSecurityGroup": {
"id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
}
A função resourceId tem parâmetros corretos
Nome do teste: resourceIds não deve conter
Ao gerar IDs do recurso, não use funções desnecessárias para parâmetros opcionais. Por padrão, a função resourceId usa a assinatura e o grupo de recursos atuais. Não é necessário fornecer esses valores.
O exemplo a seguir é reprovado, pois você não precisa fornecer a ID da assinatura e o nome do grupo de recursos atuais.
"networkSecurityGroup": {
"id": "[resourceId(subscription().subscriptionId, resourceGroup().name, 'Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
}
O exemplo a seguir é aprovado.
"networkSecurityGroup": {
"id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
}
Este teste se aplica a:
Para reference
e list*
, o teste reprova quando você usa concat
para construir a ID do recurso.
Práticas recomendadas dependsOn
Nome do teste: práticas recomendadas dependsOn
Ao definir as dependências de implantação, não use a função if para testar uma condição. Se um recurso depender de outro que seja implantado condicionalmente, defina a dependência da mesma forma que você faria com qualquer recurso. Quando um recurso condicional não é implantado, o Azure Resource Manager o remove automaticamente das dependências necessárias.
O elemento dependsOn
não pode começar com uma função concat.
No Bicep, use a regra do Linter – nenhuma entrada dependsOn desnecessária.
O exemplo a seguir é reprovado porque contém uma função if
.
"dependsOn": [
"[if(equals(parameters('newOrExisting'),'new'), variables('storageAccountName'), '')]"
]
O exemplo a seguir é reprovado porque começa com concat
.
"dependsOn": [
"[concat(variables('storageAccountName'))]"
]
O exemplo a seguir é aprovado.
"dependsOn": [
"[variables('storageAccountName')]"
]
Implantações aninhadas ou vinculadas não podem usar depuração
Nome do teste: recursos de implantação não devem ser depurados
Ao definir um modelo aninhado ou vinculado com o tipo de recurso Microsoft.Resources/deployments
, você pode habilitar a depuração. A depuração é usada quando você precisa testar um modelo, mas pode expor informações confidenciais. Antes que o modelo seja usado na produção, desligue a depuração. Você pode remover o objeto debugSetting
ou alterar a propriedade detailLevel
para none
.
O exemplo a seguir é reprovado.
"debugSetting": {
"detailLevel": "requestContent"
}
O exemplo a seguir é aprovado.
"debugSetting": {
"detailLevel": "none"
}
Nomes de usuário administrador não podem ser valores literais
Nome do teste: adminUsername não deve ser literal
Ao definir um adminUserName
, não use um valor literal. Crie um parâmetro para o nome de usuário e use uma expressão para referenciar o valor do parâmetro.
No Bicep, use a regra do Linter – o nome de usuário administrador não deve ser literal.
O exemplo a seguir é reprovado com um valor literal.
"osProfile": {
"adminUserName": "myAdmin"
}
O exemplo a seguir é aprovado com uma expressão.
"osProfile": {
"adminUsername": "[parameters('adminUsername')]"
}
Usar imagem de VM mais recente
Nome do teste: imagens de VM devem usar a versão mais recente
Esse teste está desabilitado, mas a saída mostra que ele foi aprovado. A melhor prática é verificar seu modelo quanto aos seguintes critérios:
Se o modelo incluir uma máquina virtual com uma imagem, verifique se ele está usando a versão mais recente da imagem.
No Bicep, use a regra do Linter – usar imagem de VM estável.
Usar imagens de VM estáveis
Nome do teste: máquinas virtuais não devem ser pré-visualizadas
As máquinas virtuais não devem usar imagens de pré-visualização. O teste escaneia o storageProfile
para verificar se o imageReference
não está usando uma cadeia de caracteres contendo uma versão de visualização. E se essa versão de visualização não está sendo usada nas propriedades imageReference
, offer
, sku
ou version
.
Para obter mais informações sobre a propriedade imageReference
, confira Microsoft.Compute virtualMachines e Microsoft.Compute virtualMachineScaleSets.
No Bicep, use a regra do Linter – usar imagem de VM estável.
O exemplo a seguir é aprovado porque imageReference
é uma cadeia de caracteres que contém versão de visualização.
"properties": {
"storageProfile": {
"imageReference": "latest-preview"
}
}
O exemplo a seguir é reprovado quando a versão de visualização é usada em offer
, sku
ou version
.
"properties": {
"storageProfile": {
"imageReference": {
"publisher": "Canonical",
"offer": "UbuntuServer_preview",
"sku": "16.04-LTS-preview",
"version": "preview"
}
}
}
O exemplo a seguir é aprovado.
"storageProfile": {
"imageReference": {
"publisher": "Canonical",
"offer": "UbuntuServer",
"sku": "16.04-LTS",
"version": "latest"
}
}
Não usar a extensão ManagedIdentity
Nome do teste: ManagedIdentityExtension não deve ser usada
Não aplique a extensão ManagedIdentity
a uma máquina virtual. A extensão foi preterida em 2019 e não deve mais ser usada.
As saídas não podem incluir segredos
Nome do teste: saídas não devem conter segredos
Não inclua nenhum valor na seção outputs
que tenha o potencial de expor segredos. Por exemplo, parâmetros seguros do tipo secureString
ou secureObject
, ou funções de lista* como listKeys
.
A saída de um modelo é armazenada no histórico de implantação, o que possibilita que um usuário mal-intencionado encontre essas informações.
No Bicep, use a regra do Linter – as saídas não devem conter segredos.
O exemplo a seguir é reprovado porque ele inclui um parâmetro seguro em um valor de saída.
{
"$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'))]"
}
}
}
O exemplo a seguir reprova porque ele usa uma função list* nas saídas.
{
"$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')]"
}
}
}
Usar protectedSettings para segredos commandToExecute
Nome do teste: CommandToExecute deve usar ProtectedSettings para segredos
Para recursos com o tipo CustomScript
, use o protectedSettings
criptografado quando commandToExecute
incluir dados com segredo, como uma senha. Por exemplo, dados com segredo podem ser usados em parâmetros seguros do tipo secureString
ou secureObject
, funções de lista* como listKeys
ou scripts personalizados.
Não use dados com segredo no objeto settings
porque eles usam texto não criptografado. Para obter mais informações, confira Microsoft.Compute virtualMachines/extensions, Windows ou Linux.
No Bicep, use a regra do Linter – usar protectedSettings para segredos commandToExecute.
O exemplo a seguir é reprovado porque settings
usa commandToExecute
com um parâmetro seguro.
"parameters": {
"adminPassword": {
"type": "secureString"
}
}
...
"properties": {
"type": "CustomScript",
"settings": {
"commandToExecute": "[parameters('adminPassword')]"
}
}
O exemplo a seguir é reprovado porque settings
usa commandToExecute
com uma função listKeys
.
"properties": {
"type": "CustomScript",
"settings": {
"commandToExecute": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageName')), '2021-02-01')]"
}
}
O exemplo a seguir é aprovado porque protectedSettings
usa commandToExecute
com um parâmetro seguro.
"parameters": {
"adminPassword": {
"type": "secureString"
}
}
...
"properties": {
"type": "CustomScript",
"protectedSettings": {
"commandToExecute": "[parameters('adminPassword')]"
}
}
O exemplo a seguir é aprovado porque protectedSettings
usa commandToExecute
com uma função listKeys
.
"properties": {
"type": "CustomScript",
"protectedSettings": {
"commandToExecute": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageName')), '2021-02-01')]"
}
}
Usar versões recentes da API em funções de referência
Nome do Teste: apiVersions Deve Ser Recente em Funções de Referência
A versão da API usada em uma função de referência deve ser recente, e não uma versão de visualização. O teste avalia a versão da API em seu modelo em relação às versões do provedor de recursos no cache do kit de ferramentas. Uma versão da API com menos de dois anos a partir da data em que o teste foi executado é considerada recente.
Um aviso de que uma versão da API não foi encontrada apenas indica que a versão não está incluída no cache do kit de ferramentas. Usar a versão mais recente de uma API, que é recomendada, pode gerar o aviso.
Saiba mais sobre o cache do kit de ferramentas.
O exemplo a seguir é reprovado porque a versão da API tem mais de dois anos.
"outputs": {
"stgAcct": {
"type": "string",
"value": "[reference(resourceId(parameters('storageResourceGroup'), 'Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2019-06-01')]"
}
}
O exemplo a seguir é reprovado porque a versão da API é uma versão de visualização.
"outputs": {
"stgAcct": {
"type": "string",
"value": "[reference(resourceId(parameters('storageResourceGroup'), 'Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2020-08-01-preview')]"
}
}
O exemplo a seguir é aprovado porque a versão da API tem menos de dois anos e não é uma versão de visualização.
"outputs": {
"stgAcct": {
"type": "string",
"value": "[reference(resourceId(parameters('storageResourceGroup'), 'Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2021-02-01')]"
}
}
Usar o tipo e o nome em funções resourceId
Nome do teste: Os Recursos não Devem ser Ambíguos
Esse teste está desabilitado, mas a saída mostra que ele foi aprovado. A melhor prática é verificar seu modelo quanto aos seguintes critérios:
Um resourceId deve incluir um tipo e nome de recurso. Este teste encontra todas as funções de resourceId
do modelo e verifica se o recurso é usado no modelo com a sintaxe correta. Caso contrário, a função será considerada ambígua.
Por exemplo, uma função resourceId
é considerada ambígua:
- Quando um recurso não é encontrado no modelo e um grupo de recursos não é especificado.
- Se um recurso incluir uma condição e um grupo de recursos não for especificado.
- Se um recurso relacionado contiver alguns, mas não todos os segmentos de nome. Por exemplo, um recurso filho contém mais de um segmento de nome. Para obter mais informações, confira comentários sobre resourceId.
Usar o escopo interno para parâmetros seguros de implantação aninhada
Nome do teste: Parâmetros Seguros em Implantações Aninhadas
Use o objeto expressionEvaluationOptions
do modelo aninhado com escopo inner
para avaliar expressões que contêm parâmetros seguros do tipo secureString
ou secureObject
ou funções de lista* como listKeys
. Se o escopo outer
for usado, as expressões serão avaliadas em texto não criptografado dentro do escopo do modelo pai. O valor seguro fica visível para qualquer pessoa com acesso ao histórico de implantação. O valor padrão de expressionEvaluationOptions
é outer
.
Para obter mais informações sobre modelos aninhados, confira Implantações do Microsoft.Resources e Escopo de avaliação de expressão em modelos aninhados.
No Bicep, use a regra do Linter – proteger parâmetros na implantação aninhada.
O exemplo a seguir é reprovado porque expressionEvaluationOptions
usa o escopo outer
para avaliar parâmetros seguros ou funções list*
.
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2021-04-01",
"name": "nestedTemplate",
"properties": {
"expressionEvaluationOptions": {
"scope": "outer"
}
}
}
]
O exemplo a seguir é aprovado porque expressionEvaluationOptions
usa o escopo inner
para avaliar parâmetros seguros ou funções list*
.
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2021-04-01",
"name": "nestedTemplate",
"properties": {
"expressionEvaluationOptions": {
"scope": "inner"
}
}
}
]
Próximas etapas
- Para saber mais sobre como executar o kit de ferramentas de teste, consulte Usar o kit de ferramentas do modelo do ARM.
- Para conferir um módulo do Learn que aborda o uso do kit de ferramentas de teste, consulteVisualizar alterações e validar recursos do Azure usando o teste de hipóteses e o kit de ferramentas de teste do modelo do ARM.
- Para testar arquivos de parâmetros, confira Casos de teste de arquivos de parâmetros.
- Para testes createUiDefinition, confira Casos de teste para createUiDefinition.json.
- Para saber mais sobre testes para todos os arquivos, consulte Casos de teste para todos os arquivos.