Your basic ITPro blog... What's going on at work, what I'm interested in.

Wednesday, July 2, 2008

Signing PowerShell Scripts

Talk has begun around here of using PowerShell on our servers. Up until now, I have just been running it on my laptop, using my scripts myself. But, with talk of distributing this functionality and expanding our use of PoSH, it is also time to start thinking about script security.

To that end, I have begun looking in to script signing. Now, I am not going to spend a lot of time writing up what little I know about this topic. There is a ton of other information out there that is way better than anything I could produce. I will say, however, that one particular post was most helpful for me.

You can find the post here.

Scott Hanselman does a great job of taking you through the process of creating a self-signed cert for code-signing. Check it out!

A couple of things I did run across... When I turned on AllSigned "Set-ExecutionPolicy AllSigned", I had to then sign every script that I might run. Of course, this is exactly by design. But, I was just thinking about the scripts that I write. But, it wasn't long before I realized that my profile wouldn't load either. So, I had to sign that. Then, my profile calls various scripts, to pre-load a bunch of stuff... All those had to be signed. You get the idea.

To help me in my new environment, I wrote a couple little functions to do the signing for me. The first one just signs a script I pass it:

function Sign-Script
(
    [string]$Script
)
{
    begin {
        function Usage() {
            Write-Host ''
            Write-Host 'FUNCTION: Sign-Script' -ForegroundColor White
            Write-Host ''
            Write-Host 'USAGE'
            Write-Host '    Sign-Script'
            Write-Host '    Sign-Script "C:\scripts\myScript.ps1"'
            Write-Host ''
            Write-Host 'SYNOPSIS'
            Write-Host '    Digitally signs a script file'
            Write-Host ''
            Write-Host 'PARAMETERS'
            Write-Host '    $Script as string     DEFAULT: none   ( example: "C:\scripts\myScript.ps1" )'
            Write-Host ''
        }
        if (($Args[0] -eq "-?") -or ($Args[0] -eq "-help")) {
            Usage
            break
        }
    }
    process {
        if ($Script) {
            $cert = Get-ChildItem cert:\CurrentUser\My -codesigning
            Set-AuthenticodeSignature $Script $cert
        }
        else {
            Write-Host "Please provide a script to sign."
        }
    }
}

The second function refreshes the signatures on all the scripts in my 'library'. I have a \library folder that holds all of my functions and scripts I pre-load for every PoSH session. If I ever change these scripts (which I do often) I have to re-sign them or the hash is wrong and the script won't run. This function takes care of that for me.

function Sign-LibraryScripts
{
    begin {
        function Usage() {
            Write-Host ''
            Write-Host 'FUNCTION: Sign-LibraryScripts' -ForegroundColor White
            Write-Host ''
            Write-Host 'USAGE'
            Write-Host '    Sign-LibraryScripts'
            Write-Host ''
            Write-Host 'SYNOPSIS'
            Write-Host '    Digitally signs my library script files'
            Write-Host ''
            Write-Host 'PARAMETERS'
            Write-Host '    none'
            Write-Host ''
        }
        if (($Args[0] -eq "-?") -or ($Args[0] -eq "-help")) {
            Usage
            break
        }
    }
    process {
        $cert = Get-ChildItem cert:\CurrentUser\My -codesigning
        $scripts = Get-ChildItem C:\scripts\Library\*.ps1
        foreach ($script in $scripts) {
            Set-AuthenticodeSignature $script $cert
        }
    }
}

No comments:

Additional Info

My photo
email: support (AT) mangrumtech (DOT) com
mobile: 480-270-4332