powershellscripts.com

Tutorials  Tutorials

Powershell Basics
Introduction to Windows PowerShell Part 1
Introduction to Windows PowerShell Part 2
Introduction to Windows PowerShell Part 3
PowerShell Script Signing
PowerShell Scheduled Tasks
PowerShell Networking Tasks

Powershell Advanced Tutorials
PowerShell and VMware Introduction



 



PowerShell Script Signing (Why won't my script run?)

Anyone just starting out with PowerShell has probably tried to run a script only to see this error:

	echo get-help > test.ps1
	test.ps1
	.\test.ps1
	
	File C:\scripts\test.ps1 cannot be loaded because the execution of 
	scripts is disabled on this system. Please see "get-help about_signing" 
	for more details.
	
As part of PowerShell's "secure by default" initial setup, scripts are not allowed to be ran by the command interpreter.  This behavior can be modified by changing the PowerShell execution policy. There are four execution polices to choose from.
For most budding scripter's the RemoteSigned option is the proper security level. This will let you test your own code while still giving a little bit of added security against outside attacks. Finding your current execution level and changing its value is a simple process.
	PS C:\scripts> Get-ExecutionPolicy
	Restricted
	
	PS C:\scripts> Set-ExecutionPolicy RemoteSigned
	
	PS C:\scripts> Get-ExecutionPolicy
	RemoteSigned
Detailed information about each policy level can be found in the get-help about_signing help file.

Script Signing
For most admin's, relaxing the default signing level is all they need to get started.  However, what if you would like to keep the default security level high but still run scripts?  Or you would like to deploy a script you write across your enterprise without changing every system's execution policy.  In these cases you would want to sign the script. Remember, before signing any script make sure you have examined it and verify it is safe to run in it's intended environment.  The two types of certificates used for signing a script file are certificates created by a certificate authority (Verisign etc..) or cert's that you create yourself (self signed certs).  Using self signed certs is useful for controlling security on the machine that created them, but not on other systems without additional configuration since they will not trust your machine as a certificate authority.  Let's try creating our own certificate.

Before We Begin
Let's set our Execution Policy to AllSigned to make sure we are requiring digital signatures.

Creating the Certificate
Before we can do any digital signing, we will need a tool to create the certificate.  The makecert.exe executable included in the .Net SDK (1.1 or higher) should do the trick.  If you don't already have the SDK installed you can get a copy here.  Online documentation for makecert can be found here.  Once downloaded and installed,  run the sdk command prompt.  From here we'll create the local certificate authority and a personal certificate.
	C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0>makecert -n 
	"CN=PowerShell Local Certificate Root" -a sha1 `
	-eku 1.3.6.1.5.5.7.3.3 -r -sv root.pvk root.cer `
	-ss Root -sr localMachine
	
	C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0>makecert -pe -n 
	"CN=PowerShell User" -ss MY -a sha1 `
	-eku 1.3.6.1.5.5.7.3.3 -iv root.pvk -ic root.cer
After running these commands you will be prompted to provide passwords.  There are a number of ways to determine if the cert was created correctly including looking in the Certificated snap-in MMC or running the following PowerShell command (includes output):
	PS C:\scripts> get-childitem cert:\CurrentUser\My -codesigning

	Directory: Microsoft.PowerShell.Security\Certificate::CurrentUser\My

	Thumbprint Subject
	---------- -------
	1A06757DE2EA2AA89D5CCB7E5730ED090D92D88E CN=PowerShell User
Sign the Script
Now that we have our certificate it's time to create the script and get it signed.
	echo get-location > signed-script.ps1
We now have our one line script created, let's sign it.
	$cert = @(Get-ChildItem cert:\CurrentUser\My -codesigning)[0]
	Set-AuthenticodeSignature signed-script.ps1 $cert

	Directory: C:\scripts

	SignerCertificate 				Status 	Path
	----------------- 				------	----
	1A06757DE2EA2AA89D5CCB7E5730ED090D92D88E 	Valid 	signed-script.ps1
Hey, that was easy.  If you open up your script file in an editor you'll notice that it now has a large signature block section in it. Use Get-AuthenticodeSignature to see the file's new signature details.

Enable Strong Key Protection
To keep malicious programs on your computer from utilizing your newly created cert it is best practice to enable strong key protection which will force the user to provide a password when signing. A GUI tool, certmgr.exe can be used to export the certificate to a secured .pfx file.  The get-help about_signing help file has step-by-step instructions on how to perform this process.