patpitchaya - Fotolia

Create a self-signed certificate to control PowerShell scripts

Signing code ensures that every change is official and approved. This helps to prevent errors and security breaches. Write a PowerShell self-signed certificate for code testing.

Change can be dangerous. This is especially true in large IT environments, wherein only approved versions of scripts should run. Signing code helps ensure script integrity and enforce good computing hygiene.

With Microsoft PowerShell, most admins use the Set-ExecutionPolicy RemoteSigned command and effectively negate enterprise security. RemoteSigned is one step more secure than an unrestricted policy, so it enables a great deal of freedom for execution. Microsoft's execution policy options include Unrestricted, RemoteSigned, AllSigned, Restricted, Default, Bypass and Undefined. For added ops security, change the policy to run only signed code, under the AllSigned option. To try it out, create your own self-signed certificate.

Author's note: This article covers self-signed certificates for testing purposes. In a production environment, the certificate should be signed by the corporate root certificate. To tighten up control and restrict code execution to scripts signed by a trusted individual, a Windows administrator can modify the policy around PowerShell execution using Group Policy Objects (GPOs).

To modify the execution policy in Windows on a local workstation, open the PowerShell console with administrative privileges. Use the Get-ExecutionPolicy command to display the current execution policy setting. As mentioned, most organizations rely on RemoteSigned, which does not require a signature if the script was written locally. It only restricts code from outside sources.

This PowerShell script is a simple one that takes your name as input and outputs it in a sentence, courtesy of The PowerShell Guy's blog:

$yourName=Read-Host "What is your name?"

Write-Host "Hello $yourName"

Change the execution policy to run only signed code with AllSigned, controlling internal and external sources:

     Set-ExecutionPolicy AllSigned

Any change prompts the administrator for approval.

PowerShell execution policy
Figure 1. Set the execution policy in PowerShell.

An attempt to run PowerShell scripts at this point would fail because code isn't signed, but this only restricts the use of scripts and potentially any add-in modules from running.

Unsigned PowerShell script
Figure 2. An unsigned script won't run on PowerShell now that the execution policy calls for AllSigned.

Administrators can still use the PowerShell console for individual commands, but not full scripts. Although there are several other execution policies, this tutorial focuses on how to ensure only signed code runs. This can be enforced via GPO.

Create a new self-signed certificate for demonstration purposes. Microsoft added the New-SelfSignedCertificate cmdlet in PowerShell 4 and eliminated the need for a separate certificate tool, such as MakeCert.

To utilize this cmdlet, run the following command on a system with Windows 8.1 and up. Include the to allow the command to stretch over several lines.

     $mycert = New-SelfSignedCertificate  -Subject "CN=PowerShell signing example" `

              -KeyAlgorithm RSA -KeyLength 2048   -Type CodeSigningCert `

              -CertStoreLocation Cert:\LocalMachine\My\

PowerShell New-SelfSignedCertificate
Figure 3. PowerShell creates a new self-signed certification from the command listed above.

The above code snippet creates a new certificate (see Figure 3) and assigns it to the variable $mycert. The key is stored in the local certificate store. The -Type CodeSigningCert switch is vital to include to create the correct certificate type. The common name should be useful and intuitive.

To ensure the self-signed certificate generates correctly, type the variable name in PowerShell, $mycert, to make PowerShell echo the variable contents and display the certificate thumbprint.

PowerShell $mycert self-signed certification verification
Figure 4. The admin can verify the self-signed certificate was created correctly with $mycert.

Move the certificate to the root certificate store with the following command:

Move-Item "Cert:\LocalMachine\My\$($mycert.Thumbprint)" Cert:\LocalMachine\Root

To sign this code example, assign the certificate thumbprint to a variable, which will make it easier to use.

$myrootcert = "Cert:\LocalMachine\Root\$($mycert.Thumbprint)"

Now, sign the PowerShell script with the following:

set-AuthenticodeSignature \Users\Stuart\Desktop\test.ps1 $mycert

This PowerShell file should now be correctly signed. Because the code is not signed by a trusted provider -- just your own self-signed certificate -- you must run the code. Press R to run once or A to accept recurring use.

PowerShell self-signed certificate choices
Figure 5. PowerShell gives the admin the option to never run, not run, run once or always run the self-signed certificate.

At the bottom of the PowerShell script file, a section of new code appears: the certificate thumbprint. If either the script or the signing code at the bottom is modified, the script will not run.

This process enabled signed code in PowerShell for a test. Don't try to use this self-signed certificate for the entire estate. Organizations should install an official certificate in a production environment to ensure only signed certificates authorized by the company work.

Dig Deeper on Systems automation and orchestration

Software Quality
App Architecture
Cloud Computing
Data Center