برنامج تعليمي: استخدام برامج التوزيع النصية لإنشاء شهادة موقعة ذاتيًا

تعرف على كيفية استخدام برامج توزيع القالب النصية في قوالب Azure Resource Manager (قوالب ARM). يمكن استخدام برامج التوزيع النصية لتنفيذ خطوات مخصصة لا يمكن تنفيذها بواسطة قوالب ARM. على سبيل المثال، إنشاء شهادة موقعة ذاتيًا. في هذا البرنامج التعليمي، ستنشئ قالبًا لتوزيع Azure key vault، ثم استخدام مورد Microsoft.Resources/deploymentScripts في نفس القالب لإنشاء شهادة، ثم إضافة الشهادة إلى key vault. لمعرفة المزيد حول برنامج التوزيع النصي، راجع استخدام برامج التوزيع النصية في قوالب ARM.

هام

تم إنشاء موردي برنامج توزيع نصي وحساب تخزين ومثيل حاوية في نفس مجموعة الموارد لتنفيذ البرنامج النصي واستكشاف الأخطاء وإصلاحها. عادة ما يتم حذف هذه الموارد بواسطة خدمة البرنامج النصي عندما يصل تنفيذ البرنامج النصي إلى حالة الإنهاء. تتم فوترتك مقابل الموارد حتى يتم حذف الموارد. لمعرفة المزيد، راجع تنظيف موارد برنامج التوزيع النصي.

يشمل البرنامج التعليمي المهام التالية:

  • افتح قالب التشغيل السريع
  • تحرير القالب
  • نشر القالب
  • تصحيح البرنامج النصي الفاشل
  • تنظيف الموارد

للحصول على وحدة Learn تغطي برامج التوزيع النصية، راجع توسيع قوالب ARM باستخدام برامج التوزيع النصية.

المتطلبات الأساسية

لإكمال هذه المقالة، تحتاج إلى الآتي:

فتح قالب "التشغيل السريع"

بدلاً من إنشاء قالب من البداية، يمكنك فتح قالب من قوالب Azure Quickstart. قوالب التشغيل السريع Azure عبارة عن مستودع لقوالب ARM.

يطلق على القالب المستخدَم في بدء التشغيل السريع هذا إنشاء Azure Key Vault وسر. يتم من خلال القالب إنشاء key vault، ثم يضيف سرًا إلى key vault.

  1. من Visual Studio Code، حدد ملف>فتح الملف.

  2. في اسم الملف، أَلصِق عنوان URL الآتي:

    https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/quickstarts/microsoft.keyvault/key-vault-create/azuredeploy.json
    
  3. حدد Open لفتح الملف.

  4. حدد ملف>حفظ باسم لحفظ نسخة من الملف باسم azuredeploy.json على جهاز الكمبيوتر المحلي.

تحرير القالب

بادر بإجراء التغييرات التالية على القالب:

تنظيف القالب (اختياري)

يضيف القالب الأصلي سرًا إلى key vault. لتبسيط البرنامج التعليمي، بادر بإزالة المورد التالي:

  • Microsoft.KeyVault/vaults/secrets

إزالة تعريفي المعلمتين التاليتين:

  • secretName
  • secretValue

إذا اخترت عدم إزالة هذه التعريفات، فأنت بحاجة إلى تحديد قيم المعلمة أثناء التوزيع.

تكوين نُهج الوصول إلى key vault

يضيف برنامج التوزيع النصي شهادة إلى key vault. تكوين نهج الوصول إلى key vault لإعطاء الإذن للهوية المُدارة:

  1. إضافة معلمة للحصول على معرف الهوية المدارة:

    "identityId": {
      "type": "string",
      "metadata": {
        "description": "Specifies the ID of the user-assigned managed identity."
      }
    },
    

    إشعار

    يتعذر على ملحق قالب Resource Manager من تعليمة Visual Studio البرمجية تنسيق برامج التوزيع النصية حتى الآن. لا تستخدم Shift+Alt+F لتنسيق موارد deploymentScripts، مثل الموارد التالية.

  2. بادر بإضافة معلمة لتكوين نُهج الوصول إلى key vault بحيث يمكن للهوية المدارة إضافة شهادات إلى key vault:

    "certificatesPermissions": {
      "type": "array",
      "defaultValue": [
        "get",
        "list",
        "update",
        "create"
      ],
      "metadata": {
      "description": "Specifies the permissions to certificates in the vault. Valid values are: all, get, list, update, create, import, delete, recover, backup, restore, manage contacts, manage certificate authorities, get certificate authorities, list certificate authorities, set certificate authorities, delete certificate authorities."
      }
    }
    
  3. تحديث نهج الوصول key valt الحالية إلى:

    "accessPolicies": [
      {
        "objectId": "[parameters('objectId')]",
        "tenantId": "[parameters('tenantId')]",
        "permissions": {
          "keys": "[parameters('keysPermissions')]",
          "secrets": "[parameters('secretsPermissions')]",
          "certificates": "[parameters('certificatesPermissions')]"
        }
      },
      {
        "objectId": "[reference(parameters('identityId'), '2018-11-30').principalId]",
        "tenantId": "[parameters('tenantId')]",
        "permissions": {
          "keys": "[parameters('keysPermissions')]",
          "secrets": "[parameters('secretsPermissions')]",
          "certificates": "[parameters('certificatesPermissions')]"
        }
      }
    ],
    

    هناك نهجان معرفان، أحدهما للمستخدم الذي سجل الدخول والآخر للهوية المدارة. يحتاج المستخدم الذي سجل الدخول إلى إذن القائمة فقط للتحقق من التوزيع. لتبسيط البرنامج التعليمي، يتم تعيين نفس الشهادة لكل من الهوية المُدارة والمستخدمين الذين سجلوا الدخول.

إضافة برنامج التوزيع النصي

  1. إضافة ثلاثة معلمات التي يتم استخدامها بواسطة برنامج التوزيع النصي:

    "certificateName": {
      "type": "string",
      "defaultValue": "DeploymentScripts2019"
    },
    "subjectName": {
      "type": "string",
      "defaultValue": "CN=contoso.com"
    },
    "utcValue": {
      "type": "string",
      "defaultValue": "[utcNow()]"
    }
    
  2. إضافة مورد deploymentScripts

    إشعار

    لأن برامج التوزيع النصية المضمنة موجودة ضمن علامات الاقتباس مزدوجة، يجب إحاطة السلاسل داخل برامج التوزيع النصية ضمن علامات اقتباس مفردة بدلاً من ذلك. يمثل حرف إلغاء PowerShell علامة الاقتباس النهائية (`).

    {
      "type": "Microsoft.Resources/deploymentScripts",
      "apiVersion": "2020-10-01",
      "name": "createAddCertificate",
      "location": "[resourceGroup().location]",
      "dependsOn": [
        "[resourceId('Microsoft.KeyVault/vaults', parameters('keyVaultName'))]"
      ],
      "identity": {
        "type": "UserAssigned",
        "userAssignedIdentities": {
          "[parameters('identityId')]": {
          }
        }
      },
      "kind": "AzurePowerShell",
      "properties": {
        "forceUpdateTag": "[parameters('utcValue')]",
        "azPowerShellVersion": "3.0",
        "timeout": "PT30M",
        "arguments": "[format(' -vaultName {0} -certificateName {1} -subjectName {2}', parameters('keyVaultName'), parameters('certificateName'), parameters('subjectName'))]", // can pass an argument string, double quotes must be escaped
        "scriptContent": "
          param(
            [string] [Parameter(Mandatory=$true)] $vaultName,
            [string] [Parameter(Mandatory=$true)] $certificateName,
            [string] [Parameter(Mandatory=$true)] $subjectName
          )
    
          $ErrorActionPreference = 'Stop'
          $DeploymentScriptOutputs = @{}
    
          $existingCert = Get-AzKeyVaultCertificate -VaultName $vaultName -Name $certificateName
    
          if ($existingCert -and $existingCert.Certificate.Subject -eq $subjectName) {
    
            Write-Host 'Certificate $certificateName in vault $vaultName is already present.'
    
            $DeploymentScriptOutputs['certThumbprint'] = $existingCert.Thumbprint
            $existingCert | Out-String
          }
          else {
            $policy = New-AzKeyVaultCertificatePolicy -SubjectName $subjectName -IssuerName Self -ValidityInMonths 12 -Verbose
    
            # private key is added as a secret that can be retrieved in the Resource Manager template
            Add-AzKeyVaultCertificate -VaultName $vaultName -Name $certificateName -CertificatePolicy $policy -Verbose
    
            # it takes a few seconds for KeyVault to finish
            $tries = 0
            do {
              Write-Host 'Waiting for certificate creation completion...'
              Start-Sleep -Seconds 10
              $operation = Get-AzKeyVaultCertificateOperation -VaultName $vaultName -Name $certificateName
              $tries++
    
              if ($operation.Status -eq 'failed')
              {
                throw 'Creating certificate $certificateName in vault $vaultName failed with error $($operation.ErrorMessage)'
              }
    
              if ($tries -gt 120)
              {
                throw 'Timed out waiting for creation of certificate $certificateName in vault $vaultName'
              }
            } while ($operation.Status -ne 'completed')
    
            $newCert = Get-AzKeyVaultCertificate -VaultName $vaultName -Name $certificateName
            $DeploymentScriptOutputs['certThumbprint'] = $newCert.Thumbprint
            $newCert | Out-String
          }
        ",
        "cleanupPreference": "OnSuccess",
        "retentionInterval": "P1D"
      }
    }
    

    يعتمد المورد deploymentScripts على مورد key vault ومورد تعيين الدور. يحتوي على هذه الخصائص:

    • identity: يستخدم برنامج التوزيع النصي هوية مُدارة تم تعيينها من قِبل المستخدم لتنفيذ العمليات في البرنامج النصي.
    • kind: يحدد نوع البرنامج النصي. حاليًا، يتم اعتماد برامج PowerShell النصية فقط.
    • forceUpdateTag: يحدد ما إذا كان يجب تنفيذ برنامج التوزيع النصي حتى إذا لم يتغير مصدر البرنامج النصي. يمكن أن يكون الطابع الزمني الحالي أو GUID. لمعرفة المزيد، راجع تشغيل البرنامج النصي أكثر من مرة.
    • azPowerShellVersion: يحدد إصدار وحدة Azure PowerShell النمطية المطلوب استخدامها. حاليًا، يدعم برنامج التوزيع النصي الإصدارات 2.7.0 و2.8.0 و3.0.0.
    • timeout: يحدد أقصى وقت مسموح به لتنفيذ البرنامج النصي المحدد بتنسيق ISO 8601. القيمة الافتراضية هي P1D.
    • arguments: يحدد قيم المعلمات. تُفصل القيم بمسافات.
    • scriptContent: يحدد محتوى البرنامج النصي. لتشغيل برنامج نصي خارجي، استخدم primaryScriptURI بدلاً من ذلك. لمزيد من المعلومات، راجع استخدام برنامج نصي خارجي. الإعلان عن $DeploymentScriptOutputs مطلوب فقط عند اختبار البرنامج النصي على جهاز محلي. يسمح الإعلان عن المتغير بتشغيل البرنامج النصي على جهاز محلي وفي مورد deploymentScript دون الحاجة إلى إجراء تغييرات. القيمة المعينة إلى $DeploymentScriptOutputs متوفرة كمخرجات في عمليات التوزيع. لمزيد من المعلومات، راجع العمل مع مخرجات من برامج توزيع PowerShell النصية أو العمل مع مخرجات من برامج توزيع CLI النصية.
    • cleanupPreference: يحدد التفضيل المتعلق بوقت حذف موارد برنامج التوزيع النصي. القيمة الافتراضية هي دائمًا، مما يعني أن موارد برنامج التوزيع النصي يتم حذفها على الرغم من حالة الإنهاء (نجاح، فشل، تم الإلغاء). في هذا البرنامج التعليمي، OnSuccess يستخدم بحيث تحصل على فرصة لعرض نتائج تنفيذ البرنامج النصي.
    • retentionInterval: يحدد الفترة التي تحتفظ الخدمة بموارد البرنامج النصي بعد وصولها إلى حالة الإنهاء. سيتم حذف الموارد عند انتهاء هذه المدة. تستند المدة إلى نمط ISO 8601. يستخدم هذا البرنامج التعليمي P1D، وهو ما يعني يوم واحد. يتم استخدام هذه الخاصية عند تعيين cleanupPreference إلى OnExpiration. هذه الخاصية غير ممكنة حاليًا.

    يأخذ برنامج التوزيع النصي ثلاثة معلمات: keyVaultName وcertificateName وsubjectName. حيث يتم من خلاله إنشاء شهادة، ثم إضافة الشهادة إلى key vault.

    $DeploymentScriptOutputs يُستخدم لتخزين قيمة الإخراج. لمعرفة المزيد، راجع العمل مع مخرجات من برامج توزيع PowerShell النصية أو العمل مع مخرجات من برامج توزيع CLI النصية.

    يمكن العثور على القالب الكامل هنا.

  3. لمشاهدة عملية التصحيح، ضع خطأً في التعليمة البرمجية بإضافة السطر التالي إلى برنامج التوزيع النصي:

    Write-Output1 $keyVaultName
    

    الأمر الصحيح هو Write-Output بدلاً من Write-Output1.

  4. حدد ملف>حفظ لحفظ الملف.

نشر القالب

  1. سجل الدخول إلى Azure Cloud Shell

  2. اختر بيئتك المفضلة بتحديد PowerShell أو Bash (لـ CLI) في الزاوية العلوية اليسرى. يلزم إعادة تشغيل Shell عند التبديل.

    Azure portal Cloud Shell upload file

  3. حدد تحميل/تنزيل ملفات، ثم حدد تحميل. راجع لقطة الشاشة السابقة. حدد الملف الذي قمت بحفظه في القسم السابق. بعد تحميل الملف، يمكنك استخدام الأمر ls والأمر cat للتحقق من تحميل الملف بنجاح.

  4. شغّل البرنامج النصي التالي لـ Azure CLI أو PowerShell لتوزيع القالب.

    echo "Enter a project name that is used to generate resource names:" &&
    read projectName &&
    echo "Enter the location (i.e. centralus):" &&
    read location &&
    echo "Enter your email address used to sign in to Azure:" &&
    read upn &&
    echo "Enter the user-assigned managed identity ID:" &&
    read identityId &&
    adUserId=$((az ad user show --id ${upn}) | jq -r '.id') &&
    resourceGroupName="${projectName}rg" &&
    keyVaultName="${projectName}kv" &&
    az group create --name $resourceGroupName --location $location &&
    az deployment group create --resource-group $resourceGroupName --template-file "$HOME/azuredeploy.json" --parameters identityId=$identityId keyVaultName=$keyVaultName objectId=$adUserId
    

    تحتاج خدمة برنامج التوزيع النصي إلى إنشاء موارد إضافية لبرنامج التوزيع النصي لتنفيذ البرنامج النصي. يمكن أن تستغرق عملية الإعداد والتنظيف دقيقة واحدة للإكمال، بالإضافة إلى وقت تنفيذ البرنامج النصي الفعلي.

    فشل التوزيع لأن الأمر غير صالح، يتم استخدام Write-Output1 في البرنامج النصي. سيظهر لك خطأ يفيد:

    The term 'Write-Output1' is not recognized as the name of a cmdlet, function, script file, or operable
    program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
    

    يتم تخزين نتيجة تنفيذ برنامج التوزيع النصي في موارد برنامج التوزيع النصي لغرض استكشاف الأخطاء وإصلاحها.

تصحيح البرنامج النصي الفاشل

  1. سجل الدخول إلى مدخل Azure.

  2. افتح مجموعة الموارد. إنه اسم المشروع مع إلحاق rg. سترى موردين إضافيين في مجموعة الموارد. ويُشار إلى هذه الموارد باسم موارد برنامج التوزيع النصي.

    Resource Manager template deployment script resources

    يحمل كلا الملفين اللاحقة azscripts. أحدهما حساب تخزين والآخر هو مثيل حاوية.

    حدد إظهار الأنواع المخفية لسرد المورد deploymentScripts.

  3. حدد حساب التخزين الذي لديه اللاحقة azscripts.

  4. حدد التجانب مشاركات الملفات. سترى المجلد azscripts الذي يحتوي على ملفات تنفيذ برنامج التوزيع النصي.

  5. حدد azscripts. سترى مجلدين azscriptinput و azscriptoutput. يحتوي مجلد الإدخال على ملف برنامج PowerShell نصي للنظام وملفات برنامج التوزيع النصي للمستخدم. يحتوي مجلد الإخراج على executionresult.js وملف إخراج البرنامج النصي. يمكنك مشاهدة رسالة الخطأ في executionresult.js. ملف الإخراج غير موجود بسبب فشل التنفيذ.

بادر بإزالة السطر Write-Output1 وإعادة توزيع القالب.

عند تشغيل التوزيع الثاني بنجاح، ستتم إزالة موارد برنامج التوزيع النصي بواسطة خدمة البرنامج النصي، لأنه تم تعيين الخاصية cleanupPreference إلى OnSuccess.

تنظيف الموارد

عندما لا تكون موارد Azure مطلوبة، قم بتنظيف الموارد التي قمت بنشرها عن طريق حذف مجموعة الموارد.

  1. من مدخل Azure، حدد مجموعة الموارد من القائمة اليمنى.
  2. أدخل اسم مجموعة الموارد في الحقل Filter by name.
  3. حدد اسم مجموعة الموارد.
  4. حدد Delete resource group من القائمة.

الخطوات التالية

في هذا البرنامج التعليمي، تعلمت كيفية استخدام برنامج التوزيع النصي في قوالب ARM. لمعرفة كيفية توزيع موارد Azure استنادًا إلى الشروط، راجع: