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 備註

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

測試名稱:保護巢狀部署中的參數

使用具有expressionEvaluationOptions範圍之巢狀範本inner物件,評估包含類型secureStringsecureObject之安全參數運算式,或 list* 函式 (例如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"
      }
    }
  }
]

後續步驟