Casos de teste para modelos ARM
Este artigo descreve testes que são executados com o kit de ferramentas de teste de modelo para modelos do Azure Resource Manager (modelos ARM). Ele fornece exemplos que passam ou reprovam no teste e inclui o nome de cada teste. Para obter mais informações sobre como executar testes ou como executar um teste específico, consulte Parâmetros de teste.
Usar esquema correto
Nome do teste: O esquema DeploymentTemplate está correto
Em seu modelo, você deve especificar um valor de esquema válido.
O exemplo a seguir falha 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 2015-01-01
do esquema foi preterida e não foi mantida.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
}
O exemplo a seguir passa usando um esquema válido.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
}
A propriedade do schema
modelo deve ser definida como 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
Devem ser utilizados parâmetros declarados
Nome do teste: Os parâmetros devem ser referenciados
Este teste localiza parâmetros que não são usados no modelo ou parâmetros 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 modelo porque você não precisa fornecer valores desnecessários.
No Bicep, use a regra de Linter - sem parâmetros não utilizados.
O exemplo a seguir falha porque a expressão que faz referência a um parâmetro está faltando o colchete à esquerda ([
).
"resources": [
{
"location": " parameters('location')]"
}
]
O exemplo a seguir passa porque a expressão é válida.
"resources": [
{
"location": "[parameters('location')]"
}
]
Os parâmetros seguros não podem ter padrão codificado
Nome do teste: Parâmetros de cadeia de caracteres seguros não podem ter padrão
Não forneça um valor padrão codificado para um parâmetro seguro em seu modelo. Um parâmetro seguro pode ter uma cadeia de caracteres vazia como um 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 pode ser descoberto por qualquer pessoa que possa acessar o modelo ou o histórico de implantação.
No Bicep, use a regra Linter - parâmetro seguro padrão.
O exemplo a seguir falha.
"parameters": {
"adminPassword": {
"defaultValue": "HardcodedPassword",
"type": "secureString"
}
}
O próximo exemplo passa.
"parameters": {
"adminPassword": {
"type": "secureString"
}
}
O exemplo a seguir passa porque a newGuid
função é usada.
"parameters": {
"secureParameter": {
"type": "secureString",
"defaultValue": "[newGuid()]"
}
}
As URLs de ambiente não podem ser codificadas
Nome do teste: DeploymentTemplate não deve conter Uri codificado
Não codifice URLs de ambiente em seu modelo. Em vez disso, use a função de ambiente para obter dinamicamente essas URLs durante a implantação. Para obter uma lista dos hosts de URL bloqueados, consulte o caso de teste.
No Bicep, use a regra Linter - sem URL de ambiente codificado.
O exemplo a seguir falha porque a URL é codificada.
"variables":{
"AzureURL":"https://management.azure.com"
}
O teste também falha quando usado com concat ou uri.
"variables":{
"AzureSchemaURL1": "[concat('https://','gallery.azure.com')]",
"AzureSchemaURL2": "[uri('gallery.azure.com','test')]"
}
O exemplo a seguir passa.
"variables": {
"AzureSchemaURL": "[environment().gallery]"
}
Localização usa parâmetro
Nome do teste: O local não deve ser codificado
Para definir o local de um recurso, seus modelos devem ter um parâmetro nomeado location
com o tipo definido como string
. No modelo principal, azuredeploy.json 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 location não deve ter um local padrão.
Os usuários de modelo podem ter acesso limitado a regiões onde podem criar recursos. Um local de recurso codificado pode impedir que os usuários criem um recurso. A "[resourceGroup().location]"
expressão pode bloquear usuários se o grupo de recursos tiver sido 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 location
parâmetro padrão para o local do grupo de recursos, os usuários podem usar o valor padrão quando 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 falha porque o recurso está definido como resourceGroup().location
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 location
parâmetro, mas falha porque o parâmetro assume como padrão um local codificado.
{
"$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 passa quando o modelo é usado como o modelo principal. Crie um parâmetro que tenha como padrão o local do grupo de recursos, mas permita 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": {}
}
Nota
Se o exemplo anterior for usado como um modelo vinculado, o teste falhará. Quando usado como um modelo vinculado, remova o valor padrão.
Os recursos devem ter localização
Nome do teste: Os recursos devem ter localização
O local de um recurso deve ser definido como uma expressão de modelo ou global
. A expressão de modelo normalmente usaria o location
parâmetro descrito em Location uses parameter.
No Bicep, use a regra Linter - sem locais codificados.
O exemplo a seguir falha porque o 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 passa 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 passa porque o location
parâmetro 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: O tamanho da VM deve ser um parâmetro
Não codifice o hardwareProfile
arquivo vmSize
. O teste falha quando o hardwareProfile
é omitido ou contém um valor codificado. Forneça um parâmetro para que os usuários do seu modelo possam modificar o tamanho da máquina virtual implantada. Para obter mais informações, consulte Microsoft.Compute virtualMachines.
O exemplo a vmSize
seguir falha porque o hardwareProfile
do objeto é um valor codificado.
"resources": [
{
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "2020-12-01",
"name": "demoVM",
"location": "[parameters('location')]",
"properties": {
"hardwareProfile": {
"vmSize": "Standard_D2_v3"
}
}
}
]
O exemplo passa 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 para vmSize
para fazer 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 min e max são números
Nome do teste: Min e valor 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 falha.
O exemplo a seguir falha porque minValue
e maxValue
são strings.
"exampleParameter": {
"type": "int",
"minValue": "0",
"maxValue": "10"
}
O exemplo a seguir falha porque somente minValue
é usado.
"exampleParameter": {
"type": "int",
"minValue": 0
}
O exemplo a seguir passa 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. Para passar neste ensaio, devem ser preenchidas as seguintes condições:
- 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 um ou"[deployment().properties.templateLink.uri]"
o URL de repositório bruto para seu valor padrão._artifactsLocationSasToken
deve ser umsecureString
._artifactsLocationSasToken
só pode ter uma cadeia de caracteres vazia para seu valor padrão._artifactsLocationSasToken
não pode ter um valor padrão em um modelo aninhado.
No Bicep, use a regra de Linter - parâmetros de artefatos.
Variáveis declaradas devem ser usadas
Nome do teste: As variáveis devem ser referenciadas
Este teste localiza variáveis que não são usadas no modelo ou 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.
As variáveis que usam o copy
elemento para iterar valores devem ser referenciadas. Para obter mais informações, consulte Iteração variável em modelos ARM.
No Bicep, use a regra de Linter - sem variáveis não utilizadas.
O exemplo a seguir falha porque a variável que usa o copy
elemento 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 falha porque a expressão que faz referência a uma variável está faltando o colchete à esquerda ([
).
"outputs": {
"outputVariable": {
"type": "string",
"value": " variables('varExample')]"
}
}
O exemplo a seguir passa 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 passa porque a expressão é válida.
"outputs": {
"outputVariable": {
"type": "string",
"value": "[variables('varExample')]"
}
}
Variável dinâmica não deve usar concat
Nome do teste: Referências de variáveis dinâmicas 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 passa. A variável é definida dinamicamente durante a currentImage
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 da API
Nome do teste: apiVersions deve ser recente
A versão da API para cada recurso deve usar uma versão recente codificada como uma 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 utilize uma versão de pré-visualização quando estiver disponível uma versão mais recente.
Um aviso de que uma versão da API não foi encontrada indica apenas que a versão não está incluída no cache do kit de ferramentas. Usar a versão mais recente de uma API, o que é recomendado, pode gerar o aviso.
Saiba mais sobre o cache do kit de ferramentas.
No Bicep, use a regra Linter - use versões recentes da API.
O exemplo a seguir falha 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 falha 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 passa porque é uma versão recente que não é uma versão de visualização.
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2021-02-01",
"name": "storageaccount1",
"location": "[parameters('location')]"
}
]
Usar a versão da API codificada
Nome do teste: Provedores apiVersions não é permitido
A versão da API para um tipo de recurso determina quais propriedades estão disponíveis. Forneça uma versão de API codificada em seu modelo. Não recupere uma versão da API determinada durante a implantação porque você não saberá quais propriedades estão disponíveis.
O exemplo a seguir falha.
"resources": [
{
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "[providers('Microsoft.Compute', 'virtualMachines').apiVersions[0]]",
...
}
]
O exemplo a seguir passa.
"resources": [
{
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "2020-12-01",
...
}
]
As propriedades não podem estar vazias
Nome do teste: O modelo não deve conter espaços em branco
Não codifice propriedades para um valor vazio. Os valores vazios incluem cadeias de caracteres, objetos ou matrizes nulos e vazios. Se uma propriedade estiver definida como um valor vazio, remova-a do modelo. Você pode definir uma propriedade como um valor vazio durante a implantação, como por meio de um parâmetro.
A template
propriedade em um modelo aninhado pode incluir propriedades vazias. Para obter mais informações sobre modelos aninhados, consulte Implantações Microsoft.Resources.
O exemplo a seguir falha porque há propriedades vazias.
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2021-01-01",
"name": "storageaccount1",
"location": "[parameters('location')]",
"sku": {},
"kind": ""
}
]
O exemplo a seguir passa 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 de recurso
Nome do teste: IDs devem ser derivados de ResourceIDs
Ao especificar uma ID de 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 um ID de recurso.
No Bicep, use a regra Linter - use funções de ID de recurso.
O exemplo a seguir falha.
"networkSecurityGroup": {
"id": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/networkSecurityGroups/', variables('networkSecurityGroupName'))]"
}
O próximo exemplo passa.
"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 de recursos, não use funções desnecessárias para parâmetros opcionais. Por padrão, a função resourceId usa a assinatura atual e o grupo de recursos. Você não precisa fornecer esses valores.
O exemplo a seguir falha porque você não precisa fornecer a ID da assinatura atual e o nome do grupo de recursos.
"networkSecurityGroup": {
"id": "[resourceId(subscription().subscriptionId, resourceGroup().name, 'Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
}
O próximo exemplo passa.
"networkSecurityGroup": {
"id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
}
Este teste aplica-se a:
Para reference
e list*
, o teste falha quando você usa concat
para construir a ID do recurso.
depende das melhores práticas
Nome do teste: DependsOn Best Practices
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 um recurso implantado condicionalmente, defina a dependência como faria com qualquer recurso. Quando um recurso condicional não é implantado, o Azure Resource Manager o remove automaticamente das dependências necessárias.
O dependsOn
elemento não pode começar com uma função concat .
No Bicep, use a regra Linter - sem entradas desnecessárias.
O exemplo a seguir falha porque contém uma if
função.
"dependsOn": [
"[if(equals(parameters('newOrExisting'),'new'), variables('storageAccountName'), '')]"
]
O exemplo a seguir falha porque começa com concat
.
"dependsOn": [
"[concat(variables('storageAccountName'))]"
]
O exemplo a seguir passa.
"dependsOn": [
"[variables('storageAccountName')]"
]
Implantações aninhadas ou vinculadas não podem usar depuração
Nome do teste: Os recursos de implantação não devem ser depurados
Ao definir um modelo aninhado ou vinculado com o tipo de recurso, você pode habilitar a Microsoft.Resources/deployments
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, desative a depuração. Você pode remover o debugSetting
objeto ou alterar a detailLevel
propriedade para none
.
O exemplo a seguir falha.
"debugSetting": {
"detailLevel": "requestContent"
}
O exemplo a seguir passa.
"debugSetting": {
"detailLevel": "none"
}
Os nomes de usuário Admin não podem ter valor literal
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 fazer referência ao valor do parâmetro.
No Bicep, use a regra Linter - o nome de usuário admin não deve ser literal.
O exemplo a seguir falha com um valor literal.
"osProfile": {
"adminUserName": "myAdmin"
}
O exemplo a seguir passa com uma expressão.
"osProfile": {
"adminUsername": "[parameters('adminUsername')]"
}
Usar a imagem de VM mais recente
Nome do teste: As imagens VM devem usar a versão mais recente
Este teste está desativado, mas a saída mostra que ele passou. A melhor prática é verificar o seu modelo para os seguintes critérios:
Se o seu modelo incluir uma máquina virtual com uma imagem, certifique-se de que está a utilizar a versão mais recente da imagem.
No Bicep, use a regra Linter - use uma imagem de VM estável.
Usar imagens de VM estáveis
Nome do teste: Máquinas virtuais não devem ser visualizadas
As máquinas virtuais não devem usar imagens de visualização. O teste verifica se o storageProfile
imageReference
não usa uma cadeia de caracteres que contém visualização. E essa visualização não é usada nas imageReference
propriedades offer
, sku
ou version
.
Para obter mais informações sobre a imageReference
propriedade, consulte Microsoft.Compute virtualMachines e Microsoft.Compute virtualMachineScaleSets.
No Bicep, use a regra Linter - use uma imagem de VM estável.
O exemplo a seguir falha porque imageReference
é uma cadeia de caracteres que contém visualização.
"properties": {
"storageProfile": {
"imageReference": "latest-preview"
}
}
O exemplo a seguir falha quando a 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 passa.
"storageProfile": {
"imageReference": {
"publisher": "Canonical",
"offer": "UbuntuServer",
"sku": "16.04-LTS",
"version": "latest"
}
}
Não use a extensão ManagedIdentity
Nome do teste: ManagedIdentityExtension não deve ser usado
Não aplique a ManagedIdentity
extensão 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: As saídas não devem conter segredos
Não inclua nenhum valor na outputs
seção que potencialmente exponha 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, para que um usuário mal-intencionado possa encontrar essas informações.
No Bicep, use a regra Linter - as saídas não devem conter segredos.
O exemplo a seguir falha porque 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 falha porque 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')]"
}
}
}
Use protectedSettings para commandToExecute secrets
Nome do teste: CommandToExecute deve usar ProtectedSettings para segredos
Para recursos com o tipo CustomScript
, use o criptografado protectedSettings
quando commandToExecute
incluir dados secretos, como uma senha. Por exemplo, os dados secretos 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 secretos settings
no objeto porque ele usa texto não criptografado. Para obter mais informações, consulte Microsoft.Compute virtualMachines/extensions, Windows ou Linux.
No Bicep, use a regra Linter - use protectedSettings para commandToExecute secrets.
O exemplo a seguir falha porque settings
usa commandToExecute
com um parâmetro seguro.
"parameters": {
"adminPassword": {
"type": "secureString"
}
}
...
"properties": {
"type": "CustomScript",
"settings": {
"commandToExecute": "[parameters('adminPassword')]"
}
}
O exemplo a seguir falha porque settings
usa commandToExecute
com uma listKeys
função.
"properties": {
"type": "CustomScript",
"settings": {
"commandToExecute": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageName')), '2021-02-01')]"
}
}
O exemplo a seguir passa porque protectedSettings
usa commandToExecute
com um parâmetro seguro.
"parameters": {
"adminPassword": {
"type": "secureString"
}
}
...
"properties": {
"type": "CustomScript",
"protectedSettings": {
"commandToExecute": "[parameters('adminPassword')]"
}
}
O exemplo a seguir passa porque protectedSettings
usa commandToExecute
com uma listKeys
função.
"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 indica apenas que a versão não está incluída no cache do kit de ferramentas. Usar a versão mais recente de uma API, o que é recomendado, pode gerar o aviso.
Saiba mais sobre o cache do kit de ferramentas.
O exemplo a seguir falha 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 falha 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 passa 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 tipo e nome em funções resourceId
Nome do teste: Os recursos não devem ser ambíguos
Este teste está desativado, mas a saída mostra que ele passou. A melhor prática é verificar o seu modelo para os seguintes critérios:
Um resourceId deve incluir um tipo de recurso e um nome de recurso. Este teste localiza todas as resourceId
funções do modelo e verifica se o recurso é usado no modelo com a sintaxe correta. Caso contrário, a função é considerada ambígua.
Por exemplo, uma resourceId
função é 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, consulte observações 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 do modelo aninhado com escopo para avaliar expressões que contenham parâmetros seguros de funções do tipo secureString
ou secureObject
lista*, como listKeys
.inner
expressionEvaluationOptions
Se o escopo for usado, as outer
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, consulte Microsoft.Resources deployments and Expression evaluation scope in nested templates.
No Bicep, use a regra Linter - parâmetros seguros na implantação aninhada.
O exemplo a seguir falha porque expressionEvaluationOptions
usa outer
o escopo para avaliar parâmetros ou list*
funções seguras.
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2021-04-01",
"name": "nestedTemplate",
"properties": {
"expressionEvaluationOptions": {
"scope": "outer"
}
}
}
]
O exemplo a seguir passa porque expressionEvaluationOptions
usa inner
o escopo para avaliar parâmetros ou list*
funções seguras.
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2021-04-01",
"name": "nestedTemplate",
"properties": {
"expressionEvaluationOptions": {
"scope": "inner"
}
}
}
]
Próximos passos
- Para saber mais sobre como executar o kit de ferramentas de teste, consulte Usar kit de ferramentas de teste de modelo ARM.
- Para obter um módulo do Learn que aborda o uso do kit de ferramentas de teste, consulte Visualizar alterações e validar recursos do Azure usando hipóteses e o kit de ferramentas de teste de modelo ARM.
- Para testar arquivos de parâmetro, consulte Casos de teste para arquivos de parâmetro.
- Para testes createUiDefinition, consulte Casos de teste para createUiDefinition.json.
- Para saber mais sobre testes para todos os arquivos, consulte Casos de teste para todos os arquivos.