Kasus pengujian untuk templat ARM

Artikel ini menjelaskan pengujian yang dijalankan dengan toolkit pengujian templat untuk templat Azure Resource Manager (templat ARM). Ini memberikan contoh yang lolos atau gagal pengujian dan menyertakan nama setiap pengujian. Selengkapnya tentang cara menjalankan pengujian atau cara menjalankan pengujian tertentu, lihat Parameter pengujian.

Menggunakan skema yang benar

Nama pengujian: Skema DeploymentTemplate Sudah Benar

Di templat Anda, Anda harus menentukan nilai skema yang valid.

Contoh berikut gagal karena skema tidak valid.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-01-01/deploymentTemplate.json#",
}

Contoh berikut menampilkan peringatan karena versi skema 2015-01-01 tidak digunakan lagi dan tidak dipelihara.

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
}

Contoh berikut lolos menggunakan skema yang valid.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
}

Properti schema skema harus diatur ke salah satu dari skema berikut:

  • 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

Parameter yang dinyatakan harus digunakan

Nama pengujian: Parameter Harus Direferensikan

Pengujian ini menemukan parameter yang tidak digunakan dalam templat atau parameter yang tidak digunakan dalam ekspresi yang valid.

Untuk menghindari kebingungan pada templat Anda, hapus parameter apa pun yang ditentukan tetapi tidak digunakan. Menghilangkan parameter yang tidak digunakan memudahkan penyebaran templat Anda karena Anda tidak perlu memberikan nilai yang tidak perlu.

Di Bicep, gunakan aturan Linter - tidak ada parameter yang tidak digunakan.

Contoh berikut gagal karena ekspresi yang merujuk parameter tidak memiliki kurung siku awal ([).

"resources": [
  {
    "location": " parameters('location')]"
  }
]

Contoh berikut lolos karena ekspresi valid.

"resources": [
  {
    "location": "[parameters('location')]"
  }
]

Parameter aman tidak boleh memiliki default yang dikodekan secara permanen

Nama pengujian: Parameter Untai (Karakter) Aman Tidak Boleh Memiliki Default

Jangan memberikan nilai default yang dikodekan secara permanen untuk parameter aman di templat Anda. Parameter aman dapat memiliki string kosong sebagai nilai default atau menggunakan fungsi newGuid dalam ekspresi.

Anda menggunakan jenis secureString atau secureObject pada parameter yang berisi nilai sensitif, seperti kata sandi. Ketika parameter menggunakan tipe aman, nilai parameter tidak dicatat atau disimpan dalam riwayat penyebaran. Tindakan ini mencegah pengguna jahat untuk menemukan nilai sensitif.

Ketika Anda memberikan nilai default, nilai tersebut dapat ditemukan oleh siapa saja yang dapat mengakses templat atau riwayat penyebaran.

Di Bicep, gunakan aturan Linter - default parameter aman.

Contoh berikut gagal.

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

Contoh berikut lolos.

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

Contoh berikut lolos karena fungsi newGuid valid.

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

URL lingkungan tidak dapat dikodekan secara permanen

Nama pengujian: DeploymentTemplate Tidak Boleh Berisi Uri yang Dikodekan Secara Permanen

Jangan mengodekan URL lingkungan secara permanen pada templat Anda. Sebaiknya gunakan fungsi lingkungan untuk mendapatkan URL ini secara dinamis selama penerapan. Untuk daftar host URL yang diblokir, lihat kasus pengujian.

Di Bicep, gunakan aturan Linter - tidak ada URL lingkungan yang dikodekan secara permanen.

Contoh berikut gagal karena URL dikodekan secara permanen.

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

Pengujian juga gagal ketika digunakan dengan concat atau uri.

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

Contoh berikut lolos.

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

Lokasi menggunakan parameter

Nama pengujian: Lokasi Tidak Boleh Dikodekan Secara Permanen

Untuk mengatur lokasi sumber daya, templat Anda harus memiliki parameter bernama location dengan jenis yang diatur ke string. Di templat utama, azuredeploy.json atau mainTemplate.json, parameter ini dapat default ke lokasi grup sumber daya. Dalam templat yang ditautkan atau berlapis, parameter lokasi seharusnya tidak boleh memiliki lokasi default.

Pengguna templat mungkin memiliki akses terbatas ke wilayah di mana mereka dapat membuat sumber daya. Lokasi sumber daya yang dikodekan secara permanen mungkin menghalangi pengguna untuk membuat sumber daya. Ekspresi "[resourceGroup().location]" dapat memblokir pengguna jika grup sumber daya dibuat di wilayah yang tidak dapat diakses pengguna. Pengguna yang diblokir tidak dapat menggunakan templat.

Dengan menyediakan parameter location yang default ke lokasi grup sumber daya, pengguna dapat menggunakan nilai default jika ingin tetapi juga menentukan lokasi yang berbeda.

Di Bicep, gunakan aturan Linter - tidak ada ekspresi lokasi di luar nilai default parameter.

Contoh berikut gagal karena sumber daya location diatur ke 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"
      }
    }
  ]
}

Contoh berikutnya menggunakan parameter location tetapi gagal dalam pengujian ini karena parameter lokasi diatur default ke lokasi yang dikodekan secara permanen.

{
  "$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": {}
}

Contoh berikut lolos ketika templat digunakan sebagai templat utama. Buat parameter yang default ke lokasi grup sumber daya tetapi memungkinkan pengguna untuk memberikan nilai yang berbeda.

{
  "$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": {}
}

Catatan

Jika contoh sebelumnya digunakan sebagai templat yang ditautkan, maka pengujian gagal. Saat digunakan sebagai templat tertaut, hapus nilai default.

Sumber daya harus memiliki lokasi

Nama uji: Sumber Daya Harus Memiliki Lokasi

Lokasi untuk sumber daya harus diatur ke ekspresi templat atau global. Ekspresi templat biasanya akan menggunakan parameter location yang dijelaskan dalam Lokasi menggunakan parameter.

Di Bicep, gunakan aturan Linter - tidak ada lokasi yang dikodekan secara permanen.

Contoh berikut gagal dalam pengujian ini karena location bukan merupakan ekspresi atau 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": {}
}

Contoh berikut lolos karena sumber daya location diatur ke 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": {}
}

Contoh berikutnya juga lolos karena parameter location menggunakan ekspresi. Sumber daya location menggunakan nilai ekspresi.

{
  "$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": {}
}

Ukuran komputer virtual menggunakan parameter

Nama uji: Ukuran Komputer Virtual Harus Berupa Parameter

Jangan kodekan secara permanen hardwareProfilevmSize objek. Tes gagal ketika hardwareProfile dihilangkan atau berisi nilai yang dikodekan secara permanen. Berikan parameter sehingga pengguna templat Anda dapat memodifikasi ukuran komputer virtual yang disebarkan. Untuk informasi selengkapnya, lihat Microsoft.Compute virtualMachines.

Contoh berikut gagal karena hardwareProfilevmSize objek dikodekan secara permanen.

"resources": [
  {
    "type": "Microsoft.Compute/virtualMachines",
    "apiVersion": "2020-12-01",
    "name": "demoVM",
    "location": "[parameters('location')]",
    "properties": {
      "hardwareProfile": {
        "vmSize": "Standard_D2_v3"
      }
    }
  }
]

Contoh lolos jika parameter menetapkan nilai untuk vmSize:

"parameters": {
  "vmSizeParameter": {
    "type": "string",
    "defaultValue": "Standard_D2_v3",
    "metadata": {
      "description": "Size for the virtual machine."
    }
  }
}

Lalu, hardwareProfile menggunakan ekspresi untuk vmSize untuk merujuk ke nilai parameter:

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

Nilai min dan maks berupa angka

Nama pengujian: Nilai Min Dan Maks Berupa Angka

Saat Anda menetapkan parameter dengan minValue dan maxValue, tentukan mereka sebagai angka. Anda harus menggunakan minValue dan maxValue sebagai pasangan atau pengujian akan gagal.

Contoh berikut gagal karena minValue dan maxValue adalah string.

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

Contoh berikut gagal karena hanya minValue yang digunakan.

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

Contoh berikut lolos karena minValue dan maxValue adalah angka.

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

Parameter artefak didefinisikan dengan benar

Nama pengujian: parameter artefak

Ketika Anda menyertakan parameter untuk _artifactsLocation dan _artifactsLocationSasToken, gunakan default dan jenis yang benar. Ketentuan berikut harus dipenuhi untuk dapat lolos pengujian ini:

  • jika Anda memberikan satu parameter, Anda harus memberikan yang lainnya juga.
  • _artifactsLocation harus berupa string.
  • _artifactsLocation harus memiliki nilai default dalam templat utama.
  • _artifactsLocation tidak boleh memiliki nilai default dalam templat berlapis.
  • _artifactsLocation harus memiliki salah satu dari "[deployment().properties.templateLink.uri]" atau URL repositori mentah untuk nilai defaultnya.
  • _artifactsLocationSasToken harus berupa secureString.
  • _artifactsLocationSasToken hanya dapat memiliki untai (karakter) kosong untuk nilai defaultnya.
  • _artifactsLocationSasToken tidak boleh memiliki nilai default dalam templat berlapis.

Di Bicep, gunakan aturan Linter - parameter artefak.

Variabel yang dinyatakan harus digunakan

Nama pengujian: Variabel Harus Direferensikan

Pengujian ini menemukan variabel yang tidak digunakan dalam templat atau tidak digunakan dalam ekspresi yang valid. Untuk menghindari kebingungan pada templat Anda, hapus variabel apa pun yang ditentukan tetapi tidak digunakan.

Variabel yang menggunakan elemen copy untuk iterasi nilai harus dirujuk. Untuk informasi selengkapnya, lihat Iterasi variabel dalam templat ARM.

Di Bicep, gunakan aturan Linter - tidak ada variabel yang tidak digunakan.

Contoh berikut gagal karena variabel yang menggunakan elemen copy tidak dirujuk.

{
  "$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": {}
}

Contoh berikut gagal karena ekspresi yang merujuk variabel tidak memiliki kurung siku awal ([).

"outputs": {
  "outputVariable": {
    "type": "string",
    "value": " variables('varExample')]"
  }
}

Contoh berikut lolos karena variabel dirujuk di 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')]"
    }
  }
}

Contoh berikut lolos karena ekspresi valid.

"outputs": {
  "outputVariable": {
    "type": "string",
    "value": "[variables('varExample')]"
  }
}

Variabel dinamis tidak boleh menggunakan concat

Nama pengujian: Referensi Variabel Dinamis Tidak Boleh Menggunakan Concat

Terkadang Anda perlu secara dinamis membangun variabel berdasarkan nilai variabel atau parameter lain. Jangan gunakan fungsi concat saat mengatur nilai. Sebagai gantinya, gunakan objek yang menyertakan opsi yang tersedia dan secara dinamis mendapatkan salah satu properti dari objek selama penyebaran.

Contoh berikut lolos. Variabel currentImage diatur secara dinamis selama penerapan.

{
  "$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')]"
    }
  }
}

Menggunakan versi API terbaru

Nama pengujian: apiVersions Harus yang Terbaru

Versi API untuk setiap sumber daya harus menggunakan versi terbaru yang dikodekan secara permanen. Pengujian ini mengevaluasi versi API di templat Anda terhadap versi penyedia sumber daya di cache toolkit. Versi API yang berusia kurang dari dua tahun sejak tanggal pengujian dijalankan dianggap baru-baru ini. Jangan gunakan versi pratinjau saat versi yang lebih baru tersedia.

Peringatan bahwa versi API tidak ditemukan hanya menunjukkan versi tidak termasuk dalam cache toolkit. Menggunakan versi terbaru dari API, yang direkomendasikan, dapat menghasilkan peringatan.

Pelajari selengkapnya tentang cache toolkit.

Di Bicep, gunakan aturan Linter - gunakan versi API terbaru.

Contoh berikut gagal karena versi API lebih dari dua tahun lamanya.

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

Contoh berikut gagal karena versi pratinjau digunakan saat versi yang lebih baru tersedia.

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

Contoh berikut lolos karena ini adalah versi terbaru yang bukan merupakan versi pratinjau.

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

Menggunakan versi API yang dikodekan secara permanen

Nama pengujian: Penyedia apiVersions Tidak Diizinkan

Versi API untuk jenis sumber daya menentukan properti mana yang tersedia. Berikan versi API yang dikodekan secara permanen di templat Anda. Jangan mengambil versi API yang ditentukan selama penerapan karena Anda tidak akan tahu properti mana yang tersedia.

Contoh berikut gagal.

"resources": [
  {
    "type": "Microsoft.Compute/virtualMachines",
    "apiVersion": "[providers('Microsoft.Compute', 'virtualMachines').apiVersions[0]]",
    ...
  }
]

Contoh berikut lolos.

"resources": [
  {
    "type": "Microsoft.Compute/virtualMachines",
    "apiVersion": "2020-12-01",
    ...
  }
]

Properti tidak boleh kosong

Nama pengujian: Templat Tidak Boleh Kosong

Jangan mengodekan properti secara permanen ke nilai kosong. Nilai kosong termasuk untai (karakter), objek, atau larik yang kosong dan tidak berlaku. Jika properti diatur ke nilai kosong, hapus properti tersebut dari templat Anda. Anda dapat mengatur properti ke nilai kosong selama penyebaran, seperti melalui parameter.

Properti template dalam templat berlapis dapat menyertakan properti kosong. Untuk informasi selengkapnya tentang templat bertumpuk, lihat Penerapan Microsoft.Resources.

Contoh berikut gagal karena ada properti kosong.

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

Contoh berikut lolos karena properti menyertakan nilai.

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

Menggunakan fungsi ID Sumber Daya

Nama pengujian: ID Harus Berasal dari ResourceID

Ketika menentukan ID sumber daya, gunakan salah satu fungsi ID sumber daya. Fungsi yang diperbolehkan adalah:

Jangan gunakan fungsi concat untuk membuat ID sumber daya.

Di Bicep, gunakan aturan Linter - gunakan fungsi ID sumber daya.

Contoh berikut gagal.

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

Contoh berikut lolos.

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

Fungsi ResourceId memiliki parameter yang benar

Nama pengujian: ResourceIds tidak boleh berisi

Saat membuat ID sumber daya, jangan gunakan fungsi yang tidak diperlukan untuk parameter opsional. Secara default, fungsi resourceId menggunakan grup langganan dan sumber daya saat ini. Anda tidak perlu memberikan nilai-nilai tersebut.

Contoh berikut gagal karena Anda tidak perlu memberikan ID langganan dan nama grup sumber daya saat ini.

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

Contoh berikut lolos.

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

Pengujian ini berlaku untuk:

Untuk reference dan list*, pengujian dinyatakan gagal ketika Anda menggunakan concat untuk membangun ID sumber daya.

Praktik terbaik dependsOn

Nama pengujian: Praktik Terbaik DependsOn

Saat mengatur dependensi penyebaran, jangan gunakan fungsi jika untuk menguji kondisi. Jika satu sumber daya bergantung pada sumber daya yang disebarkan secara kondisional, atur dependensi seperti yang Anda lakukan pada sumber daya lain. Saat sumber daya kondisional tidak disebarkan, Azure Resource Manager secara otomatis menghapusnya dari dependensi yang diperlukan.

Elemen dependsOn tidak dapat dimulai dengan fungsi concat.

Di Bicep, gunakan aturan Linter - tidak ada entri dependsOn yang tidak perlu.

Contoh berikut gagal karena ini berisi fungsi if.

"dependsOn": [
  "[if(equals(parameters('newOrExisting'),'new'), variables('storageAccountName'), '')]"
]

Contoh berikut gagal karena dimulai dengan concat.

"dependsOn": [
  "[concat(variables('storageAccountName'))]"
]

Contoh berikut lolos.

"dependsOn": [
  "[variables('storageAccountName')]"
]

Penyebaran berlapis atau tertaut tidak dapat menggunakan debug

Nama pengujian: Sumber Daya Penyebaran Tidak Boleh Debug

Saat Anda menentukan templat berlapis atau bertaut dengan tipe sumber daya Microsoft.Resources/deployments, Anda dapat mengaktifkan debugging. Debugging digunakan ketika Anda perlu menguji template tetapi dapat mengekspos informasi sensitif. Sebelum templat digunakan dalam produksi, matikan debugging. Anda dapat menghapus objek debugSetting atau mengubah properti detailLevel ke none.

Contoh berikut gagal.

"debugSetting": {
  "detailLevel": "requestContent"
}

Contoh berikut lolos.

"debugSetting": {
  "detailLevel": "none"
}

Nama pengguna admin tidak boleh bernilai harfiah

Nama pengujian: adminUsername Tidak Boleh Harfiah

Ketika mengatur adminUserName, jangan gunakan nilai harfiah. Buat parameter untuk nama pengguna dan gunakan ekspresi untuk merujuk nilai parameter.

Di Bicep, gunakan aturan Linter - nama pengguna admin tidak boleh harfiah.

Contoh berikut gagal dengan nilai harfiah.

"osProfile":  {
  "adminUserName": "myAdmin"
}

Contoh berikut lolos dengan ekspresi.

"osProfile": {
  "adminUsername": "[parameters('adminUsername')]"
}

Gunakan gambar komputer virtual terbaru

Nama uji: Gambar Komputer Virtual Harus Menggunakan Versi Terbaru

Tes ini dinonaktifkan, tetapi output menunjukkan bahwa ini lolos. Praktik terbaik adalah memeriksa templat Anda untuk kriteria berikut:

Jika templat Anda menyertakan komputer virtual dengan gambar, pastikan templat tersebut menggunakan gambar dengan versi terbaru.

Di Bicep, gunakan aturan Linter - gunakan gambar VM yang stabil.

Menggunakan gambar komputer virtual yang stabil

Nama pengujian: Komputer Virtual Tidak Boleh Pratinjau

Komputer virtual tidak boleh menggunakan gambar pratinjau. Pengujian memeriksa storageProfile untuk memverifikasi bahwa imageReference tidak menggunakan string yang berisi pratinjau. Dan pratinjau tersebut tidak digunakan di imageReference properti offer, sku, atau version.

Untuk informasi selengkapnya tentang properti imageReference, lihat Microsoft.Compute virtualMachines dan Microsoft.Compute virtualMachineScaleSets.

Di Bicep, gunakan aturan Linter - gunakan gambar VM yang stabil.

Contoh berikut gagal karena imageReference adalah string yang berisi pratinjau.

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

Contoh berikut gagal saat pratinjau digunakan di offer, sku, atau version.

"properties": {
  "storageProfile": {
    "imageReference": {
      "publisher": "Canonical",
      "offer": "UbuntuServer_preview",
      "sku": "16.04-LTS-preview",
      "version": "preview"
    }
  }
}

Contoh berikut lolos.

"storageProfile": {
  "imageReference": {
    "publisher": "Canonical",
    "offer": "UbuntuServer",
    "sku": "16.04-LTS",
    "version": "latest"
  }
}

Jangan gunakan ekstensi ManagedIdentity

Nama pengujian: ManagedIdentityExtension tidak boleh digunakan

Jangan terapkan ekstensi ManagedIdentity ke komputer virtual. Ekstensi ini tidak digunakan lagi pada tahun 2019 dan sejak saat itu tidak boleh lagi digunakan.

Output tidak dapat menyertakan rahasia

Nama pengujian: Output Tidak Boleh Berisi Rahasia

Jangan sertakan nilai apa pun di bagian outputs yang berpotensi mengekspos rahasia. Misalnya, buat parameter bertipe secureString atau secureObject, atau daftar* fungsi seperti listKeys.

Output dari templat disimpan dalam riwayat penyebaran, sehingga pengguna jahat dapat menemukan informasi tersebut.

Di Bicep, gunakan aturan Linter - output tidak boleh berisi rahasia.

Contoh berikut gagal karena menyertakan parameter aman dalam nilai output.

{
  "$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'))]"
    }
  }
}

Contoh berikut gagal karena menggunakan fungsi daftar* dalam output.

{
  "$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')]"
    }
  }
}

Menggunakan protectedSettings untuk rahasia commandToExecute

Nama pengujian: CommandToExecute Harus Menggunakan ProtectedSettings Untuk Rahasia

Untuk sumber daya dengan tipe CustomScript, gunakan protectedSettings terenkripsi saat commandToExecute menyertakan data rahasia seperti kata sandi. Misalnya, data rahasia dapat digunakan dalam parameter mana dengan tipe secureString atau secureObject, daftar* fungsi seperti listKeys, atau naskah kustom.

Jangan gunakan data rahasia dalam objek settings karena menggunakan teks yang jelas. Untuk informasi selengkapnya, lihat Microsoft.Compute virtualMachines/extensions, Windows, atau Linux.

Di Bicep, gunakan aturan Linter - gunakan protectedSettings untuk rahasia commandToExecute.

Contoh berikut gagal karena settings menggunakan commandToExecute dengan parameter aman.

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

Contoh berikut gagal karena settings menggunakan commandToExecute dengan fungsi listKeys.

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

Contoh berikut lolos karena protectedSettings menggunakan commandToExecute dengan parameter aman.

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

Contoh berikut lolos karena protectedSettings menggunakan commandToExecute dengan fungsi listKeys.

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

Menggunakan versi API terbaru dalam fungsi referensi

Nama pengujian: apiVersions Harus yang Terbaru Dalam Fungsi Referensi

Versi API yang digunakan di fungsi referensi harus terbaru dan bukan versi pratinjau. Pengujian ini mengevaluasi versi API di templat Anda terhadap versi penyedia sumber daya di cache toolkit. Versi API yang berusia kurang dari dua tahun sejak tanggal pengujian dijalankan dianggap baru-baru ini.

Peringatan bahwa versi API tidak ditemukan hanya menunjukkan versi tidak termasuk dalam cache toolkit. Menggunakan versi terbaru dari API, yang direkomendasikan, dapat menghasilkan peringatan.

Pelajari selengkapnya tentang cache toolkit.

Contoh berikut gagal karena versi API lebih dari dua tahun lamanya.

"outputs": {
  "stgAcct": {
    "type": "string",
    "value": "[reference(resourceId(parameters('storageResourceGroup'), 'Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2019-06-01')]"
  }
}

Contoh berikut gagal karena versi API adalah versi pratinjau.

"outputs": {
  "stgAcct": {
    "type": "string",
    "value": "[reference(resourceId(parameters('storageResourceGroup'), 'Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2020-08-01-preview')]"
  }
}

Contoh berikut lolos karena versi API kurang dari dua tahun lamanya dan bukan versi pratinjau.

"outputs": {
  "stgAcct": {
    "type": "string",
    "value": "[reference(resourceId(parameters('storageResourceGroup'), 'Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2021-02-01')]"
  }
}

Menggunakan tipe dan nama dalam fungsi resourceId

Nama pengujian: Sumber Daya Tidak Boleh Ambigu

Tes ini dinonaktifkan, tetapi output menunjukkan bahwa ini lolos. Praktik terbaik adalah memeriksa templat Anda untuk kriteria berikut:

resourceId harus menyertakan tipe sumber daya dan nama sumber daya. Pengujian ini menemukan semua fungsi resourceId templat dan memverifikasi bahwa sumber daya digunakan dalam templat dengan sintaks yang benar. Jika tidak, fungsinya dianggap ambigu.

Misalnya, fungsi resourceId dianggap ambigu:

  • Ketika sumber daya tidak ditemukan di templat dan grup sumber daya tidak ditentukan.
  • Jika sumber daya menyertakan kondisi dan grup sumber daya tidak ditentukan.
  • Jika sumber daya terkait berisi beberapa tetapi tidak semua segmen nama. Misalnya, sumber daya anak berisi lebih dari satu segmen nama. Untuk informasi selengkapnya, lihat keterangan resourceId.

Gunakan lingkup dalam untuk penerapan berlapis parameter aman

Nama pengujian: Parameter Aman Dalam Penerapan Berlapis

Gunakan objek expressionEvaluationOptions templat berlapis dengan ruang lingkup inner untuk menilai ekspresi yang berisi parameter aman atau dengan tipe secureString atau secureObject atau daftar* fungsi seperti listKeys. Jika ruang lingkup outer digunakan, ekspresi dievaluasi dalam teks yang jelas dalam lingkup templat induk. Nilai aman kemudian terlihat oleh siapa saja yang memiliki akses ke riwayat penerapan. Nilai default expressionEvaluationOptions adalah outer.

Untuk informasi selengkapnya tentang templat berlapis, lihat penerapan Microsoft.Resources dan Ruang lingkup evaluasi ekspresi di templat berlapis.

Di Bicep, gunakan aturan Linter - param aman dalam penyebaran berlapis.

Contoh berikut gagal karena expressionEvaluationOptions menggunakan ruang lingkup outer untuk menilai parameter aman atau fungsi list*.

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

Contoh berikut lolos karena expressionEvaluationOptions menggunakan ruang lingkup inner untuk menilai parameter aman atau fungsi list*.

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

Langkah berikutnya