Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этой статье описываются тесты, выполняемые с помощью набора средств тестирования template для шаблонов Azure Resource Manager (шаблоны ARM). Здесь приводятся примеры, которые успешно проходят или не проходят тест, с указанием имени каждого теста. Дополнительные сведения о том, как выполнять тесты или как выполнять определенный тест, см. в разделе "Параметры теста".
Использование правильной схемы
Имя теста: Схема DeploymentTemplate правильная
В шаблоне необходимо указать допустимое значение схемы.
Следующий пример не проходит тест, так как схема является недопустимой.
{
"$schema": "https://schema.management.azure.com/schemas/2019-01-01/deploymentTemplate.json#",
}
Следующий пример отображает предупреждение, так как версия схемы 2015-01-01 является нерекомендуемой и не поддерживается.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
}
Следующий пример проходит тест, используя правильную схему.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
}
Свойству schema в шаблоне должна быть задана одна из следующих схем:
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
Должны использоваться объявленные параметры
Имя теста: Параметры должны быть указаны
Этот тест находит параметры, которые не используются в шаблоне или имеют недопустимые выражения.
Чтобы сократить путаницу в шаблоне, удалите все параметры, которые определены, но не используются. Устранение неиспользуемых параметров упрощает развертывания шаблона, избавляя вас от необходимости вводить ненужные значения.
В Bicep используйте правило Linter — отсутствие неиспользуемых параметров.
Следующий шаблон не проходит тест, так как в выражении со ссылкой на параметр отсутствует открывающая квадратная скобка ([).
"resources": [
{
"location": " parameters('location')]"
}
]
Следующий пример успешно выполняется, потому что выражение является допустимым.
"resources": [
{
"location": "[parameters('location')]"
}
]
Защищенные параметры не могут иметь прописанные в коде значения по умолчанию
Имя теста: Строковые параметры безопасности не могут иметь значения по умолчанию
Не задавайте жестко запрограммированное значение по умолчанию для параметра безопасности в шаблоне. Защищенный параметр может иметь в качестве значения по умолчанию пустую строку или использовать в выражении функцию newGuid.
Типы secureString и secureObject используются для параметров с конфиденциальными значениями, например для паролей. Если параметр использует безопасный тип, значение параметра не заносится в журнал и не сохраняется в журнале развертывания. Это действие не позволит злоумышленнику обнаружить конфиденциальное значение.
Если вы предоставляете значение по умолчанию, оно может быть обнаружено любым пользователем, имеющим доступ к шаблону или журналу развертывания.
В Bicep используйте правило Linter — безопасный параметр по умолчанию.
В следующем примере неудается.
"parameters": {
"adminPassword": {
"defaultValue": "HardcodedPassword",
"type": "secureString"
}
}
Пример ниже проходит тест.
"parameters": {
"adminPassword": {
"type": "secureString"
}
}
Следующий пример проходит тест, так как в нем используется функция newGuid.
"parameters": {
"secureParameter": {
"type": "secureString",
"defaultValue": "[newGuid()]"
}
}
URL-адреса окружения не могут быть жестко закодированы
Имя теста: DeploymentTemplate не должен содержать жестко заданный URI
Не следует жёстко прописывать URL-адреса окружения в шаблоне. Вместо этого используйте функцию environment для динамического получения URL-адресов во время развертывания. Список заблокированных хостов URL см. в test case.
В Bicep используйте правило Linter — без жестко заданного URL среды.
Следующий пример не проходит тест, так как URL-адрес прописан в коде.
"variables":{
"AzureURL":"https://management.azure.com"
}
Тест также завершается ошибкой при использовании concat или uri.
"variables":{
"AzureSchemaURL1": "[concat('https://','gallery.azure.com')]",
"AzureSchemaURL2": "[uri('gallery.azure.com','test')]"
}
Следующий пример проходит.
"variables": {
"AzureSchemaURL": "[environment().gallery]"
}
В расположении используется параметр
Имя теста: Расположение не должно быть жестко запрограммировано
Чтобы задать расположение ресурса, в шаблонах нужно указать параметр location с типом string. В основном шаблоне (azuredeploy.json или mainTemplate.json) этот параметр может по умолчанию содержать расположение группы ресурсов. В связанных или вложенных шаблонах параметр location не должен содержать расположение по умолчанию.
Пользователи шаблонов могут иметь ограниченный доступ к регионам, в которых они могут создавать ресурсы. Прописанное в коде расположение ресурса может привести к тому, что пользователь не сможет создать ресурс. Выражение "[resourceGroup().location]" будет блокировать пользователей, если группа ресурсов создана в недоступном для них регионе. Заблокированные пользователи не смогут использовать шаблон.
Если указать параметр location, в котором по умолчанию задано расположение группы ресурсов, пользователи смогут использовать значение по умолчанию, если это удобно, или указать другое расположение.
В Bicep используйте правило Linter — нет выражений расположения за пределами значений по умолчанию.
Следующий пример не выполняется, так как значение ресурса location установлено на 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": "2025-06-01",
"name": "storageaccount1",
"location": "[resourceGroup().location]",
"kind": "StorageV2",
"sku": {
"name": "Premium_LRS",
}
}
]
}
Следующий пример использует параметр location, но не проходит тест, так как этот параметр в качестве значения по умолчанию использует прописанное в коде расположение.
{
"$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": "2025-06-01",
"name": "storageaccount1",
"location": "[parameters('location')]",
"kind": "StorageV2",
"sku": {
"name": "Premium_LRS",
}
}
],
"outputs": {}
}
Следующий пример проходит этот тест, если шаблон используется как основной. Создайте параметр, который в качестве значения по умолчанию использует расположение группы ресурсов, но позволяет пользователям указать другое значение.
{
"$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": "2025-06-01",
"name": "storageaccount1",
"location": "[parameters('location')]",
"kind": "StorageV2",
"sku": {
"name": "Premium_LRS",
}
}
],
"outputs": {}
}
Примечание.
Если предыдущий пример используется в качестве связанного шаблона, он не пройдет тест. При использовании в качестве связанного шаблона удалите значение по умолчанию.
Ресурсы должны иметь расположение
Имя теста: Ресурсы должны иметь расположение
Для расположения ресурса должно быть задано выражение шаблона или global. В выражении шаблона обычно используется параметр location, описанный в разделе В расположении используется параметр.
В Bicep используйте правило Linter — без жестко закодированных расположений.
Следующий пример не проходит тест, так как location не является выражением или 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": "2025-06-01",
"name": "storageaccount1",
"location": "westus",
"kind": "StorageV2",
"sku": {
"name": "Premium_LRS",
}
}
],
"outputs": {}
}
Следующий пример проходит тест, так как ресурс location имеет значение 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": "2025-06-01",
"name": "storageaccount1",
"location": "global",
"kind": "StorageV2",
"sku": {
"name": "Premium_LRS",
}
}
],
"outputs": {}
}
Следующий пример также проходит тест, так как параметр location использует выражение. Ресурс location использует значение выражения.
{
"$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": "2025-06-01",
"name": "storageaccount1",
"location": "[parameters('location')]",
"kind": "StorageV2",
"sku": {
"name": "Premium_LRS",
}
}
],
"outputs": {}
}
Размер виртуальной машины использует параметр
Имя теста: Размер виртуальной машины должен быть параметром
Не жёстко кодируйте hardwareProfile объекта vmSize. Этот тест завершается ошибкой, если hardwareProfile пропускается или содержит прописанное в коде значение. Предоставьте параметр, чтобы пользователи шаблона могли изменять размер развернутой виртуальной машины. См. дополнительные сведения о Microsoft.Compute virtualMachines.
Следующий пример не проходит тест, так как у объекта hardwareProfile параметр vmSize имеет прописанное в коде значение.
"resources": [
{
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "2025-04-01",
"name": "demoVM",
"location": "[parameters('location')]",
"properties": {
"hardwareProfile": {
"vmSize": "Standard_D2_v3"
}
}
}
]
Этот пример проходит тест, если параметр задает значение для vmSize:
"parameters": {
"vmSizeParameter": {
"type": "string",
"defaultValue": "Standard_D2_v3",
"metadata": {
"description": "Size for the virtual machine."
}
}
}
Затем hardwareProfile использует выражение для vmSize, чтобы ссылаться на значение этого параметра.
"resources": [
{
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "2025-04-01",
"name": "demoVM",
"location": "[parameters('location')]",
"properties": {
"hardwareProfile": {
"vmSize": "[parameters('vmSizeParameter')]"
}
}
}
]
Минимальное и максимальное значения являются числами
Имя теста: Минимальное и максимальное значения являются числами
Если вы задаете параметр с помощью minValue и maxValue, их необходимо указать в виде чисел.
minValue и maxValue всегда используются вместе, иначе тест завершается ошибкой.
Следующий пример не проходит тест, так как minValue и maxValue имеют строковые значения.
"exampleParameter": {
"type": "int",
"minValue": "0",
"maxValue": "10"
}
Следующий пример не проходит тест, так как используется только minValue.
"exampleParameter": {
"type": "int",
"minValue": 0
}
Следующий пример проходит тест, так как minValue и maxValue имеют числовые значения.
"exampleParameter": {
"type": "int",
"minValue": 0,
"maxValue": 10
}
Параметр артефактов определен правильно
Имя теста: Параметр артефактов
При включении параметров для _artifactsLocation и _artifactsLocationSasToken используйте правильные значения по умолчанию и типы. Для прохождения этого теста должны быть выполнены следующие условия.
- Если вы предоставляете один параметр, необходимо указать и другой.
-
_artifactsLocationдолжен бытьstring. -
_artifactsLocationдолжен иметь значение по умолчанию в основном шаблоне. -
_artifactsLocationне может иметь значение по умолчанию во вложенном шаблоне. -
_artifactsLocationдолжен иметь значение по умолчанию либо"[deployment().properties.templateLink.uri]", либо URL-адрес сырого репозитория. -
_artifactsLocationSasTokenдолжен бытьsecureString. -
_artifactsLocationSasTokenможет иметь в качестве значения по умолчанию только пустую строку. -
_artifactsLocationSasTokenне может иметь значение по умолчанию во вложенном шаблоне.
В Bicep используйте правило Linter — параметры артефактов.
Необходимо использовать объявленные переменные
Имя теста: Переменные должны быть указаны по ссылке
Этот тест ищет переменные, которые не используются в шаблоне или используются в недопустимом выражении. Чтобы сократить путаницу в шаблоне, удалите все переменные, которые определены, но не используются.
Переменные, которые используют элемент copy для перебора значений, должны иметь ссылки. Дополнительные сведения см. в статье Итерация переменной в шаблонах ARM.
В Bicep используйте правило Linter — неиспользуемые переменные.
Следующий пример не проходит тест, так как в нем нет ссылок на переменную, которая использует элемент 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": {}
}
Следующий шаблон не проходит тест, так как в выражении со ссылкой на переменную отсутствует открывающая квадратная скобка ([).
"outputs": {
"outputVariable": {
"type": "string",
"value": " variables('varExample')]"
}
}
Следующий пример проходит тест, так как в 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')]"
}
}
}
Следующий пример успешно выполняется, потому что выражение является допустимым.
"outputs": {
"outputVariable": {
"type": "string",
"value": "[variables('varExample')]"
}
}
Динамическая переменная не должна использовать Concat
Имя теста: Ссылки на динамические переменные не должны использовать Concat
Иногда необходимо динамически создать переменную на основе значения другой переменной или параметра. Не используйте функцию concat при задании значения. Вместо этого следует использовать объект, в котором есть доступные параметры, и динамически получать одно из свойств объекта во время развертывания.
Следующий пример проходит. Переменная currentImage задается динамически во время развертывания.
{
"$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')]"
}
}
}
Использование последней версии API
Имя теста: Значением apiVersions должна быть последняя версия
Версия API для каждого ресурса должна указывать свежую версию, прописанную в коде в виде строки. Этот тест оценивает версию API в вашем шаблоне, сравнивая её с версиями поставщика ресурсов в кэше инструментария. Свежей считается версия API, созданная менее чем за два года до даты выполнения теста. Не используйте предварительную версию, если доступна более свежая.
Предупреждение о том, что версия API не найдена, указывает, что версия не включена в кэш набора инструментов. Предупреждение может возникнуть при использовании самой последней и рекомендуемой версии API.
Дополнительные сведения о кэше toolkit.
В Bicep используйте правило Linter— используйте последние версии API.
Следующий пример не проходит тест, так как версия API в нем старше двух лет.
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2025-06-01",
"name": "storageaccount1",
"location": "[parameters('location')]"
}
]
Следующий пример не работает, так как используется предварительная версия, когда доступна более новая версия.
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2020-08-01-preview",
"name": "storageaccount1",
"location": "[parameters('location')]"
}
]
Следующий пример проходит тест, так как используется свежая версия, которая не является предварительной.
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2025-06-01",
"name": "storageaccount1",
"location": "[parameters('location')]"
}
]
Использование прописанной в коде версии API
Имя теста: apiVersions провайдеров не разрешены
Версия API для типа ресурсов определяет доступные свойства. Укажите в шаблоне жестко запрограммированную версию API. Не извлекайте версию API, которая определяется в процессе развертывания, так как не известно, какие свойства доступны.
В следующем примере неудается.
"resources": [
{
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "[providers('Microsoft.Compute', 'virtualMachines').apiVersions[0]]",
...
}
]
Следующий пример проходит.
"resources": [
{
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "2025-04-01",
...
}
]
Свойства не могут быть пустыми
Имя теста: В шаблоне не должно быть пустых свойств
Не прописывайте в коде для свойств пустое значение. Пустыми являются значения NULL, пустые строки, объекты или массивы. Если свойству присвоено пустое значение, удалите это свойство из шаблона. Но вы можете присвоить свойству пустое значение во время развертывания, например с помощью параметра.
Свойство template во вложенном шаблоне может содержать пустые свойства. Для получения дополнительной информации о вложенных шаблонах см. раздел Развертывания Microsoft.Resources.
Следующий пример не проходит тест, так как в нем есть пустые свойства.
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2025-06-01",
"name": "storageaccount1",
"location": "[parameters('location')]",
"sku": {},
"kind": ""
}
]
Следующий пример проходит тест, так как свойства в нем содержат значения.
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2025-06-01",
"name": "storageaccount1",
"location": "[parameters('location')]",
"sku": {
"name": "Standard_LRS",
},
"kind": "Storage"
}
]
Использование функций идентификатора ресурса
Имя теста: Идентификаторы должны быть производными от идентификаторов ресурсов
При указании идентификатора ресурса используйте одну из функций идентификатора ресурса. Допустимые функции:
Не используйте функцию concat для создания идентификатора ресурса.
В Bicep используйте правило Linter— используйте функции идентификатора ресурса.
В следующем примере неудается.
"networkSecurityGroup": {
"id": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/networkSecurityGroups/', variables('networkSecurityGroupName'))]"
}
Пример ниже проходит тест.
"networkSecurityGroup": {
"id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
}
Функция ResourceId имеет правильные параметры
Имя теста: Идентификаторы ресурсов не должны содержать
При создании идентификаторов ресурсов не используйте ненужные функции для необязательных параметров. По умолчанию функция resourceId использует текущую подписку и группу ресурсов. Указывать эти значения не нужно.
Следующий пример не проходит тест, так как не нужно указывать идентификатор текущей подписки и имя группы ресурсов.
"networkSecurityGroup": {
"id": "[resourceId(subscription().subscriptionId, resourceGroup().name, 'Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
}
Пример ниже проходит тест.
"networkSecurityGroup": {
"id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
}
Этот тест применяется к:
Для reference и list* тест завершается ошибкой при использовании concat для создания идентификатора ресурса.
Рекомендуемые практики для dependsOn
Имя теста: Рекомендации по DependsOn
При задании зависимостей развертывания не используйте функцию if для проверки условия. Если один ресурс зависит от ресурса, который развертывается условно, установите зависимость так же, как и для любого другого ресурса. Если условный ресурс не развернут, Azure Resource Manager автоматически удаляет его из необходимых зависимостей.
Элемент dependsOn не может начинаться с функции concat.
В Bicep используйте правило Linter — никаких лишних зависимостей dependsOn.
Следующий пример не проходит тест, так как содержит функцию if.
"dependsOn": [
"[if(equals(parameters('newOrExisting'),'new'), variables('storageAccountName'), '')]"
]
Следующий пример не проходит тест, так как начинается с concat.
"dependsOn": [
"[concat(variables('storageAccountName'))]"
]
Следующий пример проходит.
"dependsOn": [
"[variables('storageAccountName')]"
]
Вложенные или связанные развертывания не могут использовать отладку
Имя теста: Ресурсы развертывания не должны быть в режиме отладки
Если вы определяете вложенный или связанный шаблон с типом ресурса Microsoft.Resources/deployments, для него можно включить отладку. Отладка используется, когда необходимо протестировать шаблон, но это может привести к раскрытию конфиденциальной информации. Перед развертыванием шаблона в рабочей среде отключите отладку. Вы можете просто удалить объект debugSetting или указать для его свойства detailLevel значение none.
В следующем примере неудается.
"debugSetting": {
"detailLevel": "requestContent"
}
Следующий пример проходит.
"debugSetting": {
"detailLevel": "none"
}
Имя пользователя администратора не может быть литеральным значением
Имя теста: adminUsername не должен быть задан буквально
Если вы задаете значение adminUserName, не используйте литеральное значение. Создайте параметр для имени пользователя и укажите выражение со ссылкой на значение этого параметра.
В Bicep используйте правило Linter — имя пользователя администратора не должно быть литеральным.
Следующий пример не проходит тест, так как содержит литеральное значение.
"osProfile": {
"adminUserName": "myAdmin"
}
Следующий пример проходит тест так как используется выражение.
"osProfile": {
"adminUsername": "[parameters('adminUsername')]"
}
Использование последней версии образа виртуальной машины
Имя теста: Должна использоваться последняя версия образа виртуальной машины
Этот тест отключен, но в выходных данных отображается как пройденный. Мы рекомендуем проверить шаблон на соответствие следующим критериям:
Убедитесь, что если в шаблоне есть виртуальная машина с образом, она использует последнюю версию образа.
В Bicep используйте правило Linter — используйте стабильный образ виртуальной машины.
Использование стабильных образов виртуальных машин
Имя теста: Virtual Machines не должно быть предварительной версии
Виртуальные машины не должны использовать предварительные образы. Этот тест проверяет storageProfile, чтобы убедиться, что imageReference не использует строку, содержащую preview. в подстроке preview не используется в свойствах imageReference, offer, sku или version.
Дополнительные сведения о свойстве imageReference см. в документации по Microsoft.Compute virtualMachines и Microsoft.Compute virtualMachineScaleSets.
В Bicep используйте правило Linter — используйте стабильный образ виртуальной машины.
Следующий пример не проходит тест, так как imageReference является строкой и содержит preview.
"properties": {
"storageProfile": {
"imageReference": "latest-preview"
}
}
Следующий пример терпит сбой, когда preview используется в offer, sku или version.
"properties": {
"storageProfile": {
"imageReference": {
"publisher": "Canonical",
"offer": "UbuntuServer_preview",
"sku": "16.04-LTS-preview",
"version": "preview"
}
}
}
Следующий пример проходит.
"storageProfile": {
"imageReference": {
"publisher": "Canonical",
"offer": "UbuntuServer",
"sku": "16.04-LTS",
"version": "latest"
}
}
Не использовать расширение ManagedIdentity
Имя теста: Нельзя использовать расширение ManagedIdentity
Не применяйте расширение ManagedIdentity к виртуальной машине. Расширение было признано устаревшим в 2019 г. и больше не должно использоваться.
Выходные данные не могут содержать секреты
Имя теста: Выходные данные не должны содержать секреты
Не включайте в раздел outputs значения, которые могут раскрыть секреты. Например, защитите все параметры с типом secureString или secureObject, а также функции list*, например listKeys.
Выходные данные шаблона хранятся в журнале развертывания, поэтому злоумышленник может найти эту информацию.
В Bicep используйте правило Linter— выходные данные не должны содержать секреты.
Следующий пример не проходит тест, так как в его выходных данных содержится защищенный параметр.
{
"$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'))]"
}
}
}
Следующий пример не проходит тест, поскольку в его выходных данных используется функция list*.
{
"$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')]"
}
}
}
Используйте protectedSettings для секретов commandToExecute
Имя теста: CommandToExecute должно использовать ProtectedSettings для секретов
Для ресурсов с типом CustomScript используйте зашифрованное значение protectedSettings, если commandToExecute содержит пароли или другие секретные данные. Секретные данные могут содержаться в параметрах с типом secureString или secureObject, функциях list* (например, listKeys) и пользовательских скриптах.
Не используйте секретные данные в объекте settings, так как он использует открытый текст. Дополнительные сведения см. в разделе Microsoft.Compute virtualMachines/extensions, Windows или Linux.
В Bicep используйте правило Linter — используйте protectedSettings для секретов commandToExecute.
Следующий пример не проходит тест, так как settings использует commandToExecute для защищенного параметра.
"parameters": {
"adminPassword": {
"type": "secureString"
}
}
...
"properties": {
"type": "CustomScript",
"settings": {
"commandToExecute": "[parameters('adminPassword')]"
}
}
Следующий пример не проходит тест, так как settings использует commandToExecute с функцией listKeys.
"properties": {
"type": "CustomScript",
"settings": {
"commandToExecute": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageName')), '2021-02-01')]"
}
}
Следующий пример проходит тест, так как protectedSettings использует commandToExecute для защищенного параметра.
"parameters": {
"adminPassword": {
"type": "secureString"
}
}
...
"properties": {
"type": "CustomScript",
"protectedSettings": {
"commandToExecute": "[parameters('adminPassword')]"
}
}
Следующий пример проходит тест, так как protectedSettings использует commandToExecute с функцией listKeys.
"properties": {
"type": "CustomScript",
"protectedSettings": {
"commandToExecute": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageName')), '2021-02-01')]"
}
}
Использование свежих версий API в ссылочных функциях
Имя теста: apiVersions Should Be Recent In Reference Functions (В ссылочных функциях должны быть свежие версии API)
Версия API, используемая в ссылочной функции, должна быть свежей и не должна быть предварительной. Этот тест оценивает версию API в вашем шаблоне, сравнивая её с версиями поставщика ресурсов в кэше инструментария. Свежей считается версия API, созданная менее чем за два года до даты выполнения теста.
Предупреждение о том, что версия API не найдена, указывает, что версия не включена в кэш набора инструментов. Предупреждение может возникнуть при использовании самой последней и рекомендуемой версии API.
Дополнительные сведения о кэше toolkit.
Следующий пример не проходит тест, так как версия API в нем старше двух лет.
"outputs": {
"stgAcct": {
"type": "string",
"value": "[reference(resourceId(parameters('storageResourceGroup'), 'Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2019-06-01')]"
}
}
Следующий пример не проходит тест, так как используется API предварительной версии.
"outputs": {
"stgAcct": {
"type": "string",
"value": "[reference(resourceId(parameters('storageResourceGroup'), 'Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2020-08-01-preview')]"
}
}
Следующий пример проходит тест, так как версия API не старше двух лет и не является предварительной версией.
"outputs": {
"stgAcct": {
"type": "string",
"value": "[reference(resourceId(parameters('storageResourceGroup'), 'Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2021-02-01')]"
}
}
Использование типа и имени в функциях resourceId
Имя теста: Resources Should Not Be Ambiguous (Ресурсы не должны быть неоднозначными)
Этот тест отключен, но в выходных данных отображается как пройденный. Мы рекомендуем проверить шаблон на соответствие следующим критериям:
Значение resourceId должно содержать тип и имя ресурса. Этот тест ищет все функции resourceId в шаблоне и проверяет, что ресурс в шаблоне используется с правильным синтаксисом. В противном случае функция считается неоднозначной.
Например, функция resourceId будет неоднозначной в следующих случаях:
- если ресурс не обнаружен в шаблоне и группа ресурсов не указана;
- если ресурс содержит условие и группа ресурсов не указана;
- если связанный ресурс содержит некоторые, но не все сегменты имени. Например, дочерний ресурс содержит более одного сегмента имени. См. дополнительные сведения в примечаниях о resourceId.
Использование внутренней области действия для защищенных параметров во вложенных развертываниях
Имя теста: Secure Params In Nested Deployments (Защищенные параметры во вложенных развертываниях)
Используйте объект expressionEvaluationOptions во вложенном шаблоне с областью действия inner для оценки выражений, которые содержат защищенные параметры с типами secureString и secureObject или функции list*, например listKeys. Если используется область действия outer, выражения оцениваются в формате обычного текста в области действия родительского шаблона. Защищенный параметр в этом случае становится виден всем, кто имеет доступ к журналу развертывания. Значение expressionEvaluationOptions по умолчанию — outer.
Дополнительные сведения о вложенных шаблонах см. в статьях Развертывания Microsoft.Resources и Область оценки выражений во вложенных шаблонах.
В Bicep используйте правило Linter — безопасные параметры во вложенном развертывании.
Следующий пример не проходит тест, так как expressionEvaluationOptions использует область действия outer для оценки защищенных параметров или функций list*.
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2025-04-01",
"name": "nestedTemplate",
"properties": {
"expressionEvaluationOptions": {
"scope": "outer"
}
}
}
]
Следующий пример проходит тест, так как expressionEvaluationOptions использует область действия inner для оценки защищенных параметров или функций list*.
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2025-04-01",
"name": "nestedTemplate",
"properties": {
"expressionEvaluationOptions": {
"scope": "inner"
}
}
}
]
Следующие шаги
- Дополнительные сведения о запуске набора средств тестирования см. в статье Использование набора средств тестирования ARM.
- Для модуля Learn, охватывающего использование набора средств тестирования, см. статью Просмотр изменений и проверка ресурсов Azure с помощью набора средств тестирования шаблонов ARM.
- Чтобы протестировать файлы параметров, см. статью Тестовые случаи для файлов параметров.
- Сведения о тестах createUiDefinition см. в разделе "Тестовые варианты" для createUiDefinition.json.
- Дополнительные сведения о тестах для всех файлов см. в разделе "Тестовые случаи для всех файлов".