Firma della pipeline MSIX e CI/CD con Azure Key Vault

La firma è una delle attività critiche da eseguire quando si lavora con i pacchetti MSIX. Se un pacchetto MSIX non è firmato con un certificato attendibile, gli utenti non potranno installare l'applicazione. Allo stesso tempo, la firma è una delle attività più critiche anche quando si tratta di sicurezza. I certificati devono essere archiviati in modo sicuro, per evitare che gli attori malintenzionati possano riutilizzarli per firmare le applicazioni con l'identità. Azure Key Vault è l'opzione migliore per supportare questo requisito.

In questo articolo verrà illustrato come sfruttare Azure Key Vault in una pipeline CI/CD, in modo da poter firmare automaticamente il pacchetto MSIX come parte del processo.

Importante

Il processo descritto in questo articolo si basa su uno strumento open source denominato Azure SignTool, che funziona sia con Azure Pipelines che con GitHub Actions. Se si usa Azure Pipelines, è possibile usare anche le estensioni MSIX in combinazione con l'attività Azure Key Vault.

Prerequisiti

  • Un account Azure. Se non è ancora disponibile alcun account di Azure, iniziare da qui.
  • Un insieme di credenziali delle chiavi di Azure. Per altre informazioni, vedere Creare un insieme di credenziali delle chiavi.
  • Un certificato di firma del pacchetto valido importato in Azure Key Vault. Il certificato predefinito generato da Azure Key Vault non potrà essere usato per la firma del codice. Per informazioni dettagliate su come creare un certificato per la firma dei pacchetti, vedere Creare un certificato per la firma dei pacchetti.
  • Pipeline CI/CD che genera un pacchetto MSIX, ospitato in Azure Pipelines o GitHub Actions. Per altre informazioni, vedere Configurare la pipeline CI/CD con il file YAML.

Registrare un'applicazione in Azure

Per firmare il pacchetto come parte della pipeline CI/CD, si userà uno strumento denominato Azure SignTool. Funziona come l'utilità SignTool standard inclusa in Windows 10 SDK, ma, invece di usare un certificato locale, si connette ad Azure Key Vault per usare uno dei certificati disponibili. Per stabilire la connessione, tuttavia, è prima necessario registrare un'applicazione in Azure, che fornirà le credenziali necessarie per consentire ad Azure SignTool di eseguire l'autenticazione nel servizio Azure Key Vault.

Aprire il portale di Azure e scegliere Azure Active Directory tra i servizi disponibili. Fare clic su Registrazioni app e scegliere Nuova registrazione per avviare il processo. Assegnare un nome all'applicazione, ad esempio SignToolForContoso nell'immagine seguente, e quindi lasciare le impostazioni predefinite.

Register an application on Azure

Il passaggio successivo consiste nel considerare l'applicazione come client pubblico, poiché si è in uno scenario in cui non è necessario un URI di reindirizzamento. Passare alla sezione Autenticazione e, in Impostazioni avanzate, modificare l'opzione Considera applicazione come client pubblico su .

Set advanced settings

L'ultimo passaggio consiste nel creare un segreto client, ovvero la password necessaria per l'autenticazione da Azure SignTool. Passare alla sezione Certificati e segreti, quindi fare clic su Nuovo segreto client. Assegnare un nome, scegliere una scadenza e quindi premere il pulsante Aggiungi . Si verrà reindirizzati di nuovo alla pagina principale, in cui il segreto verrà elencato insieme al relativo valore. Assicurarsi di copiarlo e di archiviarlo in un luogo sicuro. Non sarà possibile recuperarlo di nuovo. Non appena aggiorni la pagina, il segreto verrà mascherato e non ci sarà alcun modo per rivelarlo. L'unica opzione consiste nel generare un nuovo segreto.

È necessario salvare un'ultima informazione insieme al segreto client: l'identificatore dell'applicazione. Tornare alla home page dell'applicazione (facendo clic su Panoramica) e, nella sezione superiore, cercare l'ID applicazione (client):

Application Id

Abilitare l'accesso ad Azure Key Vault

Il passaggio successivo consiste nel configurare l'applicazione Azure appena creata per accedere al servizio Azure Key Vault. Dal portale di Azure passare all'istanza di Azure Key Vault che contiene il certificato da usare per firmare il pacchetto MSIX. Passare alla sezione Criteri di accesso e fare clic su Aggiungi criteri di accesso. Lo strumento supporta la scelta di uno dei modelli disponibili per definire le autorizzazioni che si vuole concedere, ma, in questo scenario, nessuno di essi è la scelta appropriata. Di conseguenza, sarà necessario impostare manualmente, usando gli elenchi a discesa, le opzioni seguenti:

  • In Autorizzazioni chiave abilitare l'opzione Firma .
  • In Autorizzazioni certificato abilitare l'opzione Recupera .

L'ultimo passaggio importante consiste nel specificare quale applicazione accederà a questo criterio. Fare clic su Select principal (Seleziona entità ) e cercare l'applicazione Azure creata nel passaggio precedente usandone il nome. Nell'esempio viene chiamato SignToolForContoso.

Select principal

Dopo averlo trovato, premere Seleziona. Questo è l'aspetto del criterio.

Add access policy

Dopo aver completato il processo, fare clic su Aggiungi per creare i criteri.

Usare Azure SignTool per firmare il pacchetto in locale

Dopo aver completato la configurazione di Azure, è possibile usare Azure SignTool per firmare il pacchetto. In questa sezione si userà lo strumento in locale per acquisire familiarità con esso. Nelle sezioni successive verrà usata come parte di una pipeline CI/CD.

Lo strumento è disponibile come strumento globale .NET. Assicurarsi di avere installato l'SDK .NET più recente, quindi aprire un prompt dei comandi e avviare il comando seguente:

dotnet tool install --global AzureSignTool 

È ora possibile firmare il pacchetto usando il comando AzureSignTool, che richiede i parametri seguenti:

  • kvu è l'URL dell'insieme di credenziali delle chiavi di Azure. È possibile trovarla nella pagina principale del servizio nella portale di Azure, in Nome DNS.
  • kvi è l'ID applicazione dell'app di Azure registrata e annotata in precedenza.
  • kvs è il segreto client generato in precedenza e annotato in precedenza.
  • kvc è il nome descrittivo del certificato che si vuole usare.
  • tr è l'URL di un server timestamp. Usando questa opzione, è possibile abilitare il pacchetto anche quando il certificato scadrà.
  • v è il percorso del pacchetto MSIX che si vuole firmare.

Questo è un comando di esempio:

AzureSignTool sign -kvt "<tenantID>" -kvu "https://contosoexpenses-blog.vault.azure.net/" -kvi "64fae35e-cb84-4b9f-86eb-5170d169316d" -kvs "this-is-the-secret" -kvc "MyCertificate" -tr http://timestamp.digicert.com -v .\MyContosoApp.msix

Nota

Per altre informazioni su AzureSignTool, eseguire AzureSignTool sign --help

Uso di Azure SignTool con Azure Pipelines

Questa sezione presuppone che sia già disponibile una pipeline CI/CD per un'applicazione Windows configurata con un file YAML in Azure Pipelines, come illustrato qui.

In un primo momento, sarà necessario creare alcune variabili per archiviare le informazioni richieste da Azure SignTool per connettersi ad Azure Key Vault. In Azure DevOps selezionare la pipeline e premere il pulsante Modifica nella parte superiore. Dopo aver eseguito l'accesso all'editor YAML, fare clic sul pulsante Variabili nella parte superiore per aprire il pannello. Fare clic sul pulsante + per aggiungere le variabili seguenti:

  • AzureKeyVaultName, con il nome descrittivo dell'insieme di credenziali.
  • AzureKeyVaultUrl, con l'URL dell'insieme di credenziali.
  • AzureKeyVaultClientId, con l'ID applicazione dell'applicazione Azure.
  • AzureKeyVaultClientSecret, con il segreto client dell'applicazione Azure.

Quando si crea ogni variabile, assicurarsi di abilitare l'opzione Mantieni questo valore segreto. Si assicurerà che altri utenti che hanno accesso alla pipeline non saranno in grado di visualizzare i valori.

Add variable

È ora possibile personalizzare la pipeline YAML esistente aggiungendo un'attività .NET Core per installare Azure SignTool nell'agente. Questo è il file YAML da aggiungere:

- task: DotNetCoreCLI@2
  displayName: 'Install Azure SignTool'
  inputs:
    command: custom
    custom: tool
    arguments: 'install --global AzureSignTool'

Il passaggio successivo consiste nell'aggiungere un'attività di PowerShell per eseguire il comando che firmerà il pacchetto. È necessario eseguire questa attività solo alla fine del processo di compilazione, una volta creato il pacchetto MSIX.

- powershell: '& AzureSignTool sign -kvu $(AzureKeyVaultUrl) -kvi $(AzureKeyVaultClientId) -kvs $(AzureKeyVaultClientSecret) -kvc $(AzureKeyVaultName) -tr http://timestamp.digicert.com -v "$(System.DefaultWorkingDirectory)\MyPipeline\MyContosoApp\MyContosoApp.msix"'
  displayName: 'Sign the package'

Il comando è simile a quello usato per firmare il pacchetto in locale. Le uniche differenze sono:

  • Anziché usare valori fissi per i vari parametri, si usano le variabili create con la sintassi $(Variable-Name)
  • Il percorso del pacchetto MSIX punta alla cartella dell'agente in cui viene creato il pacchetto MSIX alla fine della compilazione.

Uso di Azure SignTool con GitHub Actions

Questa sezione presuppone che sia già disponibile una pipeline CI/CD per un'applicazione Windows configurata con un file YAML in GitHub Actions, come illustrato qui.

Come primo passaggio, come in Azure Pipeline, è necessario archiviare le credenziali in modo sicuro. GitHub usa i segreti e possono essere aggiunti nelle impostazioni del repository. Quando si è nel repository GitHub che ospita l'applicazione Windows, fare clic su Impostazioni quindi passare a Segreti.

Analogamente a quanto fatto con Azure Pipelines, fare clic su Nuovo segreto per creare quattro segreti:

  • AzureKeyVaultName, con il nome descrittivo dell'insieme di credenziali.
  • AzureKeyVaultUrl, con l'URL dell'insieme di credenziali.
  • AzureKeyVaultClientId, con l'ID applicazione dell'applicazione Azure.
  • AzureKeyVaultClientSecret, con il segreto client dell'applicazione Azure.

La differenza con Azure Pipeline è che i segreti vengono nascosti in modo implicito, quindi non è necessario abilitare alcuna opzione per proteggerli.

Ora, tramite la scheda Azioni del repository, è possibile aprire il flusso di lavoro esistente e aggiungere le attività necessarie per eseguire la firma. Il primo installerà lo strumento AzureSign nell'agente:

- name: Install AzureSignTool
  run: dotnet tool install --global AzureSignTool

Il secondo firma il pacchetto e, di conseguenza, deve essere eseguito dopo il completamento della compilazione di Visual Studio e il pacchetto MSIX è stato generato.

 - name: Sign package
   run: |
        Get-ChildItem -recurse -Include **.msix | ForEach-Object {
        $msixPath = $_.FullName
        & AzureSignTool sign -kvu "${{ secrets.AzureKeyVaultUrl }}" -kvi "${{ secrets.AzureKeyVaultClientId }}" -kvs "${{ secrets.AzureKeyVaultClientSecret }}" -kvc ${{ secrets.AzureKeyVaultName }} -tr http://timestamp.digicert.com -v $msixPath
        }

Esistono alcune differenze in questa attività rispetto a quella usata in Azure Pipelines. Il primo è che GitHub usa una sintassi diversa per accedere ai segreti, ovvero ${{ secrets.edizione StandardCRET_NAME }}. Di conseguenza, i vari parametri vengono compilati con i valori creati in precedenza nella sezione Segreti. L'altro è che è necessario usare un approccio diverso per trovare i pacchetti MSIX da firmare. L'attività, invece di puntare a un pacchetto MSIX specifico, usa uno script di PowerShell che scorre tutti i file archiviati nell'output di compilazione. Se il file ha l'estensione MSIX, userà il comando AzureSignTool per firmarlo.

Distribuire un pacchetto

Indipendentemente dalla piattaforma CI/CD preferita, alla fine del flusso si avrà un pacchetto MSIX firmato con il certificato archiviato in Azure Key Vault. È ora possibile usare qualsiasi altra attività disponibile per distribuire il pacchetto usando la scelta preferita di distribuzione: Microsoft Store, un sito Web, Microsoft Intune e così via.