How to sign your first script in 48 hours

Problem


When a problem requiring a solution is small, you don’t feel like writing a separate utility to solve it, especially if you are a .NET programmer.
Script? Definitely, yes, but putting a third-party interpreter on a Windows-based combat vehicle is not at all Christian. So why not use Windows Powershell? I’m ready to immediately honestly admit: there was practically no experience with him, but it looked very tempting.
The script that solves the problem was ready in 15 minutes, if you do not take into account one “but”. It was difficult to call it a script yet, because it was a set of instructions unsuitable for execution as a script. Unsuitable in terms of PowerShell.

There is a reasonable explanation for everything - of course, certain restrictions are set on the execution of scripts that are setscript execution policy . Having created the script, I could not execute it right there on my machine. However, the problem solved for the local machine by temporarily changing the execution policy to Unrestricted or, more correctly, RemoteSigned , on the production server is raised seriously.

There is always a way out. It is logical that the finished script for execution must be signed. The process of organizing the signature mechanism is quite lengthy and thorny, but served as good soil for this post.

After two days of torment at home and in the office, I present to the public a brief manual on signing scripts for PowerShell.

Decision


By default, execution of any scripts is prohibited. To get started, you need to allow execution of only signed scripts from trusted publishers with a trusted root certificate. As part of a Powershell admin session :

> Set-ExecutionPolicy AllSigned

Further dances with a tambourine relate to a utility for creating root and personal certificates.
All certificates, according to the “instructions” for signing scripts,

> Get-Help About_Signing

are created using the makecert.exe utility located in % Program Files% \ Microsoft SDKs \ Windows \ v7.0A \ bin \ makecert

The following two steps are performed as part of a regular command line session:

> 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

> 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


The first line creates the root certificate using the local machine as the certification authority. The most popular “free” way to get a certificate.
The second line creates a personal PowerShell user certificate, which scripts will be signed with, attesting it with a root certificate. If everything went well, both lines should show the Succeeded result .

The above manipulations may not be performed if the X509 personal certificate is already there.

After that, just in case, you can verify that the OS is aware of the certificate that was just created. PowerShell: You

> Get-Childitem cert:\CurrentUser\my -codesigning

can already sign scripts, but in this case, a Powershell line will go to the script signature every time:

> Set-AuthenticodeSignature "FileName" @(Get-ChildItem cert:\CurrentUser\My -codesigning)[0]

It would be logical to create a script that will sign other scripts. The script must be created in any text editor except PowerShell ISE. For scripts created inside this environment, problems with signing as Unknown Error will occur . The decision is made here .

The script itself looks like this: Using the instructions above, we will sign this script itself in the interactive PowerShell mode. After that, the script for execution on another machine can be signed like this:
param([string] $file=$(throw "Please specify a filename."))
$cert = @(Get-ChildItem cert:\CurrentUser\My -codesigning)[0]
Set-AuthenticodeSignature $file $cert




> .\Add-Signature.ps1 MyScript.ps1

Oh sad


On any machine except the one on which the certificate was created:
  1. If the root certificate is not trusted, the script will fail at all.
  2. If the personal certificate of the publisher who signed the script is not trusted, the script will be executed only with confirmation.

In order to add root and personal certificates to trusted certificates, you need to use the mmc admin console with the Certificates snap-in . Add certificates to the Trusted Root Certification Authorities and Trusted Publishers folders .

It does not pretend to be the only true solution, but research results show that so far this is a more or less normal way. I ask those who know to help clarify the situation and poke a link, if possible.

Also popular now: