Comment signer un script Powershell ?

I. Présentation

Aujourd'hui dans un environnement Microsoft, il y a mille et une raisons d'utiliser PowerShell ! Que ce soit pour l'administration et la configuration des serveurs, mais aussi pour exécuter des scripts via GPO sur les postes clients. Pour avoir cette possibilité qui est clairement indispensable, sans remettre en cause la sécurité des postes clients, il s'avère pertinent de signer les scripts PowerShell pour autoriser uniquement les scripts signés sur vos postes clients. Ceci vous permettra d'exécuter vos scripts sur un poste où la stratégie d'exécution PowerShell est définie sur "AllSigned".


Avant de continuer, vous devez avoir une autorité de certification opérationnelle, vous pouvez lire notre tutoriel à ce sujet : Créer une autorité de certification ADCS. Pour les tests, prévoyais également un poste client dans le domaine.

II. Générer un certificat pour signer du code

Connectez-vous sur votre autorité de certification (où le rôle ADCS est présent) et ouvrez une console PowerShell en tant qu'administrateur. Nous allons devoir créer un certificat dédié à la signature de code, mais avant cela il faut inclure le template grâce à la commande suivante :

Add-CATemplate -Name CodeSigning

Confirmez l'exécution de l'action, et listez les templates de votre autorité de certification : "CodeSigning" doit apparaître.

Toujours sur le serveur ADCS, ouvrez une console MMC vierge et ajoutez le composant "Certificats" pour l'utilisateur actuel.

Sur "Personnel", effectuez un clic droit et sélectionnez la tâche "Demander un nouveau certificat".

Sélectionnez "Stratégie d'inscription à Active Directory".

Nous allons demander un certificat "Signature du code", sélectionnez la case adéquate.

Si l'on regarde les détails, nous pouvons voir que le certificat sera valide 365 jours. Avant de cliquer sur "Inscription", cliquez sur "Propriétés" puis dans l'onglet "Clé privée" activez l'option "Permettre l'exportation de la clé privée".

Si vous obtenez le message "Opération réussie" alors c'est tout bon ! Vous pouvez afficher le certificat si vous le souhaitez.

Le certificat est bien valide 365 jours comme nous pouvons le voir (bon, j'avoue, ça fait un moment que j'ai pris les captures d'écrans...).

Maintenant que le certificat est créé, il ne reste plus qu'à l'utiliser pour signer un script PowerShell 🙂

III. Déployer le certificat sur les postes clients

Le certificat doit être approuvé par les postes clients, nous allons le déployer par GPO. Pour cela, il faut l'exporter donc toujours à partir de la console MMC précédemment ouverte, effectuez un clic droit sur le certificat puis lancez la tâche "Exporter".

Suivez l'assistant et sélectionnez les deux paramètres suivants : "Non, ne pas exporter la clé privée" et "X.509 binaire encodé DER (*.cer)". Enfin, donnez un nom au certificat et exportez-le.

Connectez-vous sur votre contrôleur de domaine et copiez le certificat dessus. Ensuite, créez une nouvelle GPO qui va déployer le certificat.

Voici à quel endroit vous devez importer le certificat (via un clic droit "Importer" une fois dans "Editeurs approuvés").

La GPO est prête, positionnez-la sur votre domaine pour que le certificat soit déployé ! Passons à la suite.

IV. Signer un script PowerShell

Basculez maintenant sur un poste client, idéalement Windows 10 puisque c'est la version qui tend à être utilisée à la place de Windows 7 petit à petit. Mettez à jour les GPO sur le poste et redémarrez-le :

gpupdate /force

Nous allons définir la politique d'exécution des scripts du poste sur "AllSigned" :

Set-ExecutionPolicy AllSigned

Maintenant qu'il est redémarré, le certificat doit être présent dans le magasin local. Nous pouvons le vérifier avec cette commande :

Get-ChildItem Cert:\CurrentUser\My\ -CodeSigningCert

Maintenant, nous allons exécuter le script "IT-CONNECT.ps1" qui n'est pas signé et vous pourrez constater que ça ne fonctionne pas. Ceci est logique car la stratégie est définie sur "AllSigned". Ce qui donne l'erreur suivante :

Tous les éléments étant maintenant réuni pour que l'on signe notre script PowerShell, on ne va pas s'en priver ! Pour signer le script, on va utiliser le code suivant :

$CertCodeSigning = Get-ChildItem Cert:\CurrentUser\My\ -CodeSigningCert
$ScriptToSign = "C:\Scripting\Scripts\IT-CONNECT.ps1"
$TimestampServer = "http://timestamp.comodoca.com/authenticode"

Set-AuthenticodeSignature $ScriptToSign -Certificate $CertCodeSigning -TimestampServer $TimestampServer

Voici quelques infos sur les variables utilisées :

  • CertCodeSigning : Chemin vers lequel récupérer le certificat de signature du code
  • ScriptToSign : Chemin vers le fichier PS1 de notre script PowerShell
  • TimestampServer : On s'appuie sur un service externe qui va permettre de dater notre signature, ainsi, lorsque le certificat sera expiré la signature restera valable car elle fût réalisée pendant que le certificat était valide

Enfin, on va utiliser ces 3 variables dans le cmdlet Set-AuthenticodeSignature pour signer le script PowerShell.

Si l'on ouvre le script, on voit qu'il contient maintenant une signature :

Retournez sur le poste client et exécutez le script à nouveau : il doit maintenant s'exécuter directement 😉

Voilà, vous pouvez maintenant mettre en place cette configuration et dégainer les signatures sur tout vos scripts PowerShell en production.

En bonus, je vous livre un bout de code qui va signer automatiquement tous les fichiers PS1 contenu dans un dossier. Il vous suffit de modifier le chemin du dossier contenu dans la variable $ScriptFolder :

$CertCodeSigning = Get-ChildItem Cert:\CurrentUser\My\ -CodeSigningCert
$TimestampServer = "http://timestamp.comodoca.com/authenticode"

$ScriptFolder = "C:\Dossier\Scripts"
$ScriptList = (Get-ChildItem $ScriptFolder -Filter "*.ps1").FullName

Foreach($ScriptToSign in $ScriptList){

   Write-Output "Traitement du script : $ScriptToSign"
   Set-AuthenticodeSignature $ScriptToSign -Certificate $CertCodeSigning -TimestampServer $TimestampServer

}

Partagez cet article Partager sur Twitter Partager sur Facebook Partager sur Linkedin Partager sur Google+ Envoyer par mail

Florian B.

Co-Fondateur d'IT-Connect, je souhaite partager mes connaissances et expériences avec vous, et comme la veille techno' est importante je partage aussi des actus.

florian has 1854 posts and counting.See all posts by florian

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

 

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.