ARM 範本的測試案例

本文章說明 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 函式。

您可以使用類型 secureStringsecureObject 包含敏感性值(例如密碼)的參數。 當參數使用安全類型時,不會記錄參數的值,也不會儲存在部署歷程記錄中。 此動作可防止惡意使用者探索敏感性值。

當您提供預設值時,所有可存取範本或部署歷程記錄的人皆可找到該值。

在 Bicep 中,使用 Linter 規則 - 安全參數預設值 (部分機器翻譯)。

下列範例會失敗

"parameters": {
  "adminPassword": {
    "defaultValue": "HardcodedPassword",
    "type": "secureString"
  }
}

下一個範例會成功

"parameters": {
  "adminPassword": {
    "type": "secureString"
  }
}

由於使用newGuid函式,因此下列範例會成功

"parameters": {
  "secureParameter": {
    "type": "secureString",
    "defaultValue": "[newGuid()]"
  }
}

環境 URL 無法進行硬式編碼

測試名稱:DeploymentTemplate 不可包含硬式編碼之 Uri

請勿在範本中硬式編碼環境 URL。 相反地,請使用環境函式,在部署期間動態取得這些 URL。 如需封鎖的 URL 主機清單,請參閱測試案例

在 Bicep 中,使用 Linter 規則 - 沒有硬式編碼的環境 URL (部分機器翻譯)。

下列範例會失敗,因其 URL 已硬式編碼。

"variables":{
  "AzureURL":"https://management.azure.com"
}

使用 concaturi 時,測試也會失敗

"variables":{
  "AzureSchemaURL1": "[concat('https://','gallery.azure.com')]",
  "AzureSchemaURL2": "[uri('gallery.azure.com','test')]"
}

下列範例會成功

"variables": {
  "AzureSchemaURL": "[environment().gallery]"
}

使用參數的位置

測試名稱:不可將位置進行硬式編碼

若要設定資源的位置,您的範本應該要有一個名稱為 location 之參數,且類型需設定為 string。 在主要範本 (azuredeploy.jsonmainTemplate.json) 中,此參數可以預設為資源群組位置。 在連結或巢狀範本中,位置參數不應該有預設位置。

針對可建立資源的區域,範本使用者的存取權可能有限。 硬式編碼的資源位置可能會禁止使用者建立資源。 如果資源群組是在使用者無法存取的區域中建立,則 "[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": "2021-02-01",
      "name": "storageaccount1",
      "location": "[resourceGroup().location]",
      "kind": "StorageV2",
      "sku": {
        "name": "Premium_LRS",
        "tier": "Premium"
      }
    }
  ]
}

由於參數預設為硬式編碼的位置,因此下一個使用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": "2021-02-01",
      "name": "storageaccount1",
      "location": "[parameters('location')]",
      "kind": "StorageV2",
      "sku": {
        "name": "Premium_LRS",
        "tier": "Premium"
      }
    }
  ],
  "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": "2021-02-01",
      "name": "storageaccount1",
      "location": "[parameters('location')]",
      "kind": "StorageV2",
      "sku": {
        "name": "Premium_LRS",
        "tier": "Premium"
      }
    }
  ],
  "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": "2021-02-01",
      "name": "storageaccount1",
      "location": "westus",
      "kind": "StorageV2",
      "sku": {
        "name": "Premium_LRS",
        "tier": "Premium"
      }
    }
  ],
  "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": "2021-02-01",
      "name": "storageaccount1",
      "location": "global",
      "kind": "StorageV2",
      "sku": {
        "name": "Premium_LRS",
        "tier": "Premium"
      }
    }
  ],
  "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": "2021-02-01",
      "name": "storageaccount1",
      "location": "[parameters('location')]",
      "kind": "StorageV2",
      "sku": {
        "name": "Premium_LRS",
        "tier": "Premium"
      }
    }
  ],
  "outputs": {}
}

VM 大小使用參數

測試名稱:VM 大小應該是參數

不要對hardwareProfile物件之vmSize進行硬式編碼。 當hardwareProfile遭到省略或包含硬式編碼值時,測試就會失敗。 為您的範本使用者提供參數,以便其可修改已部署虛擬機器的大小。 如需詳細資訊,請參閱 Microsoft.Compute virtualMachines

由於hardwareProfile物件的vmSize是硬式編碼的值,因此下列範例會失敗

"resources": [
  {
    "type": "Microsoft.Compute/virtualMachines",
    "apiVersion": "2020-12-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": "2020-12-01",
    "name": "demoVM",
    "location": "[parameters('location')]",
    "properties": {
      "hardwareProfile": {
        "vmSize": "[parameters('vmSizeParameter')]"
      }
    }
  }
]

最小值和最大值為數字

測試名稱:最小值和最大值為數字

當您使用minValuemaxValue來定義參數時,請將其指定為數字。 您必須使用 minValuemaxValue 作為配對,否則測試會失敗。

由於minValuemaxValue為字串,因此下列範例會失敗

"exampleParameter": {
  "type": "int",
  "minValue": "0",
  "maxValue": "10"
}

由於僅使用minValue,因此下列範例會失敗

"exampleParameter": {
  "type": "int",
  "minValue": 0
}

由於 minValuemaxValue 為數字,因此下列範例會成功

"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 (建議使用) 會產生警告。

深入了解工具組快取

在 Bicep 中,使用 Linter 規則 - 使用最近的 API 版本 (部分機器翻譯)。

由於 API 版本已超過兩年,因此下列範例會失敗

"resources": [
  {
    "type": "Microsoft.Storage/storageAccounts",
    "apiVersion": "2019-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": "2021-02-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": "2020-12-01",
    ...
  }
]

屬性不可為空白

測試名稱:範本不應包含空白

請勿將屬性硬式編碼為空白值。 空白值包含 Null、空字串、物件或陣列。 如果屬性設定為空白值,請從您的範本中移除該屬性。 您可以在部署期間將屬性設為空白值 (例如透過參數)。

巢狀範本中的 template 可包含空白屬性。 如需有關巢狀範本的詳細資訊,請參閱 Microsoft.Resources 部署

由於具有空白屬性,因此下列範例會失敗

"resources": [
  {
    "type": "Microsoft.Storage/storageAccounts",
    "apiVersion": "2021-01-01",
    "name": "storageaccount1",
    "location": "[parameters('location')]",
    "sku": {},
    "kind": ""
  }
]

由於屬性包含值,因此下列範例會成功

"resources": [
  {
    "type": "Microsoft.Storage/storageAccounts",
    "apiVersion": "2021-01-01",
    "name": "storageaccount1",
    "location": "[parameters('location')]",
    "sku": {
      "name": "Standard_LRS",
      "tier": "Standard"
    },
    "kind": "Storage"
  }
]

使用資源識別碼函式

測試名稱:識別碼應衍生自 ResourceIDs

指定資源識別碼時,請使用其中一個資源識別碼函式。 允許的功能為:

請勿使用 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 函式有正確參數

測試名稱:ResourceIds 不應包含

當產生資源識別碼時,請勿針對選擇性參數使用不必要的函數。 依預設,resourceId 函式會使用目前的訂用帳戶與資源群組。 您不需要提供這些值。

由於您不需要提供目前的訂用帳戶識別碼和資源群組名稱,因此下列範例會失敗

"networkSecurityGroup": {
    "id": "[resourceId(subscription().subscriptionId, resourceGroup().name, 'Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
}

下一個範例會成功

"networkSecurityGroup": {
    "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
}

此測試適用於:

針對 referencelist*,當您使用 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')]"
}

使用最新的 VM 映像

測試名稱:應使用 VM 映像的最新版本

已停用此測試,但輸出顯示其已成功。 最佳做法是依照下列準則檢查您的範本:

如果您的範本包含具有映像之虛擬機器,請務必使用最新的映像版本。

在 Bicep 中,使用 Linter 規則 - 使用穩定的 VM 映像 (部分機器翻譯)。

使用穩定的 VM 映像

測試名稱:虛擬機器不應為預覽版

虛擬機器不應使用預覽版的映像。 測試會檢查 storageProfile,以確認 imageReference 未使用包含預覽版之字串。 且未在 imageReference 屬性 offerskuversion 中使用預覽版

如需屬性 imageReference 之詳細資訊,請參閱 Microsoft.Compute virtualMachinesMicrosoft.Compute virtualMachineScaleSets

在 Bicep 中,使用 Linter 規則 - 使用穩定的 VM 映像 (部分機器翻譯)。

由於imageReference包含預覽版之字串,因此下列範例會失敗

"properties": {
  "storageProfile": {
    "imageReference": "latest-preview"
  }
}

當在 offerskuversion 中使用預覽版,下列範例會失敗

"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 延伸模組

測試名稱:不得使用 ManagedIdentityExtension

請勿將 ManagedIdentity 延伸模組套用至虛擬機器。 擴充功能已在 2019 年遭取代,並不得再使用。

輸出不能包含祕密

測試名稱:輸出不能包含祕密

請勿在可能公開祕密之outputs區段中包含任何值。 例如,安全參數的類型 secureStringsecureObject,或 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')]"
    }
  }
}

針對 commandToExecute 祕密使用 protectedSettings

測試名稱:CommandToExecute 必須針對祕密,使用 ProtectedSettings

針對類型為 CustomScript 之資源,請在 commandToExecute 包含祕密資料 (例如密碼) 時,使用加密的 protectedSettings。 例如,祕密資料可用於類型secureStringsecureObject之安全參數、list* 函式 (例如listKeys),或自訂指令碼。

請勿在settings物件中使用祕密資料,因其會使用純文字。 如需詳細資訊,請參閱 Microsoft.Compute virtualMachines/extensionsWindowsLinux

在 Bicep 中,使用 Linter 規則 - 針對 commandToExecute 祕密使用 protectedSettings (部分機器翻譯)。

由於settings使用具有安全參數的commandToExecute,因此下列範例會失敗

"parameters": {
  "adminPassword": {
    "type": "secureString"
  }
}
...
"properties": {
  "type": "CustomScript",
  "settings": {
    "commandToExecute": "[parameters('adminPassword')]"
  }
}

由於settings使用具有listKeys函式的commandToExecute,因此下列範例會失敗

"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使用具有listKeys函式的commandToExecute,因此下列範例會成功

"properties": {
  "type": "CustomScript",
  "protectedSettings": {
    "commandToExecute": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageName')), '2021-02-01')]"
  }
}

使用參考函數中最新的 API 版本

測試名稱:apiVersions 在參考函式中應是最新版本

參考函數中使用的 API 必須為最新版本,而不是預覽版本。 測試會針對工具組快取中的資源提供者版本,來評估您範本中的 API 版本。 測試執行日期起兩年內的 API 版本會視為最新版本。

如果找不到 API 版本之警告,僅代表版本不在工具組的快取中。 使用最新版本的 API (建議使用) 會產生警告。

深入了解工具組快取

由於 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 函式中使用型別和名稱

測試名稱:資源必須明確

此測試已停用,但輸出顯示其已成功。 最佳做法是依照下列準則檢查您的範本:

resourceId 必須包含資源類型與資源名稱。 此測試會尋找所有範本之 resourceId 函式,並使用正確的語法驗證資源是否使用於範本中。 否則會將函式視為不明確。

若當下列情況發生,resourceId 函數會視為不明確:

  • 當範本中找不到資源,且未指定資源群組。
  • 當資源包含條件,且未指定資源群組。
  • 當相關資源包含部分,但非全部的名稱區段。 例如,子資源包含一個以上的名稱區段。 如需詳細資訊,請參閱 resourceId 備註

針對巢狀部署安全參數使用內部範圍

測試名稱:巢狀部署中的安全參數

使用具有 inner 範圍的巢狀範本 expressionEvaluationOptions 物件,來評估包含安全參數的運算式,其類型為 secureStringsecureObjectlist* 函數 (例如 listKeys)。 如果使用 outer 範圍,運算式會以純文字的方式在父代範本範圍內進行評估。 如此一來,任何可存取部署歷程記錄的人,皆能看到安全的值。 expressionEvaluationOptions 的預設值為 outer

如需更多有關巢狀範本的相關資訊,請參閱 Microsoft.Resources 部署巢狀範本中的運算式評估範圍

在 Bicep 中,使用 Linter 規則 - 巢狀部署中的安全參數 (部分機器翻譯)。

下列範例失敗,因為expressionEvaluationOptions使用outer範圍評估安全參數或list*函式。

"resources": [
  {
    "type": "Microsoft.Resources/deployments",
    "apiVersion": "2021-04-01",
    "name": "nestedTemplate",
    "properties": {
      "expressionEvaluationOptions": {
        "scope": "outer"
      }
    }
  }
]

由於expressionEvaluationOptions使用inner範圍,來評估安全參數或list*函式,因此下列範例會成功

"resources": [
  {
    "type": "Microsoft.Resources/deployments",
    "apiVersion": "2021-04-01",
    "name": "nestedTemplate",
    "properties": {
      "expressionEvaluationOptions": {
        "scope": "inner"
      }
    }
  }
]

下一步