حالات الاختبار لقوالب ARM
توضح هذه المقالة الاختبارات التي يتم تشغيلها باستخدام مجموعة أدوات اختبار القالب لقوالب Azure Resource Manager (قوالب ARM). وتوفر أمثلة على اجتياز الاختبار أو فشله ويتضمن اسم كل اختبار. لمزيدٍ من المعلومات حول كيفية إجراء الاختبارات أو كيفية إجراء اختبار معين، راجع Test parameters.
استخدام المخطط الصحيح
اسم الاختبار: المخطط DeploymentTemplate هو المخطط الصحيح
في قالبك، يجب تحديد قيمة مخطط صالحة.
فشل المثال التالي لأن المخطط غير صالح.
{
"$schema": "https://schema.management.azure.com/schemas/2019-01-01/deploymentTemplate.json#",
}
يعرض المثال التالي تحذيراً لأنه تم إهمال الإصدار 2015-01-01
للمخطط ولا تتم صيانته الآن.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
}
مر المثال التالي نظراً لاستخدام مخطط صالح.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
}
يجب تعيين خاصية schema
القالب إلى أحد المخططات التالية:
https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#
https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#
https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#
https://schema.management.azure.com/schemas/2019-08-01/tenantDeploymentTemplate.json#
https://schema.management.azure.com/schemas/2019-08-01/managementGroupDeploymentTemplate.json
يلزم استخدام المعلمات المعلنة
اسم الاختبار: يجب الرجوع إلى المعلمات
يبحث هذا الاختبار عن المعلمات غير المستخدمة في القالب أو المعلمات التي لم يتم استخدامها في تعبير صالح.
لتقليل التشويش في القالب، احذف أية معلمات تم تعريفها ولكن لا يتم استخدامها. يؤدي التخلص من المعلمات غير المستخدمة إلى تبسيط عمليات نشر القوالب لأنك لست مضطراً إلى توفير قيم غير ضرورية.
في Bicep، استخدم قاعدة Linter - لا توجد معلمات غير مستخدمة.
فشل المثال التالي نظراً لافتقاد التعبير الذي يشير إلى معلمة إلى القوس المربع البادئ ([
).
"resources": [
{
"location": " parameters('location')]"
}
]
وقد مر المثال التالي لأن التعبير صالح.
"resources": [
{
"location": "[parameters('location')]"
}
]
لا يمكن احتواء المعلمات الآمنة على تعليمات برمجية افتراضية مضمّنة
اسم الاختبار: لا يمكن أن يكون لمعلمات السلسلة الآمنة قيم افتراضية
لا تقدم قيمة تعليمات برمجية افتراضية مضمّنة لمعلمة آمنة في قالبك. ويمكن أن تحتوي المعلمة الآمنة على سلسلة فارغة كقيمة افتراضية أو تستخدم الدالة newGuid في التعبير.
يمكنك استخدام الأنواع secureString
أو secureObject
مع المعلمات التي تحتوي على قيم حساسة، مثل كلمات المرور. وعند استخدام معلمة نوع آمن، لا يتم تسجيل قيمة المعلمة أو تخزينها في محفوظات النشر. ويساعد هذا الإجراء على منع المستخدم الضار من اكتشاف القيمة الحساسة.
عند توفير قيمة افتراضية، فإن هذه القيمة يمكن اكتشافها بواسطة أي شخص يمكنه الوصول إلى القالب أو محفوظات النشر.
في Bicep، استخدم قاعدة Linter - المعلمة الآمنة الافتراضية.
المثال التالي يفشل.
"parameters": {
"adminPassword": {
"defaultValue": "HardcodedPassword",
"type": "secureString"
}
}
مر المثال التالي.
"parameters": {
"adminPassword": {
"type": "secureString"
}
}
وقد مر المثال التالي نظراً لاستخدام الدالة newGuid
.
"parameters": {
"secureParameter": {
"type": "secureString",
"defaultValue": "[newGuid()]"
}
}
لا يمكن أن تكون عناوين URL للبيئة تعليمات برمجية مضمّنة
اسم الاختبار: DeploymentTemplate لا يحتوي على عنوان URL مضمن داخل تعليمة برمجية
لا تُضمن عناوين URL للبيئة داخل تعليمة برمجية في قالبك. يمكنك بدلاً من ذلك استخدم الدالة environment للحصول على عناوين URL بشكل ديناميكي أثناء النشر. للحصول على قائمة بمضيفي عناوين URL المحظورة، راجع حالة الاختبار.
في Bicep، استخدم قاعدة Linter - لا يوجد عنوان URL للبيئة المشفرة.
فشل المثال التالي لأن عنوان URL مضمن داخل التعليمة البرمجية.
"variables":{
"AzureURL":"https://management.azure.com"
}
كما فشل الاختبار أيضاً عند استخدامه مع concat أو uri.
"variables":{
"AzureSchemaURL1": "[concat('https://','gallery.azure.com')]",
"AzureSchemaURL2": "[uri('gallery.azure.com','test')]"
}
مر المثال التالي.
"variables": {
"AzureSchemaURL": "[environment().gallery]"
}
استخدام الموقع للمعلمة
اسم الاختبار: لا يكون الموقع تعليمة برمجية مضمنة
لتعيين موقع مورد، يجب أن تحتوي قوالبك على معلمة باسم location
مع تعيين النوع إلى string
. في القالب الرئيسي، azuredeploy.json أو mainTemplate.json، يمكن أن تأخذ هذه المعلمة القيمة الافتراضية لموقع مجموعة الموارد. في القوالب المرتبطة أو المتداخلة، لا يجب أن تأخذ معلمة الموقع "الموقع الافتراضي" كقيمة لها.
قد يكون لمستخدمي القالب وصول محدود إلى المناطق حيث يمكنهم إنشاء الموارد. وقد يمنع موقع المورد المضمن داخل التعليمة البرمجية المستخدمين من إنشاء مورد. قد يمنع التعبير "[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": {}
}
استخدام حجم الجهاز الظاهري للمعلمة
اسم الاختبار: يجب أن يكون حجم الجهاز الظاهري معلمة
لا تقم بتضمين الكائن 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')]"
}
}
}
]
قيم الحد الأدنى والحد الأقصى تكون أرقاماً
اسم الاختبار: قيم الحد الأدنى والحد الأقصى تكون أرقاماً
عند تعريف المعلمة باستخدام minValue
وmaxValue
، حددها كأرقام. يجب استخدام minValue
وmaxValue
كزوج أو سيفشل الاختبار.
فشل المثال التالي نظراً لأنه تم تحديد قيم minValue
وmaxValue
كسلاسل.
"exampleParameter": {
"type": "int",
"minValue": "0",
"maxValue": "10"
}
فشل المثال التالي نظراً لأنه تم استخدام minValue
فقط.
"exampleParameter": {
"type": "int",
"minValue": 0
}
قد مر المثال التالي نظراً لأنه تم تحديد قيم minValue
وmaxValue
أرقاماً.
"exampleParameter": {
"type": "int",
"minValue": 0,
"maxValue": 10
}
معلمة البيانات الاصطناعية معرفة بشكل صحيح
اسم الاختبار: معلمة البيانات الاصطناعية
عند تضمين معلمات لـ _artifactsLocation
و_artifactsLocationSasToken
، استخدم الأنواع والإعدادات الافتراضية الصحيحة. ويجب استيفاء الشروط التالية لاجتياز هذا الاختبار:
- إذا قمت بتوفير معلمة واحدة، يجب توفير الأخرى.
- يجب أن تكون
_artifactsLocation
من النوعstring
. - يجب أن يكون لـ
_artifactsLocation
قيمة افتراضية في القالب الرئيسي. - لا ينبغي أن يكون لـ
_artifactsLocation
قيمة افتراضية في القالب الرئيسي. - يجب أن يكون لـ
_artifactsLocation
إما"[deployment().properties.templateLink.uri]"
أو تكون قيمتها الافتراضية "عنوان URL لمستودع بسيط". - يجب أن تكون
_artifactsLocationSasToken
من النوعsecureString
. - يمكن أن تكون القيمة الافتراضية لـ
_artifactsLocationSasToken
فقط سلسلة فارغة. - لا ينبغي أن يكون لـ
_artifactsLocationSasToken
قيمة افتراضية في القالب الرئيسي.
في Bicep، استخدم قاعدة Linter - معلمات البيانات الاصطناعية.
استخدام المتغيرات المعلنة
اسم الاختبار: الرجوع إلى المعلمات
يبحث هذا الاختبار عن متغيرات غير مستخدمة في القالب أو غير مستخدمة في تعبير صالح. لتقليل التشويش في القالب الخاص بك، احذف أي متغيرات تم تعريفها ولكن لا يتم استخدامها.
يجب الإشارة إلى المتغيرات التي تستخدم عنصر copy
لتكرار القيم. للحصول على المزيد من المعلومات، راجع تكرار المتغير في قالب ARM.
في Bicep، استخدم قاعدة Linter - لا توجد متغيرات غير مستخدمة.
فشل المثال التالي نظراً لأنه لا تتم الإشارة إلى المتغير الذي يستخدم العنصر copy
.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"itemCount": {
"type": "int",
"defaultValue": 5
}
},
"variables": {
"copy": [
{
"name": "stringArray",
"count": "[parameters('itemCount')]",
"input": "[concat('item', copyIndex('stringArray', 1))]"
}
]
},
"resources": [],
"outputs": {}
}
فشل المثال التالي نظراً لافتقاد التعبير الذي يشير إلى معلمة إلى القوس المربع البادئ ([
).
"outputs": {
"outputVariable": {
"type": "string",
"value": " variables('varExample')]"
}
}
مر المثال التالي لأنه يُشار إلى المتغير في outputs
.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"itemCount": {
"type": "int",
"defaultValue": 5
}
},
"variables": {
"copy": [
{
"name": "stringArray",
"count": "[parameters('itemCount')]",
"input": "[concat('item', copyIndex('stringArray', 1))]"
}
]
},
"resources": [],
"outputs": {
"arrayResult": {
"type": "array",
"value": "[variables('stringArray')]"
}
}
}
وقد مر المثال التالي لأن التعبير صالح.
"outputs": {
"outputVariable": {
"type": "string",
"value": "[variables('varExample')]"
}
}
لا يستخدم المتغير الديناميكي "concat"
اسم الاختبار: لا تستخدم مراجع المتغير الديناميكي Concat
تحتاج أحياناً إلى تكوين متغير ديناميكياً بناءً على قيمة متغير أو معلمة أخرى. لا تستخدم الدالة concat عند تعيين القيمة. ويمكنك بدلاً من ذلك استخدام عنصر يتضمن الخيارات المتاحة واحصل ديناميكياً على إحدى الخصائص من الكائن أثناء النشر.
مر المثال التالي. يتم تعيين المتغير currentImage
ديناميكياً أثناء النشر.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"osType": {
"type": "string",
"allowedValues": [
"Windows",
"Linux"
]
}
},
"variables": {
"imageOS": {
"Windows": {
"image": "Windows Image"
},
"Linux": {
"image": "Linux Image"
}
},
"currentImage": "[variables('imageOS')[parameters('osType')].image]"
},
"resources": [],
"outputs": {
"result": {
"type": "string",
"value": "[variables('currentImage')]"
}
}
}
استخدم إصدار واجهة برمجة التطبيقات حديث
اسم الاختبار: يجب أن apiVersions حديثاً
يجب أن يستخدم إصدار واجهة برمجة التطبيقات لكل مورد إصداراً حديثاً ويكون تعليمات برمجية مضمّنة كسلسلة. يُقيم الاختبار بتقييم إصدار واجهة برمجة التطبيقات في القالب مقابل إصدارات موفر المورد في ذاكرة التخزين المؤقت الخاصة بمجموعة الأدوات. يُعد إصدار واجهة برمجة التطبيقات الذي يقل عمره عن عامين من تاريخ تشغيل الاختبار حديثاً. ولا تستخدم الإصدار الأولي عندما يتوفر إصدار أحدث.
يشير التحذير من عدم العثور على إصدار واجهة برمجة التطبيقات فقط إلى أن الإصدار غير مدرج في ذاكرة التخزين المؤقت لمجموعة الأدوات. ويمكنك إنشاء التحذير باستخدام أحدث إصدار من واجهة برمجة التطبيقات، وهذا هو المستحسن.
تعرف على المزيد حول ذاكرة التخزين المؤقت لمجموعة الأدوات.
في Bicep، استخدم قاعدة Linter - استخدم إصدارات واجهة برمجة التطبيقات الأخيرة.
فشل المثال التالي نظراً لأن إصدار واجهة برمجة التطبيقات مر عليه أكثر من عامين.
"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')]"
}
]
استخدام إصدار واجهة برمجة التطبيقات المضمن داخل تعليمات برمجية مضمّنة
اسم الاختبار: لا يُسمح بموفري apiVersions
يحدد إصدار واجهة برمجة التطبيقات لنوع مورد الخصائص المتوفرة. ويوفر إصدار واجهة برمجة التطبيقات المضمن داخل تعليمات برمجية مضمّنة في قالبك. لا تقم باسترداد إصدار واجهة برمجة التطبيقات الذي يتم تحديده أثناء النشر لأنك لن تعرف الخصائص المتوفرة.
المثال التالي يفشل.
"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'))]"
}
ينطبق هذا الاختبار على:
بالنسبة لـ reference
وlist*
، فشل الاختبار عند استخدامها concat
لإنشاء معرف المورد.
أفضل ممارسات dependsOn
اسم الاختبار: أفضل ممارسات DependsOn
عند تعيين تبعيات النشر، لا تستخدم الدالة if لاختبار شرط. إذا كان أحد الموارد يعتمد على مورد تم نشره بشروط، فقم بتعيين التبعية كما تفعل مع أي مورد. عندما لا يتم نشر مورد شرطي، يقوم Azure Resource Manager بإزالتها تلقائياً من التبعيات المطلوبة.
لا يمكن أن يبدأ العنصر dependsOn
بدالة concat.
في Bicep، استخدم قاعدة Linter - لا توجد إدخالات dependsOn غير ضرورية.
فشل المثال التالي نظراً لأنه يحتوي على دالة if
.
"dependsOn": [
"[if(equals(parameters('newOrExisting'),'new'), variables('storageAccountName'), '')]"
]
فشل المثال التالي نظراً لأنه يبدأ بدالة concat
.
"dependsOn": [
"[concat(variables('storageAccountName'))]"
]
مر المثال التالي.
"dependsOn": [
"[variables('storageAccountName')]"
]
لا يمكن استخدام التصحيح في عمليات النشر المتداخلة أو المرتبطة التصحيح
اسم الاختبار: لا يتم تصحيح الأخطاء في موارد النشر
عند تعريف قالب متداخل أو مرتبط باستخدام نوع المورد Microsoft.Resources/deployments
، يمكنك تمكين تصحيح الأخطاء. يتم استخدام تصحيح الأخطاء عند الحاجة إلى اختبار قالب ولكن يمكن أن يعرض معلومات حساسة. قبل استخدام القالب في بيئة التشغيل، قم بإيقاف تشغيل تصحيح الأخطاء. يمكنك إزالة الكائن debugSetting
أو تغيير خاصية detailLevel
إلى none
.
المثال التالي يفشل.
"debugSetting": {
"detailLevel": "requestContent"
}
مر المثال التالي.
"debugSetting": {
"detailLevel": "none"
}
لا تكون أسماء المستخدمين المسؤولين قيمة حرفية
اسم الاختبار: لا يكون adminUsername قيمة حرفية
عند تعيين adminUserName
، لا تستخدم قيمة حرفية. إنشاء معلمة لاسم المستخدم واستخدام تعبير للإشارة إلى قيمة المعلمة.
في Bicep، استخدم قاعدة Linter - يجب ألا يكون اسم مستخدم المسؤول حرفيا.
فشل المثال التالي نظراً للقيمة الحرفية.
"osProfile": {
"adminUserName": "myAdmin"
}
وقد مر المثال التالي نظراً لاستخدام تعبير.
"osProfile": {
"adminUsername": "[parameters('adminUsername')]"
}
استخدام أحدث نسخة جهاز ظاهري
اسم الاختبار: استخدام نُسخ الجهاز الظاهري لأحدث إصدار
تم تعطيل هذا الاختبار، ولكن تُظهر المخرجات أنه قد مرّ. تُعد أفضل الممارسات بمثابة آلية تحقيق قالبك للمعايير التالية:
إذا كان قالبك يتضمن جهازاً ظاهرياً من نسخة، فتأكد من أنه يستخدم أحدث إصدار من النسخة.
في Bicep، استخدم قاعدة Linter - استخدم صورة الجهاز الظاهري الثابتة.
استخدام نُسخ جهاز ظاهري مستقرة
اسم الاختبار: لا تعمل الأجهزة الظاهرية بإصدار أولى
لا يجب أن تستخدم الأجهزة الظاهرية نُسخ الإصدار الأولي. يتحقق الاختبار من storageProfile
للتحقق من أن imageReference
لا يستخدم سلسلة تحتوي على إصدار أولي. ولا يتم استخدام الإصدار الأولي في الخصائص imageReference
بالقيم offer
وsku
أو version
.
لمزيد من المعلومات حول خاصية imageReference
، راجع Microsoft.Compute virtualMachines وMicrosoft.Compute VirtualMachineScaleSets.
في Bicep، استخدم قاعدة Linter - استخدم صورة الجهاز الظاهري الثابتة.
فشل المثال التالي نظراً لأن imageReference
تأخذ قيمة سلسلة تحتوي على إصدار أولي.
"properties": {
"storageProfile": {
"imageReference": "latest-preview"
}
}
فشل المثال التالي عند استخدام إصدار أولي في offer
وsku
أو version
.
"properties": {
"storageProfile": {
"imageReference": {
"publisher": "Canonical",
"offer": "UbuntuServer_preview",
"sku": "16.04-LTS-preview",
"version": "preview"
}
}
}
مر المثال التالي.
"storageProfile": {
"imageReference": {
"publisher": "Canonical",
"offer": "UbuntuServer",
"sku": "16.04-LTS",
"version": "latest"
}
}
عدم استخدام ملحق ManagedIdentity
اسم الاختبار: عدم استخدام ملحق ManagedIdentity
لا تقم بتطبيق الملحق ManagedIdentity
على جهاز ظاهري. تم إهمال الملحق في عام 2019 ويجب عدم استخدامه بعد الآن.
عدم تضمين المخرجات أسراراً
اسم الاختبار: عدم تضمين المخرجات أسراراً
لا تقم بتضمين أي قيم في القسم outputs
الذي قد يكشف الأسرار. على سبيل المثال، معلمات آمنة من النوع secureString
أو secureObject
، أو الدوال list* مثل listKeys
.
يتم تخزين المخرجات من القالب في محفوظات النشر، بحيث لا يمكن للمستخدم الضار العثور على هذه المعلومات.
في Bicep، استخدم قاعدة Linter - يجب ألا تحتوي المخرجات على أسرار.
فشل المثال التالي لأنه يتضمن معلمة آمنة في قيمة الإخراج.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"secureParam": {
"type": "secureString"
}
},
"functions": [],
"variables": {},
"resources": [],
"outputs": {
"badResult": {
"type": "string",
"value": "[concat('this is the value ', parameters('secureParam'))]"
}
}
}
فشل المثال التالي نظراً لأنه يستخدم دالة list* في المخرجات.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageName": {
"type": "string"
}
},
"functions": [],
"variables": {},
"resources": [],
"outputs": {
"badResult": {
"type": "object",
"value": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageName')), '2021-02-01')]"
}
}
}
استخدام protectedSettings لأسرار commandToExecute
اسم الاختبار: استخدام CommandToExecute لـ ProtectedSettings للحصول على الأسرار
بالنسبة إلى الموارد من النوع CustomScript
، استخدم protectedSettings
المشفر عندما يتضمن commandToExecute
بيانات سرية مثل كلمة المرور. على سبيل المثال، يمكن استخدام البيانات السرية في معاملات آمنة من النوع secureString
أو secureObject
، ودوال list* مثل listKeys
أو البرامج النصية المخصصة.
ولا تستخدم البيانات السرية في الكائن settings
لأنه يستخدم نصاً واضحاً. لمزيد من المعلومات، راجع Microsoft.Compute virtualMachines/extension أو Windows أو Linux.
في Bicep، استخدم قاعدة Linter - استخدم protectedSettings ل commandToExecute secrets.
فشل المثال التالي نظراً لأن settings
يستخدم commandToExecute
مع معلمة آمنة.
"parameters": {
"adminPassword": {
"type": "secureString"
}
}
...
"properties": {
"type": "CustomScript",
"settings": {
"commandToExecute": "[parameters('adminPassword')]"
}
}
فشل المثال التالي نظراً لأن settings
يستخدم commandToExecute
مستخدماً الدالة listKeys
.
"properties": {
"type": "CustomScript",
"settings": {
"commandToExecute": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageName')), '2021-02-01')]"
}
}
قد مرّ المثال التالي نظراً لأن protectedSettings
يستخدم commandToExecute
مستخدماً معلمة آمنة.
"parameters": {
"adminPassword": {
"type": "secureString"
}
}
...
"properties": {
"type": "CustomScript",
"protectedSettings": {
"commandToExecute": "[parameters('adminPassword')]"
}
}
فشل المثال التالي نظراً لأن protectedSettings
يستخدم commandToExecute
مستخدماً الدالة listKeys
.
"properties": {
"type": "CustomScript",
"protectedSettings": {
"commandToExecute": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageName')), '2021-02-01')]"
}
}
استخدام إصدارات واجهة برمجة التطبيقات الأحدث في دوال reference
اسم الاختبار: يجب أن تكون apiVersions الأحدث في دوال المرجع
يجب أن يكون إصدار واجهة برمجة التطبيقات المستخدم في دالة reference حديثاً وليس إصداراً أولياً. يُقيم الاختبار بتقييم إصدار واجهة برمجة التطبيقات في القالب مقابل إصدارات موفر المورد في ذاكرة التخزين المؤقت الخاصة بمجموعة الأدوات. يُعد إصدار واجهة برمجة التطبيقات الذي يقل عمره عن عامين من تاريخ تشغيل الاختبار حديثاً.
يشير التحذير من عدم العثور على إصدار واجهة برمجة التطبيقات فقط إلى أن الإصدار غير مدرج في ذاكرة التخزين المؤقت لمجموعة الأدوات. ويمكنك إنشاء التحذير باستخدام أحدث إصدار من واجهة برمجة التطبيقات، وهذا هو المستحسن.
تعرف على المزيد حول ذاكرة التخزين المؤقت لمجموعة الأدوات.
فشل المثال التالي نظراً لأن إصدار واجهة برمجة التطبيقات مر عليه أكثر من عامين.
"outputs": {
"stgAcct": {
"type": "string",
"value": "[reference(resourceId(parameters('storageResourceGroup'), 'Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2019-06-01')]"
}
}
فشل المثال التالي نظراً لأن إصدار واجهة برمجة التطبيقات إصدار أولي.
"outputs": {
"stgAcct": {
"type": "string",
"value": "[reference(resourceId(parameters('storageResourceGroup'), 'Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2020-08-01-preview')]"
}
}
قد مر المثال التالي لأن إصدار واجهة برمجة التطبيقات مر عليه أقل من عامين وليس إصداراً أولياً.
"outputs": {
"stgAcct": {
"type": "string",
"value": "[reference(resourceId(parameters('storageResourceGroup'), 'Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2021-02-01')]"
}
}
استخدام نوع واسم في دوال resourceId
اسم الاختبار: عدم غموض الموارد
تم تعطيل هذا الاختبار، ولكن تُظهر المخرجات أنه قد مرّ. تُعد أفضل الممارسات بمثابة آلية تحقيق قالبك للمعايير التالية:
يجب أن يتضمن resourceId نوع المورد واسمه. يبحث هذا الاختبار عن جميع دوال القالب resourceId
ويتحقق من استخدام المورد في القالب باستخدام البناء الصحيح للجملة. وإلا تعتبر الدالة غامضة.
على سبيل المثال، تعتبر الدالة resourceId
غامضة:
- في حالة عدم العثور على مورد في القالب ولم يتم تحديد مجموعة موارد.
- إذا كان المورد يتضمن شرطاً ولم يتم تحديد مجموعة موارد.
- إذا كان تضمن مورد مرتبطاً ببعض مقاطع الاسم وليس كلها. على سبيل المثال، يحتوي مورد تابع على أكثر من مقطع لاسم واحد. لمزيد من المعلومات، راجع ملاحظات على resourceId.
استخدام النطاق الداخلي للمعلمات الآمنة للنشر المتداخل
اسم الاختبار: المعلمات الآمنة في عمليات النشر المتداخلة
استخدم كائن القالب المتداخل expressionEvaluationOptions
مع النطاق inner
لتقييم التعبيرات التي تحتوي على معلمات آمنة من النوع secureString
أو secureObject
أو دوال 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"
}
}
}
]
الخطوات التالية
- للتعرف على كيفية تشغيل مجموعة أدوات الاختبار، راجع استخدام مجموعة أدوات اختبار قالب ARM.
- للحصول على وحدة Learn النمطية التي تغطي استخدام مجموعة أدوات الاختبار، راجع معاينة التغييرات والتحقق من صحة موارد Azure باستخدام مجموعة أدوات اختبار نموذج "what-if" و"ARM".
- لاختبار ملفات المعلمات، راجع حالات الاختبار لملفات المعلمات.
- لإنشاء اختبارات تعريف المستخدم، راجع حالات الاختبار الخاصة بـ createUiDefinition.json.
- للتعرف على الاختبارات لكافة الملفات، راجع حالات الاختبار لكافة الملفات.