Przypadki testowe dla szablonów usługi ARM
W tym artykule opisano testy uruchamiane przy użyciu zestawu narzędzi do testowania szablonu dla szablonów usługi Azure Resource Manager (szablonów usługi ARM). Zawiera przykłady z powodzeniem lub niepowodzeniem testu i zawierają nazwę każdego testu. Aby uzyskać więcej informacji na temat uruchamiania testów lub uruchamiania określonego testu, zobacz Parametry testu.
Użyj poprawnego schematu
Nazwa testu: DeploymentTemplate Schemat jest poprawny
W szablonie należy określić prawidłową wartość schematu.
Poniższy przykład kończy się niepowodzeniem , ponieważ schemat jest nieprawidłowy.
{
"$schema": "https://schema.management.azure.com/schemas/2019-01-01/deploymentTemplate.json#",
}
W poniższym przykładzie jest wyświetlane ostrzeżenie, ponieważ wersja 2015-01-01
schematu jest przestarzała i nie jest obsługiwana.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
}
Poniższy przykład przekazuje prawidłowy schemat.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
}
Właściwość szablonu schema
musi być ustawiona na jeden z następujących schematów:
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
Parametry zadeklarowane muszą być używane
Nazwa testu: parametry muszą być przywołyne
Ten test znajduje parametry, które nie są używane w szablonie lub parametrach, które nie są używane w prawidłowym wyrażeniu.
Aby zmniejszyć zamieszanie w szablonie, usuń wszystkie zdefiniowane parametry, ale nie są używane. Wyeliminowanie nieużywanych parametrów upraszcza wdrażanie szablonów, ponieważ nie trzeba dostarczać niepotrzebnych wartości.
W Bicep użyj reguły Linter — brak nieużywanych parametrów.
Poniższy przykład kończy się niepowodzeniem , ponieważ w wyrażeniu odwołującym się do parametru brakuje wiodącego nawiasu kwadratowego ([
).
"resources": [
{
"location": " parameters('location')]"
}
]
Poniższy przykład przekazuje dane , ponieważ wyrażenie jest prawidłowe.
"resources": [
{
"location": "[parameters('location')]"
}
]
Bezpieczne parametry nie mogą mieć zakodowanej na sztywno wartości domyślnej
Nazwa testu: Parametry bezpiecznego ciągu nie mogą mieć wartości domyślnej
Nie udostępniaj zakodowanej wartości domyślnej bezpiecznego parametru w szablonie. Bezpieczny parametr może mieć pusty ciąg jako wartość domyślną lub użyć nowej funkcjiGuid w wyrażeniu.
Można używać typów secureString
lub secureObject
parametrów zawierających poufne wartości, takie jak hasła. Gdy parametr używa bezpiecznego typu, wartość parametru nie jest rejestrowana ani przechowywana w historii wdrożenia. Ta akcja uniemożliwia złośliwemu użytkownikowi odnajdywanie poufnej wartości.
Po podaniu wartości domyślnej ta wartość jest wykrywalna przez wszystkich, którzy mogą uzyskać dostęp do szablonu lub historii wdrażania.
W Bicep użyj reguły Linter — wartość domyślna bezpiecznego parametru.
Poniższy przykład kończy się niepowodzeniem.
"parameters": {
"adminPassword": {
"defaultValue": "HardcodedPassword",
"type": "secureString"
}
}
W następnym przykładzie przejdziemy dalej.
"parameters": {
"adminPassword": {
"type": "secureString"
}
}
Poniższy przykład przekazuje dane , ponieważ newGuid
funkcja jest używana.
"parameters": {
"secureParameter": {
"type": "secureString",
"defaultValue": "[newGuid()]"
}
}
Adresy URL środowiska nie mogą być zakodowane w kodzie
Nazwa testu: DeploymentTemplate nie może zawierać zakodowanego na stałe identyfikatora URI
Nie koduj twardych adresów URL środowiska w szablonie. Zamiast tego użyj funkcji środowiska , aby dynamicznie pobierać te adresy URL podczas wdrażania. Aby uzyskać listę hostów adresów URL, które są zablokowane, zobacz przypadek testowy.
W aplikacji Bicep użyj reguły Linter — bez zakodowanego na stałe adresu URL środowiska.
Poniższy przykład kończy się niepowodzeniem , ponieważ adres URL jest zakodowany w kodzie.
"variables":{
"AzureURL":"https://management.azure.com"
}
Test również kończy się niepowodzeniem w przypadku użycia z concat lub uri.
"variables":{
"AzureSchemaURL1": "[concat('https://','gallery.azure.com')]",
"AzureSchemaURL2": "[uri('gallery.azure.com','test')]"
}
Poniższy przykład przekazuje.
"variables": {
"AzureSchemaURL": "[environment().gallery]"
}
Lokalizacja używa parametru
Nazwa testu: lokalizacja nie powinna być zakodowana na stałe
Aby ustawić lokalizację zasobu, szablony powinny mieć parametr o nazwie location
z typem ustawionym na string
. W szablonie głównym azuredeploy.json lub mainTemplate.json ten parametr może być domyślnie ustawiony na lokalizację grupy zasobów. W połączonych lub zagnieżdżonych szablonach parametr lokalizacji nie powinien mieć lokalizacji domyślnej.
Użytkownicy szablonów mogą mieć ograniczony dostęp do regionów, w których mogą tworzyć zasoby. Zakodowana lokalizacja zasobu może uniemożliwić użytkownikom tworzenie zasobu. Wyrażenie "[resourceGroup().location]"
może blokować użytkowników, jeśli grupa zasobów została utworzona w regionie, do którego użytkownik nie może uzyskać dostępu. Użytkownicy, którzy są zablokowani, nie mogą używać szablonu.
location
Podając parametr domyślny lokalizacji grupy zasobów, użytkownicy mogą używać wartości domyślnej, gdy jest to wygodne, ale także określa inną lokalizację.
W Bicep użyj reguły Linter — brak wyrażeń lokalizacji poza wartościami domyślnymi parametrów.
Poniższy przykład kończy się niepowodzeniem , ponieważ zasób location
jest ustawiony na resourceGroup().location
wartość .
{
"$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"
}
}
]
}
W następnym przykładzie użyto parametru location
, ale nie powiedzie się , ponieważ parametr jest domyślnie zakodowany w lokalizacji.
{
"$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": {}
}
Poniższy przykład przekazuje informacje , gdy szablon jest używany jako szablon główny. Utwórz parametr, który jest domyślnie ustawiony na lokalizację grupy zasobów, ale umożliwia użytkownikom podanie innej wartości.
{
"$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": {}
}
Uwaga
Jeśli powyższy przykład jest używany jako połączony szablon, test zakończy się niepowodzeniem. W przypadku użycia jako szablonu połączonego usuń wartość domyślną.
Zasoby powinny mieć lokalizację
Nazwa testu: Zasoby powinny mieć lokalizację
Lokalizacja zasobu powinna być ustawiona na wyrażenie szablonu lub global
. Wyrażenie szablonu zwykle używa parametru opisanego location
w sekcji Lokalizacja używa parametru.
W aplikacji Bicep użyj reguły Linter — nie ma zakodowanych na stałe lokalizacji.
Poniższy przykład kończy się niepowodzeniem , ponieważ location
wyrażenie nie jest wyrażeniem ani 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": {}
}
Poniższy przykład przekazuje element , ponieważ zasób location
jest ustawiony na global
wartość .
{
"$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": {}
}
Następny przykład jest również przekazywana , ponieważ location
parametr używa wyrażenia. Zasób location
używa wartości wyrażenia.
{
"$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": {}
}
Rozmiar maszyny wirtualnej używa parametru
Nazwa testu: Rozmiar maszyny wirtualnej powinien być parametrem
Nie koduj hardwareProfile
trwale obiektu vmSize
. Test kończy się niepowodzeniem, gdy hardwareProfile
pominięto wartość lub zawiera wartość zakodowaną. Podaj parametr, aby użytkownicy szablonu mogli modyfikować rozmiar wdrożonej maszyny wirtualnej. Aby uzyskać więcej informacji, zobacz Microsoft.Compute virtualMachines.
Poniższy przykład kończy się niepowodzeniem , ponieważ hardwareProfile
obiekt vmSize
jest wartością zakodowaną na sztywno.
"resources": [
{
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "2020-12-01",
"name": "demoVM",
"location": "[parameters('location')]",
"properties": {
"hardwareProfile": {
"vmSize": "Standard_D2_v3"
}
}
}
]
Przykład jest przekazywana, gdy parametr określa wartość parametru :vmSize
"parameters": {
"vmSizeParameter": {
"type": "string",
"defaultValue": "Standard_D2_v3",
"metadata": {
"description": "Size for the virtual machine."
}
}
}
hardwareProfile
Następnie używa wyrażenia , vmSize
aby odwołać się do wartości parametru:
"resources": [
{
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "2020-12-01",
"name": "demoVM",
"location": "[parameters('location')]",
"properties": {
"hardwareProfile": {
"vmSize": "[parameters('vmSizeParameter')]"
}
}
}
]
Wartości minimalne i maksymalne to liczby
Nazwa testu: minimalna i maksymalna wartość to liczby
Podczas definiowania parametru za pomocą minValue
parametru i maxValue
określ je jako liczby. Musisz użyć parametru minValue
i maxValue
jako pary lub test zakończy się niepowodzeniem.
Poniższy przykład kończy się niepowodzeniem , ponieważ minValue
ciągi są maxValue
ciągami.
"exampleParameter": {
"type": "int",
"minValue": "0",
"maxValue": "10"
}
Poniższy przykład kończy się niepowodzeniem , ponieważ jest używany tylko minValue
.
"exampleParameter": {
"type": "int",
"minValue": 0
}
Poniższy przykład przekazuje dane , ponieważ minValue
i maxValue
są liczbami.
"exampleParameter": {
"type": "int",
"minValue": 0,
"maxValue": 10
}
Poprawnie zdefiniowany parametr Artifacts
Nazwa testu: parametr artefaktów
W przypadku uwzględnienia parametrów dla _artifactsLocation
i _artifactsLocationSasToken
użyj poprawnych wartości domyślnych i typów. Aby przejść ten test, należy spełnić następujące warunki:
- Jeśli podasz jeden parametr, musisz podać drugi.
_artifactsLocation
musi być .string
_artifactsLocation
musi mieć wartość domyślną w głównym szablonie._artifactsLocation
Nie może mieć wartości domyślnej w zagnieżdżonym szablonie._artifactsLocation
musi mieć"[deployment().properties.templateLink.uri]"
adres URL pierwotnego repozytorium lub dla jego wartości domyślnej._artifactsLocationSasToken
musi być .secureString
_artifactsLocationSasToken
Może mieć tylko pusty ciąg dla jego wartości domyślnej._artifactsLocationSasToken
Nie może mieć wartości domyślnej w zagnieżdżonym szablonie.
W Bicep użyj reguły Linter — parametry artefaktów.
Zadeklarowane zmienne muszą być używane
Nazwa testu: Zmienne muszą być przywołyne
Ten test wyszukuje zmienne, które nie są używane w szablonie lub nie są używane w prawidłowym wyrażeniu. Aby zmniejszyć zamieszanie w szablonie, usuń wszystkie zdefiniowane zmienne, ale nie są używane.
Do zmiennych używających copy
elementu do iterowania wartości należy odwoływać się. Aby uzyskać więcej informacji, zobacz Iteracja zmiennych w szablonach usługi ARM.
W Bicep użyj reguły Linter — nieużywane zmienne.
Poniższy przykład kończy się niepowodzeniem , ponieważ zmienna używająca copy
elementu nie jest przywołyowana.
{
"$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": {}
}
Poniższy przykład kończy się niepowodzeniem , ponieważ w wyrażeniu odwołującym się do zmiennej brakuje wiodącego nawiasu kwadratowego ([
).
"outputs": {
"outputVariable": {
"type": "string",
"value": " variables('varExample')]"
}
}
Poniższy przykład przekazuje, ponieważ zmienna jest przywoływalana w pliku 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')]"
}
}
}
Poniższy przykład przekazuje dane , ponieważ wyrażenie jest prawidłowe.
"outputs": {
"outputVariable": {
"type": "string",
"value": "[variables('varExample')]"
}
}
Zmienna dynamiczna nie powinna używać concat
Nazwa testu: Odwołania do zmiennych dynamicznych nie powinny używać concat
Czasami trzeba dynamicznie konstruować zmienną na podstawie wartości innej zmiennej lub parametru. Nie używaj funkcji concat podczas ustawiania wartości. Zamiast tego należy użyć obiektu zawierającego dostępne opcje i dynamicznie uzyskać jedną z właściwości z obiektu podczas wdrażania.
Poniższy przykład przekazuje. Zmienna currentImage
jest dynamicznie ustawiana podczas wdrażania.
{
"$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')]"
}
}
}
Korzystanie z najnowszej wersji interfejsu API
Nazwa testu: apiVersions powinna być ostatnio używana
Wersja interfejsu API dla każdego zasobu powinna używać najnowszej wersji, która jest zakodowana jako ciąg. Test ocenia wersję interfejsu API w szablonie względem wersji dostawcy zasobów w pamięci podręcznej zestawu narzędzi. Wersja interfejsu API, która jest starsza niż dwa lata od daty uruchomienia testu, jest uznawana za ostatnią. Nie używaj wersji zapoznawczej, gdy jest dostępna najnowsza wersja.
Ostrzeżenie, że nie znaleziono wersji interfejsu API tylko wskazuje, że wersja nie jest zawarta w pamięci podręcznej zestawu narzędzi. Użycie najnowszej wersji interfejsu API, która jest zalecana, może wygenerować ostrzeżenie.
Dowiedz się więcej o pamięci podręcznej zestawu narzędzi.
W aplikacji Bicep użyj reguły Linter — użyj ostatnich wersji interfejsu API.
Poniższy przykład kończy się niepowodzeniem , ponieważ wersja interfejsu API ma więcej niż dwa lata.
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2019-06-01",
"name": "storageaccount1",
"location": "[parameters('location')]"
}
]
Poniższy przykład kończy się niepowodzeniem , ponieważ wersja zapoznawcza jest używana, gdy jest dostępna nowsza wersja.
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2020-08-01-preview",
"name": "storageaccount1",
"location": "[parameters('location')]"
}
]
Poniższy przykład jest przekazywana , ponieważ jest to najnowsza wersja, która nie jest wersją zapoznawcza.
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2021-02-01",
"name": "storageaccount1",
"location": "[parameters('location')]"
}
]
Używanie zakodowanej wersji interfejsu API
Nazwa testu: Dostawcy apiVersions nie jest dozwolona
Wersja interfejsu API dla typu zasobu określa, które właściwości są dostępne. Podaj zakodowaną wersję interfejsu API w szablonie. Nie pobieraj wersji interfejsu API określonej podczas wdrażania, ponieważ nie wiesz, które właściwości są dostępne.
Poniższy przykład kończy się niepowodzeniem.
"resources": [
{
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "[providers('Microsoft.Compute', 'virtualMachines').apiVersions[0]]",
...
}
]
Poniższy przykład przekazuje.
"resources": [
{
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "2020-12-01",
...
}
]
Właściwości nie mogą być puste
Nazwa testu: szablon nie powinien zawierać wartości pustych
Nie należy kodować właściwości na wartość pustą. Puste wartości obejmują ciągi o wartości null, obiekty lub tablice. Jeśli właściwość jest ustawiona na wartość pustą, usuń właściwość z szablonu. Właściwość można ustawić na wartość pustą podczas wdrażania, na przykład za pomocą parametru.
Właściwość template
w szablonie zagnieżdżonym może zawierać puste właściwości. Aby uzyskać więcej informacji na temat szablonów zagnieżdżonych, zobacz Wdrożenia Microsoft.Resources.
Poniższy przykład kończy się niepowodzeniem , ponieważ istnieją puste właściwości.
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2021-01-01",
"name": "storageaccount1",
"location": "[parameters('location')]",
"sku": {},
"kind": ""
}
]
Poniższy przykład przekazuje dane , ponieważ właściwości zawierają wartości.
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2021-01-01",
"name": "storageaccount1",
"location": "[parameters('location')]",
"sku": {
"name": "Standard_LRS",
"tier": "Standard"
},
"kind": "Storage"
}
]
Korzystanie z funkcji identyfikatora zasobu
Nazwa testu: identyfikatory powinny pochodzić z identyfikatorów zasobów
Podczas określania identyfikatora zasobu użyj jednej z funkcji identyfikatora zasobu. Dozwolone funkcje to:
Nie używaj funkcji concat do utworzenia identyfikatora zasobu.
W Bicep użyj reguły Linter — użyj funkcji identyfikatora zasobu.
Poniższy przykład kończy się niepowodzeniem.
"networkSecurityGroup": {
"id": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/networkSecurityGroups/', variables('networkSecurityGroupName'))]"
}
W następnym przykładzie przejdziemy dalej.
"networkSecurityGroup": {
"id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
}
Funkcja ResourceId ma poprawne parametry
Nazwa testu: Identyfikatory zasobów nie powinny zawierać
Podczas generowania identyfikatorów zasobów nie używaj niepotrzebnych funkcji dla parametrów opcjonalnych. Domyślnie funkcja resourceId używa bieżącej subskrypcji i grupy zasobów. Nie musisz podawać tych wartości.
Poniższy przykład kończy się niepowodzeniem , ponieważ nie musisz podawać bieżącego identyfikatora subskrypcji i nazwy grupy zasobów.
"networkSecurityGroup": {
"id": "[resourceId(subscription().subscriptionId, resourceGroup().name, 'Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
}
W następnym przykładzie przejdziemy dalej.
"networkSecurityGroup": {
"id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
}
Ten test dotyczy:
W przypadku reference
parametrów i list*
test kończy się niepowodzeniem podczas tworzenia concat
identyfikatora zasobu.
dependsOn najlepsze rozwiązania
Nazwa testu: DependsOn Best Practices
Podczas ustawiania zależności wdrażania nie należy używać funkcji if do testowania warunku. Jeśli jeden zasób zależy od zasobu, który jest wdrażany warunkowo, ustaw zależność tak, jak w przypadku dowolnego zasobu. Gdy zasób warunkowy nie zostanie wdrożony, usługa Azure Resource Manager automatycznie usunie go z wymaganych zależności.
Element dependsOn
nie może zaczynać się od funkcji concat .
W Bicep użyj reguły Linter — brak niepotrzebnych wpisów dependsOn.
Poniższy przykład kończy się niepowodzeniemif
, ponieważ zawiera funkcję.
"dependsOn": [
"[if(equals(parameters('newOrExisting'),'new'), variables('storageAccountName'), '')]"
]
Poniższy przykład kończy się niepowodzeniem , ponieważ rozpoczyna się od concat
.
"dependsOn": [
"[concat(variables('storageAccountName'))]"
]
Poniższy przykład przekazuje.
"dependsOn": [
"[variables('storageAccountName')]"
]
Zagnieżdżone lub połączone wdrożenia nie mogą używać debugowania
Nazwa testu: Zasoby wdrażania nie mogą być debugowaniem
Podczas definiowania szablonu zagnieżdżonego lub połączonego z typem Microsoft.Resources/deployments
zasobu można włączyć debugowanie. Debugowanie jest używane, gdy trzeba przetestować szablon, ale może uwidaczniać poufne informacje. Przed zastosowaniem szablonu w środowisku produkcyjnym wyłącz debugowanie. Możesz usunąć debugSetting
obiekt lub zmienić detailLevel
właściwość na none
.
Poniższy przykład kończy się niepowodzeniem.
"debugSetting": {
"detailLevel": "requestContent"
}
Poniższy przykład przekazuje.
"debugSetting": {
"detailLevel": "none"
}
Nazwy użytkowników administratora nie mogą być wartością literału
Nazwa testu: adminUsername nie powinien być literałem
W przypadku ustawiania wartości adminUserName
literału nie używaj wartości literału. Utwórz parametr nazwy użytkownika i użyj wyrażenia, aby odwołać się do wartości parametru.
W aplikacji Bicep użyj reguły Linter — nazwa użytkownika administratora nie powinna być literałem.
Poniższy przykład kończy się niepowodzeniem z wartością literału.
"osProfile": {
"adminUserName": "myAdmin"
}
Poniższy przykład przekazuje wyrażenie.
"osProfile": {
"adminUsername": "[parameters('adminUsername')]"
}
Korzystanie z najnowszego obrazu maszyny wirtualnej
Nazwa testu: Obrazy maszyn wirtualnych powinny używać najnowszej wersji
Ten test jest wyłączony, ale dane wyjściowe pokazują, że zostały pomyślnie przekazane. Najlepszym rozwiązaniem jest sprawdzenie szablonu pod kątem następujących kryteriów:
Jeśli szablon zawiera maszynę wirtualną z obrazem, upewnij się, że używa najnowszej wersji obrazu.
W aplikacji Bicep użyj reguły Linter — użyj stabilnego obrazu maszyny wirtualnej.
Używanie stabilnych obrazów maszyn wirtualnych
Nazwa testu: Maszyny wirtualne nie powinny być w wersji zapoznawczej
Maszyny wirtualne nie powinny używać obrazów w wersji zapoznawczej. Test sprawdza, storageProfile
czy imageReference
element nie używa ciągu zawierającego podgląd. Ta wersja zapoznawcza nie jest używana we imageReference
właściwościach offer
, sku
lub version
.
Aby uzyskać więcej informacji na temat imageReference
właściwości, zobacz Microsoft.Compute virtualMachines i Microsoft.Compute virtualMachineScaleSets.
W aplikacji Bicep użyj reguły Linter — użyj stabilnego obrazu maszyny wirtualnej.
Poniższy przykład kończy się niepowodzeniem , ponieważ imageReference
jest to ciąg zawierający podgląd.
"properties": {
"storageProfile": {
"imageReference": "latest-preview"
}
}
Poniższy przykład kończy się niepowodzeniem , gdy wersja zapoznawcza jest używana w systemie offer
, sku
lub version
.
"properties": {
"storageProfile": {
"imageReference": {
"publisher": "Canonical",
"offer": "UbuntuServer_preview",
"sku": "16.04-LTS-preview",
"version": "preview"
}
}
}
Poniższy przykład przekazuje.
"storageProfile": {
"imageReference": {
"publisher": "Canonical",
"offer": "UbuntuServer",
"sku": "16.04-LTS",
"version": "latest"
}
}
Nie używaj rozszerzenia ManagedIdentity
Nazwa testu: ManagedIdentityExtension nie może być używany
Nie stosuj ManagedIdentity
rozszerzenia do maszyny wirtualnej. Rozszerzenie zostało uznane za przestarzałe w 2019 r. i nie powinno już być używane.
Dane wyjściowe nie mogą zawierać wpisów tajnych
Nazwa testu: dane wyjściowe nie mogą zawierać wpisów tajnych
Nie dołączaj żadnych wartości w outputs
sekcji, która potencjalnie uwidacznia wpisy tajne. Na przykład bezpieczne parametry typu lub lub listy* funkcji, takich jak listKeys
.secureObject
secureString
Dane wyjściowe z szablonu są przechowywane w historii wdrażania, więc złośliwy użytkownik może znaleźć te informacje.
W Bicep użyj reguły Linter — dane wyjściowe nie powinny zawierać wpisów tajnych.
Poniższy przykład kończy się niepowodzeniem , ponieważ zawiera bezpieczny parametr w wartości wyjściowej.
{
"$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'))]"
}
}
}
Poniższy przykład kończy się niepowodzeniem, ponieważ używa funkcji list* w danych wyjściowych.
{
"$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')]"
}
}
}
Używanie wartości protectedSettings dla wpisów tajnych commandToExecute
Nazwa testu: CommandToExecute musi używać wartości ProtectedSettings dla wpisów tajnych
W przypadku zasobów z typem CustomScript
użyj zaszyfrowanego elementu protectedSettings
, jeśli commandToExecute
zawierają dane tajne, takie jak hasło. Na przykład dane tajne mogą być używane w bezpiecznych parametrach typu lub , list* funkcji, takich jak listKeys
, lub skrypty niestandardowe. secureObject
secureString
Nie używaj danych tajnych w obiekcie, ponieważ używa on zwykłego settings
tekstu. Aby uzyskać więcej informacji, zobacz Microsoft.Compute virtualMachines/extensions, Windows lub Linux.
W Bicep użyj reguły Linter — użyj wartości protectedSettings dla wpisów tajnych commandToExecute.
Poniższy przykład kończy się niepowodzeniem z powodu settings
użycia commandToExecute
z bezpiecznym parametrem.
"parameters": {
"adminPassword": {
"type": "secureString"
}
}
...
"properties": {
"type": "CustomScript",
"settings": {
"commandToExecute": "[parameters('adminPassword')]"
}
}
Poniższy przykład kończy się niepowodzeniem z powodu settings
użycia commandToExecute
z funkcją listKeys
.
"properties": {
"type": "CustomScript",
"settings": {
"commandToExecute": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageName')), '2021-02-01')]"
}
}
Poniższy przykład przekazuje dane , ponieważ protectedSettings
używa go commandToExecute
z bezpiecznym parametrem.
"parameters": {
"adminPassword": {
"type": "secureString"
}
}
...
"properties": {
"type": "CustomScript",
"protectedSettings": {
"commandToExecute": "[parameters('adminPassword')]"
}
}
Poniższy przykład przekazuje dane z powodu protectedSettings
użycia commandToExecute
z funkcją listKeys
.
"properties": {
"type": "CustomScript",
"protectedSettings": {
"commandToExecute": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageName')), '2021-02-01')]"
}
}
Używanie najnowszych wersji interfejsu API w funkcjach referencyjnych
Nazwa testu: apiVersions powinna być ostatnio używana w funkcjach referencyjnych
Wersja interfejsu API używana w funkcji referencyjnej musi być najnowsza, a nie wersja zapoznawcza. Test ocenia wersję interfejsu API w szablonie względem wersji dostawcy zasobów w pamięci podręcznej zestawu narzędzi. Wersja interfejsu API, która jest starsza niż dwa lata od daty uruchomienia testu, jest uznawana za ostatnią.
Ostrzeżenie, że nie znaleziono wersji interfejsu API tylko wskazuje, że wersja nie jest zawarta w pamięci podręcznej zestawu narzędzi. Użycie najnowszej wersji interfejsu API, która jest zalecana, może wygenerować ostrzeżenie.
Dowiedz się więcej o pamięci podręcznej zestawu narzędzi.
Poniższy przykład kończy się niepowodzeniem , ponieważ wersja interfejsu API ma więcej niż dwa lata.
"outputs": {
"stgAcct": {
"type": "string",
"value": "[reference(resourceId(parameters('storageResourceGroup'), 'Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2019-06-01')]"
}
}
Poniższy przykład kończy się niepowodzeniem , ponieważ wersja interfejsu API jest wersją zapoznawcza.
"outputs": {
"stgAcct": {
"type": "string",
"value": "[reference(resourceId(parameters('storageResourceGroup'), 'Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2020-08-01-preview')]"
}
}
Poniższy przykład jest przekazywana , ponieważ wersja interfejsu API jest starsza niż dwa lata i nie jest wersją zapoznawcza.
"outputs": {
"stgAcct": {
"type": "string",
"value": "[reference(resourceId(parameters('storageResourceGroup'), 'Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2021-02-01')]"
}
}
Używanie typu i nazwy w funkcjach resourceId
Nazwa testu: Zasoby nie powinny być niejednoznaczne
Ten test jest wyłączony, ale dane wyjściowe pokazują, że zostały pomyślnie przekazane. Najlepszym rozwiązaniem jest sprawdzenie szablonu pod kątem następujących kryteriów:
Identyfikator zasobu musi zawierać typ zasobu i nazwę zasobu. Ten test wyszukuje wszystkie funkcje szablonu resourceId
i sprawdza, czy zasób jest używany w szablonie z poprawną składnią. W przeciwnym razie funkcja jest uważana za niejednoznaczną.
Na przykład resourceId
funkcja jest uważana za niejednoznaczną:
- Jeśli zasób nie zostanie znaleziony w szablonie, a grupa zasobów nie zostanie określona.
- Jeśli zasób zawiera warunek i nie określono grupy zasobów.
- Jeśli powiązany zasób zawiera niektóre, ale nie wszystkie segmenty nazw. Na przykład zasób podrzędny zawiera więcej niż jeden segment nazw. Aby uzyskać więcej informacji, zobacz resourceId uwagi.
Używanie zakresu wewnętrznego dla zagnieżdżonych parametrów bezpiecznego wdrożenia
Nazwa testu: Bezpieczne parametry we wdrożeniach zagnieżdżonych
Użyj obiektu zagnieżdżonego szablonu z zakreseminner
, aby ocenić wyrażenia zawierające bezpieczne parametry typu secureString
lub secureObject
funkcji listy*, takich jak listKeys
.expressionEvaluationOptions
outer
Jeśli zakres jest używany, wyrażenia są oceniane w postaci zwykłego tekstu w zakresie szablonu nadrzędnego. Bezpieczna wartość jest następnie widoczna dla każdej osoby z dostępem do historii wdrożenia. Wartość domyślna expressionEvaluationOptions
to outer
.
Aby uzyskać więcej informacji na temat szablonów zagnieżdżonych, zobacz Wdrożenia Microsoft.Resources i Zakres oceny wyrażeń w szablonach zagnieżdżonych.
W aplikacji Bicep użyj reguły Linter — bezpieczne parametry w zagnieżdżonym wdrożeniu.
Poniższy przykład kończy się niepowodzeniem , ponieważ expressionEvaluationOptions
używa outer
zakresu do oceny bezpiecznych parametrów lub list*
funkcji.
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2021-04-01",
"name": "nestedTemplate",
"properties": {
"expressionEvaluationOptions": {
"scope": "outer"
}
}
}
]
Poniższy przykład przechodzi, ponieważ expressionEvaluationOptions
używa inner
zakresu do oceny bezpiecznych parametrów lub list*
funkcji.
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2021-04-01",
"name": "nestedTemplate",
"properties": {
"expressionEvaluationOptions": {
"scope": "inner"
}
}
}
]
Następne kroki
- Aby dowiedzieć się więcej na temat uruchamiania zestawu narzędzi do testowania, zobacz Korzystanie z zestawu narzędzi do testowania szablonu usługi ARM.
- Aby zapoznać się z modułem Learn, który obejmuje korzystanie z zestawu narzędzi do testowania, zobacz Podgląd zmian i weryfikowanie zasobów platformy Azure przy użyciu analizy warunkowej i zestawu narzędzi do testowania szablonu usługi ARM.
- Aby przetestować pliki parametrów, zobacz Przypadki testowe dla plików parametrów.
- Aby zapoznać się z testami createUiDefinition, zobacz Przypadki testowe dla createUiDefinition.json.
- Aby dowiedzieć się więcej o testach dla wszystkich plików, zobacz Przypadki testowe dla wszystkich plików.