Signature de MSIX et de pipeline CI/CD avec Azure Key Vault

La signature est l’une des tâches critiques à effectuer lorsque vous utilisez des packages MSIX. Si un package MSIX n’est pas signé avec un certificat autorisé, les utilisateurs ne seront pas en mesure d’installer l’application. En même temps, la signature est également l’une des tâches les plus critiques en matière de sécurité. Nous devons stocker les certificats en toute sécurité afin d’éviter que des acteurs malveillants puissent les réutiliser pour signer leurs applications en usurpant notre identité. La solution Azure Key Vault est la meilleure option pour prendre en charge cette exigence.

Cet article explique comment utiliser Azure Key Vault dans un pipeline CI/CD pour signer automatiquement notre package MSIX dans le cadre du processus.

Important

Le processus décrit dans cet article est basé sur un outil open source appelé Azure SignTool fonctionnant tant avec Azure Pipelines qu’avec GitHub Actions. Si vous utilisez Azure Pipelines, vous pouvez également utiliser des Extensions MSIX avec la tâche Azure Key Vault.

Prérequis

  • Un compte Azure. Si vous n’avez pas encore de compte Azure, commencez ici.
  • Une instance Azure Key Vault. Pour plus d’informations, consultez Créer un coffre de clés.
  • Un certificat de signature de package valide importé dans Azure Key Vault. Le certificat par défaut généré par Azure Key Vault ne fonctionne pas pour la signature de code. Pour plus d’informations sur la création d’un certificat de signature de package, consultez Créer un certificat de signature de package.
  • Un pipeline CI/CD générant un package MSIX, hébergé sur Azure Pipelines ou GitHub Actions. Pour plus d’informations, consultez Configurer un pipeline CI/CD avec un fichier YAML.

Inscrire une application sur Azure

Pour signer le package dans le cadre du pipeline CI/CD, nous allons nous servir d’un outil appelé Azure SignTool. Il fonctionne comme l’utilitaire SignTool standard inclus dans le Kit de développement logiciel (SDK) Windows 10 mais, au lieu d’utiliser un certificat local, il se connecte à Azure Key Vault pour utiliser l’un des certificats disponibles. Toutefois, pour établir la connexion, nous devons commencer par inscrire sur Azure une application qui nous donnera les informations d’identification nécessaires pour permettre à Azure SignTool de s’authentifier auprès de notre service Azure Key Vault.

Ouvrez le portail Azure, puis choisissez Azure Active Directory parmi les services disponibles. Cliquez sur Inscriptions des applications, puis choisissez Nouvelle inscription pour démarrer le processus. Attribuez un nom à l’application (comme SignToolForContoso dans l’image ci-dessous) et conservez les paramètres par défaut.

Register an application on Azure

L’étape suivante consiste à traiter l’application comme un client public, car nous sommes dans un scénario dans lequel un URI de redirection n’est pas nécessaire. Accédez à la section Authentification, puis, sous Paramètres avancés, positionnez le commutateur Considérer l’application comme un client public sur Oui.

Set advanced settings

La dernière étape consiste à créer une clé secrète client, à savoir le mot de passe dont nous aurons besoin pour nous authentifier à partir d’Azure SignTool. Accédez à la section Certificats et secrets, puis cliquez sur Nouvelle clé secrète client. Spécifiez un nom, choisissez un délai d’expiration, puis appuyez sur le bouton Ajouter. Vous êtes redirigé vers la page principale affichant le secret avec sa valeur. Copiez la valeur et conservez-la en lieu sûr. Vous ne pourrez plus la récupérer une nouvelle fois. Dès que vous actualisez la page, le secret est masqué et il n’existe aucun moyen de le révéler. La seule option consiste à générer un nouveau secret.

Il vous reste à enregistrer une dernière information avec la clé secrète client, à savoir l’identificateur d’application. Revenez à la page d’accueil de l’application (en cliquant sur Vue d’ensemble), puis, dans la section supérieure, recherchez la valeur ID (client) d’application :

Application Id

Gérer l’accès à Azure Key Vault

L’étape suivante consiste à configurer l’application Azure que nous venons de créer pour accéder à notre service Azure Key Vault. À partir du portail Azure, accédez à l’instance Azure Key Vault contenant le certificat que vous souhaitez utiliser pour signer votre package MSIX. Accédez à la section Stratégies d’accès, puis cliquez sur Ajouter une stratégie d’accès. L’outil permet de choisir l’un des modèles disponibles pour définir les autorisations que nous souhaitons accorder mais, dans notre scénario, aucun de ceux-ci n’est adapté. Par conséquent, nous devons définir manuellement, à l’aide des listes déroulantes, les options suivantes :

  • Sous Autorisations de clé, activez l’option Signer.
  • Sous Autorisations de certificat, activez l’option Obtenir .

La dernière étape importante consiste à spécifier l’application qui va accéder à cette stratégie. Cliquez sur Sélectionner le principal, puis recherchez l’application Azure que vous avez créée à l’étape précédente en utilisant son nom. Dans l’exemple, elle est nommée SignToolForContoso.

Select principal

Une fois que vous l’avez trouvée, appuyez sur Sélectionner. La stratégie devrait ressembler à ceci.

Add access policy

Une fois le processus terminé, cliquez sur Ajouter pour créer la stratégie.

Utiliser Azure SignTool pour signer le package localement

À présent que la configuration d’Azure est terminée, nous pouvons utiliser Azure SignTool pour signer le package. Dans cette section, nous allons utiliser l’outil localement pour nous familiariser avec celui-ci. Dans les sections suivantes, nous allons l’utiliser dans le cadre d’un pipeline CI/CD.

L’outil est disponible en tant qu’outil global .NET. Vérifiez que le Kit de développement logiciel (SDK) .NET le plus récent est installé, puis ouvrez une invite de commandes et exécutez la commande suivante :

dotnet tool install --global AzureSignTool 

Vous pouvez maintenant signer votre package à l’aide de la commande AzureSignTool qui requiert les paramètres suivants :

  • kvu est l’URL de votre Azure Key Vault. Celle-ci figure dans la page principale du service, dans le portail Azure, sous Nom DNS.
  • kvi est l’ID d’application de l’application Azure que vous avez inscrite et notée précédemment.
  • kvs est la clé secrète client que vous avez générée et notée précédemment.
  • kvc est le nom convivial du certificat que vous souhaitez utiliser.
  • tr est l’URL d’un serveur d’horodatage. Cette option nous permet d’activer notre package de façon à ce qu’il fonctionne également après l’expiration du certificat.
  • v est le chemin d’accès du package MSIX que nous voulons signer.

Voici un exemple de commande :

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

Remarque

Pour en savoir plus sur AzureSignTool, exécutez AzureSignTool sign --help

Utilisation d’Azure SignTool avec Azure Pipelines

Cette section part du principe que vous disposez déjà d’un pipeline CI/CD pour une application Windows configurée avec un fichier YAML sur Azure Pipelines, comme expliqué ici.

Dans un premier temps, vous allez devoir créer quelques variables pour stocker les informations dont SignTool Azure a besoin pour se connecter à Azure Key Vault. Dans Azure DevOps, sélectionnez votre pipeline, puis, en haut, appuyez sur le bouton Modifier. Une fois dans l’éditeur YAML, cliquez sur le bouton Variables en haut pour ouvrir le volet. Vous allez cliquer sur le bouton + pour ajouter les variables suivantes :

  • AzureKeyVaultName, avec le nom convivial de votre coffre.
  • AzureKeyVaultUrl, avec l’URL de votre coffre.
  • AzureKeyVaultClientId, avec l’ID d’application de votre application Azure.
  • AzureKeyVaultClientSecret, avec la clé secrète client de votre application Azure.

Pour chaque variable, veillez à activer l’option Garder cette valeur secrète. Cela permet de s’assurer d’autres personnes ayant accès au pipeline ne pourront pas voir les valeurs.

Add variable

Vous pouvez maintenant personnaliser votre pipeline YAML existant en ajoutant une tâche .NET Core pour installer Azure SignTool sur l’agent. Voici le code YAML à ajouter :

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

L’étape suivante consiste à ajouter une tâche PowerShell pour exécuter la commande qui signera le package. Vous devez effectuer cette tâche uniquement à la fin du processus de génération, une fois le package MSIX créé.

- 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'

La commande est similaire à celle que nous avons utilisée pour signer le package localement. Les seuls différences sont les suivantes :

  • Au lieu d’utiliser des valeurs fixes pour les différents paramètres, nous utilisons les variables créées avec la syntaxe $(Variable-Nom).
  • Le chemin d’accès du package MSIX pointe vers le dossier sur l’agent où le package MSIX est créé à la fin de la génération.

Utilisation d’Azure SignTool avec des GitHub Actions

Cette section part du principe que vous disposez déjà d’un pipeline CI/CD pour une application Windows configurée avec un fichier YAML sur GitHub Actions, comme expliqué ici.

Comme nous l’avons fait à la première étape sur Azure Pipelines, nous devons stocker les informations d’identification en toute sécurité. GitHub utilise des secrets que vous pouvez ajouter aux paramètres de votre dépôt. Une fois sur le dépôt GitHub hébergeant votre application Windows, cliquez sur Paramètres, puis accédez à Secrets.

Comme vous l’avez fait avec Azure Pipelines, cliquez sur Nouveau secret pour créer quatre secrets :

  • AzureKeyVaultName, avec le nom convivial de votre coffre.
  • AzureKeyVaultUrl, avec l’URL de votre coffre.
  • AzureKeyVaultClientId, avec l’ID d’application de votre application Azure.
  • AzureKeyVaultClientSecret, avec la clé secrète client de votre application Azure.

La différence par rapport à Azure Pipelines est que les secrets sont implicitement masqués, de sorte que vous n’avez aucune option à activer pour les protéger.

Maintenant, sous l’onglet Actions de votre dépôt, vous pouvez ouvrir votre flux de travail et ajouter les tâches nécessaires pour effectuer la signature. La première installe l’outil AzureSign sur l’agent :

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

La deuxième signe le package et, par conséquent, doit être exécutée une fois la build Visual Studio terminée et le package MSIX généré.

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

Cette tâche présente des différences par rapport à celle que nous avons utilisée dans Azure Pipelines. L’une est que GitHub utilise une syntaxe différente pour accéder aux secrets, à savoir ${{ secrets.SECRET_NAME }}. Par conséquent, les différents paramètres présentent les valeurs que nous avons créées précédemment dans la section Secrets. L’autre est que vous devez utiliser une approche différente pour rechercher les packages MSIX à signer. La tâche, au lieu de pointer vers un package MSIX spécifique, utilise un script PowerShell qui itère dans tous les fichiers stockés dans la sortie de la build. Si le fichier a l’extension MSIX, la commande AzureSignTool est utilisée pour le signer.

Déploiement du package

Quelle que soit la plateforme CI/CD choisie, à la fin du flux, vous aurez un package MSIX signé avec votre certificat stocké sur Azure Key Vault. Vous pouvez désormais utiliser n’importe quelle autre tâche disponible pour déployer le package via votre mode de distribution favori : Microsoft Store, un site Web, Microsoft Intune, etc.