Sign PowerShell Scripts With An Enterprise PKI

PowerShell Execution Policy can be used as a control policy, to protect the administrators, or even the users, from accidental script execution. Do not think of it as a security measure, because it will not protect you from copy/paste the content of any script in the command line or run each script command by hand.

The Get-ExecutionPolicy cmdlet will show you the current policy on the machine and you can change the policy with the Set-ExecutionPolicy cmdlet and choose one of the following execution policies:

  • Restricted: No scripts can be run. Windows PowerShell can be used only in interactive mode.
  • AllSigned: Only scripts signed by a trusted publisher can be run.
  • RemoteSigned: Downloaded scripts must be signed by a trusted publisher before they can be run.
  • Unrestricted: No restrictions; all Windows PowerShell scripts can be run with a confirmation prompt.
  • Bypass: No restrictions, all Windows PowerShell scripts can be run

You can set the execution policy across your domain, using group policy. Create a new group policy (or add to an existing one), expand Computer Configuration\Policies\Administrative Templates\ Windows Components\Windows PowerShell and edit the Turn on Script Execution policy.

The recommended policies for a controlled enterprise environment, are AllSigned or RemoteSigned. In case you set the Execution Policy to one of these policies, you need to sign PowerShell scripts, in order for things to run smooth.

In this article I will describe the full procedure with all the steps, to sign PowerShell scripts in your environment, assuming that you have at least a domain controller in your environment and a Public Key Infrastructure (PKI).

Step 1. First we need to create the code signing certificate template, which we will enable on the Issuing Certificate Server.

On your CA Issuing server, open Certificate Authority tool, right click on Certificate Templates container and select Manage

sign-powershell-scripts-with-an-enterprise-pki-01

Locate the Code Signing template in the Certificate Templates Console and right click, Duplicate Template

sign-powershell-scripts-with-an-enterprise-pki-02

Set the properties of the new template, according to your environment. Below are the settings of my Code Signing template on my test environment. Leave the rest properties on default settings if you are not sure what to change. Notice the Security tab, I have allowed enroll permission for the PKI_Enroll_redmad.com_Code_Sign_24M security group (this is a global security group created in the AD, which its members will be authorized to enroll for a code sign certificate)

Close the Certificate Templates Console. In the Certificate Authority Tool, right click on the Certificate Templates, once again and select New-Certificate Template To Issuesign-powershell-scripts-with-an-enterprise-pki-08

In the Enable Certificate Templates window, select the template we have just created and click oksign-powershell-scripts-with-an-enterprise-pki-09

Step 2. Add your users in the members of the group with certificate enrollment permission

The group I created above is PKI_Enroll_redmad.com_CodeSign_24M, which will be able to sign PowerShell scripts. I will add my user espresso
sign-powershell-scripts-with-an-enterprise-pki-10

Step 3. Request a code signing certificate from the Issuing CA

Login with the user who is member of the above group and request the certificate

Open Microsoft Management Console (mmc.exe), and go to File – Add/Remove Snap-in…
Select Certificate from the Available snap-ins, click Add and select My user account, to open the store of the current user. Click oksign-powershell-scripts-with-an-enterprise-pki-11

Go to the Personal Container and right click, All Tasks, Request New Certificatesign-powershell-scripts-with-an-enterprise-pki-12

Next, Select Active Directory Enrollment Policy and Next. A List with the available certificate templates will appear. Select the one we created above and click Enroll (If you do not see the certificate template we created, logoff and logon again)

sign-powershell-scripts-with-an-enterprise-pki-13

You should see STATUS: Succeeded

sign-powershell-scripts-with-an-enterprise-pki-14

Click Finish. In the Personal container you should now see the certificate to sign PowerShell scripts.sign-powershell-scripts-with-an-enterprise-pki-15

Step 4. Deploy the code signing certificate in the Trusted Publishers Store

Export the code signing certificate

sign-powershell-scripts-with-an-enterprise-pki-16-deploy-the-code-signing-certificate

You will export only the public part of the certificate (not the private)

sign-powershell-scripts-with-an-enterprise-pki-17-deploy-the-code-signing-certificate

In the file format, choose Base-64 encoded (or DER)

sign-powershell-scripts-with-an-enterprise-pki-18-deploy-the-code-signing-certificate

Specify the file name of the file you want to export, Next, Finish

sign-powershell-scripts-with-an-enterprise-pki-19-deploy-the-code-signing-certificate

Open Group Policy Management to create a new policy object, to deploy the code signing certificate across your domain

sign-powershell-scripts-with-an-enterprise-pki-20-deploy-the-code-signing-certificate

Name the new policy

sign-powershell-scripts-with-an-enterprise-pki-21-deploy-the-code-signing-certificate

And then edit the policy and expand Computer Configuration\Policies\Windows Settings\Security Settings\Public Key Policies\Trusted Publishers, Right click on Trusted Publishers and select Import

sign-powershell-scripts-with-an-enterprise-pki-22-deploy-the-code-signing-certificate

Certificate Import Wizard will pop up, click Next and locate the certificate you exported

sign-powershell-scripts-with-an-enterprise-pki-23-deploy-the-code-signing-certificate

Continue, with Next, notice that the wizard will place the selected certificate in the Trusted Publishers

sign-powershell-scripts-with-an-enterprise-pki-24-deploy-the-code-signing-certificate

Make sure that group policy object you made previously, is applied on the machine you are logged on (also on the machines you are going to run the signed PowerShell scripts)
run gpupdate /force to enforce the policy settings

So, now we have the certificate to sign PowerShell Scripts and also we trust this certificate as a Publisher.

STEP 5. Signing the script

I will use the following script version.ps1

sign-powershell-scripts-with-an-enterprise-pki-25

For signing the certificate, we will use the Set-AuthenticodeSignature cmdlet

First we need to save the code signing certificate in a variable

sign-powershell-scripts-with-an-enterprise-pki-26

Then sign the script

sign-powershell-scripts-with-an-enterprise-pki-27

You can now check your script ans see it is signed

sign-powershell-scripts-with-an-enterprise-pki-28

Your script is now signed. Repeat Step 5 for all your scripts.