Esercitazione: Usare gli script di distribuzione per creare un certificato autofirmato

Informazioni su come usare gli script di distribuzione nei modelli di Azure Resource Manager (modelli di ARM). Gli script di distribuzione possono essere usati per eseguire passaggi personalizzati che non possono essere eseguiti dai modelli di Azure Resource Manager. Ad esempio, la creazione di un certificato autofirmato. In questa esercitazione viene creato un modello per distribuire un insieme di credenziali delle chiavi di Azure e quindi viene usata una risorsa Microsoft.Resources/deploymentScripts nello stesso modello per creare un certificato e infine viene aggiunto il certificato all'insieme di credenziali delle chiavi. Per altre informazioni sullo script di distribuzione, vedere Usare gli script di distribuzione nei modelli di Azure Resource Manager.

Importante

Due risorse dello script di distribuzione, un account di archiviazione e un'istanza del contenitore, vengono create nello stesso gruppo di risorse per l'esecuzione dello script e la risoluzione dei problemi. Queste risorse vengono in genere eliminate dal servizio di script quando l'esecuzione dello script raggiunge uno stato finale. Le risorse verranno addebitate fino a quando non vengono eliminate. Per altre informazioni, vedere Pulire le risorse dello script di distribuzione.

Questa esercitazione illustra le attività seguenti:

  • Aprire un modello di avvio rapido
  • Modificare il modello
  • Distribuire il modello
  • Eseguire il debug dello script non riuscito
  • Pulire le risorse

Per consultare un modulo Learn che illustra gli script di distribuzione, vedere Estendere i modelli di ARM usando gli script di distribuzione.

Prerequisiti

Per completare questo articolo, devi avere quanto segue:

  • Visual Studio Code con l'estensione Strumenti di Resource Manager. Vedere Guida di avvio rapido - Creare modelli di ARM con Visual Studio Code.

  • Identità gestita assegnata dall'utente. Questa identità viene usata per eseguire azioni specifiche di Azure nello script. Per crearne una, vedere Identità gestita assegnata dall'utente. È necessario l'ID identità per distribuire il modello. Il formato dell'identità è:

    /subscriptions/<SubscriptionID>/resourcegroups/<ResourceGroupName>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<IdentityID>
    

    Usare lo script dell'interfaccia della riga di comando seguente per recuperare l'ID fornendo il nome del gruppo di risorse e il nome dell'identità.

    echo "Enter the Resource Group name:" &&
    read resourceGroupName &&
    az identity list -g $resourceGroupName
    

Aprire un modello di avvio rapido

Invece di creare un modello da zero, aprire un modello da Modelli di avvio rapido di Azure. Modelli di avvio rapido di Azure è un repository di modelli di Azure Resource Manager.

Il modello usato in questo avvio rapido è denominato Creare un insieme di credenziali delle chiavi e un segreto di Azure. Il modello crea un'insieme di credenziali delle chiavi e quindi aggiunge un segreto all'insieme di credenziali delle chiavi.

  1. In Visual Studio Code selezionare File>Apri file.

  2. In Nome file incollare l'URL seguente:

    https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/quickstarts/microsoft.keyvault/key-vault-create/azuredeploy.json
    
  3. Selezionare Apri per aprire il file.

  4. Selezionare File>Salva con nome per salvare il file con il nome azuredeploy.json nel computer locale.

Modificare il modello

Apportare le modifiche seguenti al modello:

Pulire il modello (facoltativo)

Il modello originale aggiunge un segreto all'insieme di credenziali delle chiavi. Per semplificare l'esercitazione, rimuovere la risorsa seguente:

  • Microsoft.KeyVault/vaults/secrets

Rimuovere le due definizioni di parametro seguenti:

  • secretName
  • secretValue

Se si sceglie di non rimuovere queste definizioni, è necessario specificare i valori dei parametri durante la distribuzione.

Configurare i criteri di accesso dell'insieme di credenziali delle chiavi

Lo script di distribuzione aggiunge un certificato all'insieme di credenziali delle chiavi. Configurare i criteri di accesso dell'insieme di credenziali delle chiavi per concedere l'autorizzazione all'identità gestita:

  1. Aggiungere un parametro per ottenere l'ID identità gestita:

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

    Nota

    L'estensione del modello di Resource Manager di Visual Studio Code non è ancora in grado di formattare gli script di distribuzione. Non usare MAIUSC+ALT+F per formattare le risorse deploymentScripts, come quella seguente.

  2. Aggiungere un parametro per la configurazione dei criteri di accesso dell'insieme di credenziali delle chiavi in modo che l'identità gestita possa aggiungere certificati all'insieme di credenziali delle chiavi:

    "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. Aggiornare i criteri di accesso dell'insieme di credenziali delle chiavi esistenti come segue:

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

    Sono definiti due criteri, uno per l'utente connesso e l'altro per l'identità gestita. Per verificare la distribuzione, l'utente connesso necessita solo dell'autorizzazione list. Per semplificare l'esercitazione, lo stesso certificato viene assegnato sia all'identità gestita che agli utenti connessi.

Aggiungere lo script di distribuzione

  1. Aggiungere tre parametri usati dallo script di distribuzione:

    "certificateName": {
      "type": "string",
      "defaultValue": "DeploymentScripts2019"
    },
    "subjectName": {
      "type": "string",
      "defaultValue": "CN=contoso.com"
    },
    "utcValue": {
      "type": "string",
      "defaultValue": "[utcNow()]"
    }
    
  2. Aggiungere una risorsa deploymentScripts:

    Nota

    Poiché gli script di distribuzione inline sono racchiusi tra virgolette doppie, le stringhe all'interno degli script di distribuzione devono essere racchiuse tra virgolette singole. Il carattere di escape per PowerShell è l'apice inverso (`).

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

    La risorsa deploymentScripts dipende dalla risorsa dell'insieme di credenziali delle chiavi e dalla risorsa di assegnazione di ruolo. Ha queste proprietà:

    • identity: lo script di distribuzione usa un'identità gestita assegnata dall'utente per eseguire le operazioni nello script.
    • kind: specificare il tipo di script. Attualmente sono supportati solo gli script di PowerShell.
    • forceUpdateTag: determinare se lo script di distribuzione debba essere eseguito anche se l'origine dello script non è stata modificata. Può essere il timestamp corrente o un GUID. Per altre informazioni, vedere Eseguire lo script più di una volta.
    • azPowerShellVersion: specifica la versione del modulo di Azure PowerShell da usare. Attualmente, lo script di distribuzione supporta la versione 2.7.0, 2.8.0 e 3.0.0.
    • timeout: specificare il tempo massimo di esecuzione dello script consentito nel formato ISO 8601. Il valore predefinito è P1D.
    • arguments: specificare i valori del parametro. I valori sono separati da uno spazio.
    • scriptContent: specificare il contenuto dello script. Per eseguire uno script esterno, usare primaryScriptURI. Per altre informazioni, vedere Usare uno script esterno. La dichiarazione $DeploymentScriptOutputs è necessaria solo se si testa lo script in un computer locale. La dichiarazione della variabile consente di eseguire lo script in un computer locale e in una risorsa deploymentScript senza dover apportare modifiche. Il valore assegnato a $DeploymentScriptOutputs è disponibile come output nelle distribuzioni. Per altre informazioni, vedere Usare gli output degli script di distribuzione di PowerShell o Usare gli output degli script di distribuzione dell'interfaccia della riga di comando.
    • cleanupPreference: specificare la preferenza che determina quando eliminare le risorse dello script di distribuzione. Il valore predefinito è Always, che significa che le risorse dello script di distribuzione vengono eliminate nonostante lo stato finale (Succeeded, Failed, Canceled). In questa esercitazione viene usato OnSuccess in modo da potere visualizzare i risultati dell'esecuzione dello script.
    • retentionInterval: specificare l'intervallo durante il quale il servizio mantiene le risorse dello script dopo il raggiungimento di uno stato finale. Le risorse verranno eliminate alla scadenza di tale durata. La durata è basata sul modello ISO 8601. Questa esercitazione usa P1D, che indica un giorno. Questa proprietà si utilizza quando cleanupPreference è impostato su OnExpiration. Questa proprietà non è attualmente abilitata.

    Lo script di distribuzione accetta tre parametri: keyVaultName, certificateName e subjectName. Crea un certificato e quindi aggiunge il certificato all'insieme di credenziali delle chiavi.

    $DeploymentScriptOutputs consente di archiviare il valore di output. Per altre informazioni, vedere Usare gli output degli script di distribuzione di PowerShell o Usare gli output degli script di distribuzione dell'interfaccia della riga di comando.

    Il modello completato è disponibile qui.

  3. Per visualizzare il processo di debug, inserire un errore nel codice aggiungendo la riga seguente allo script di distribuzione:

    Write-Output1 $keyVaultName
    

    Il comando corretto è Write-Output invece di Write-Output1.

  4. Selezionare File>Salva per salvare il file.

Distribuire il modello

  1. Accedere ad Azure Cloud Shell

  2. Scegliere l'ambiente preferito selezionando PowerShell o Bash (per l'interfaccia della riga di comando) nell'angolo in alto a sinistra. Quando si cambia interfaccia, è necessario riavviare la shell.

    Azure portal Cloud Shell upload file

  3. Selezionare Carica/Scarica file e quindi Carica. Vedere l'immagine sopra riportata. Selezionare il file salvato nella sezione precedente. Dopo aver caricato il file, è possibile usare i comandi ls e cat per verificare che il file sia stato caricato.

  4. Per distribuire il modello, eseguire lo script seguente dell'interfaccia della riga di comando di Azure o di Azure 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
    

    Il servizio dello script di distribuzione deve creare altre risorse dello script di distribuzione per l'esecuzione dello script. Il completamento della preparazione e del processo di pulizia può richiedere fino a un minuto oltre al tempo di esecuzione effettivo dello script.

    La distribuzione non è riuscita perché nello script è stato usato il comando Write-Output1 che non è valido. Verrà visualizzato un errore simile al seguente:

    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.
    

    Il risultato dell'esecuzione dello script di distribuzione viene archiviato nelle risorse dello script di distribuzione per la risoluzione dei problemi.

Eseguire il debug dello script non riuscito

  1. Accedere al portale di Azure.

  2. Aprire il gruppo di risorse. È il nome del progetto seguito da rg. Nel gruppo di risorse verranno visualizzate due risorse aggiuntive. Queste risorse vengono definite risorse dello script di distribuzione.

    Resource Manager template deployment script resources

    Entrambi i file hanno il suffisso azscripts. Uno è un account di archiviazione e l'altro è un'istanza di contenitore.

    Selezionare Mostra tipi nascosti per elencare la risorsa deploymentScripts.

  3. Selezionare l'account di archiviazione con il suffisso azscripts.

  4. Selezionare il riquadro Condivisioni file. Viene visualizzata una cartella azscripts che contiene i file di esecuzione dello script di distribuzione.

  5. Selezionare azscripts. Verranno visualizzate due cartelle, azscriptinput e azscriptoutput. La cartella di input contiene un file di script di sistema di PowerShell e i file di script di distribuzione dell'utente. La cartella di output contiene un file executionresult.json e il file di output dello script. È possibile visualizzare il messaggio di errore in executionresult.json. Il file di output non è presente perché l'esecuzione non è riuscita.

Rimuovere la riga Write-Output1 e distribuire nuovamente il modello.

Dopo l'esecuzione corretta della seconda distribuzione, le risorse dello script di distribuzione verranno rimosse dal servizio di script, perché la proprietà cleanupPreference è impostata su OnSuccess.

Pulire le risorse

Quando non sono più necessarie, eseguire la pulizia delle risorse di Azure distribuite eliminando il gruppo di risorse.

  1. Nel portale di Azure selezionare Gruppo di risorse nel menu a sinistra.
  2. Immettere il nome del gruppo di risorse nel campo Filtra per nome.
  3. Selezionare il nome del gruppo di risorse.
  4. Selezionare Elimina gruppo di risorse nel menu in alto.

Passaggi successivi

Questa esercitazione ha illustrato come usare uno script di distribuzione nei modelli di Azure Resource Manager. Per informazioni su come distribuire risorse di Azure in base a condizioni, vedere: