This continues a short series of posts about getting started with PowerShell … with a few tips about things you can do to keep your PowerShell profile safe and organized. Your “profile” is the script that is automatically loaded when you start up PowerShell. Really, I should say that your profile is the set of scripts which are loaded by default when you start up PowerShell. “By default” because you can always skip loading them by passing the -NoProfile switch to PowerShell.exe, and a set because PowerShell does, in fact, attempt to load at least four scripts when you run it:
PowerShell loads “machine” profile scripts (which are located in the PowerShell folder) and “user” profile scripts (located in your Documents\WindowsPowerShell folder). But there’s a little more to it than that: PowerShell is a scripting engine which can be hosted inside any app, PowerShell.exe is a DOS-style console which is the default host. There are several third-party hosts available such as PowerShell Plus and PowerGUI and several open source hosts such as BgShell and PoshConsole … in order to support this ecosystem of hosts, the default PowerShell behavior is to load a host-specific profile script (for both the machine settings and the local-user settings). Not all hosts will do that, but anyway … the default host loads Microsoft.PowerShell_profile.ps1 and Profile.ps1 from both the user and machine locations.
By default, none of those profiles actually exist. Once you’ve installed everything as in Part 1, you should have a Profile.ps1 file provided by PSCX. This profile defines a whole bunch of values that are used by various PSCX cmdlets and scripts, so you may want to change some of it, but you should be careful about just deleting things until you’re well acquainted with the PSCX cmdlets. Over time, I’ve added settings to my profile for other snapins as well, and there gets to be a lot of noise in there that’s specific to different snapins, so instead of just leaving all of that in my main profile, I rename the Profile.ps1 file provided by PSCX and then dot-source it from a new blank profile script.
In fact, and I found that I started collecting a lot of scripts in my WindowsPowerShell folder so I created a sub-folder for them, and I automatically load everything that’s in that folder, so I don’t have to manually dot-source things when I add a new snapin profile.
In order to make sure that automatically loading scripts doesn’t become a way for people to attack my computer, I made a decision awhile ago that I would only auto-load signed scripts. The how and why of this is a bit much to get into, and I wrote about Generating Windows Authenticode Code-Signing Certificates with OpenSSL a while back, so you can read that if you want more details, I want to review the simplest steps. (more…)
I’ve decided to spend part of this weekend organizing my sock drawer PowerShell profile, and since there doesn’t seem to be a lot of best practices or prescriptive advice on setting up your PowerShell profile, I thought I’d write about how I do it, to help any new users out there get started.
If you are a .Net developer or a Computer Science researcher, and haven’t started using PowerShell, let me just make this argument for learning it:
PowerShell cmdlets are simple to write. The additional code required to make a .Net class into a cmdlet is very minor (at a minimum, a single method with a line of code to
Write-Outputsomething). Since cmdlets must derive from either Cmdlet or PSCmdlet you can’t just write every class as a cmdlet, but even non-cmdlet classes can be instantiated viaNew-Objectand their methods and properties can be exercised.After writing portions of a recent research project as PowerShell cmdlets, I would say that the ability to write a simple class and then use/execute from the command line and in scripts — plus the built in automatic argument parsing (PowerShell assigns pipeline input and command line parameters to object properties for you) makes PowerShell cmdlets quite useful for research and development. Because the overhead is so minimal, it minimizes the distractions of creating a user interface and allows you to focus your actual research goals. Additionally, because the PowerShell-specific code can be restricted to attributes and a method or two, the actual classes are still usable for other purposes. That is, your class is invokable within PowerShell, but it’s also reusabe within any .Net application, whether Windows.Forms, WPF, or even web apps.
Of course, since I’m primarily using PowerShell for research and development, I’m using the current CTP 2 release of PowerShell v2, some of what I’m doing in my profile won’t work until PowerShell 2 is released (next year?). I’ll try to mark the CTP-only features appropriately and offer PowerShell 1-compatible workarounds.
The first step, of course, is to install the software. To take full advantage of PowerShell 2, you need to have the .Net Framework 3.5 although you could use the .Net Framework 2.0 instead if you’re just using PowerShell 1.0. PowerShell 1 is only available as a “patch” so you have to choose the correct download for your platform through the Microsoft Download Center. However, since it’s still in CTP release, there is an installer for PowerShell 2 CTP2.
I also use the PowerShell Community Extensions and recommend them, although there’s a lot in there you may not use, there’s also a lot of extremely useful things — some of which are practically requirements. This package needs updating to work well with PowerShell 2, because PowerShell 2 has implemented natively some of the most popular features in PSCX, but it’s just a few minor changes. If you’re just getting started (or want to follow along with this series of posts), you should let PSCX install it’s profile (if you already have a profile, then in order to follow along with these posts, you should MOVE your profile out of the way before you install PSCX, and go ahead and let it create a profile from scratch).
The cool thing about the way authenticode signatures are implemented is that even if a script is signed with a self-issued certificate, you can still tell if the script has been tampered with… Check this out:
As you can see, in the case of a UNTRUSTED, but correct, signature, you get the UnknownError status. If you checked the output object, it has a StatusMessage which says “A certificate chain could not be built to a trusted root authority”. If the script has been altered (as in my SampleBAD.ps1 scripts) then the signature is incorrect, you get the HashMismatch status, and the corresponding StatusMessage is: “The contents of file SCRIPTS:\TrustedCert\SampleBAD.ps1 may have been tampered because the hash of the file does not match the hash stored in the digital signature. The script will not execute on the system…”
One odd thing is that the messages are inaccurate about not executing the script: if you have your execution policy set to Unrestricted, the signatures aren’t checked at all, and if you have it set to RemoteSigned they are only checked for remote scripts. Furthermore: if you do have your execution policy set to AllSigned, neither the UnknownError nor the HashMismatch script will execute — only the one Valid scripts will.
The bottom line is: you can verify that nothing has happened to the script — even if you don’t trust the person who signed it nor the person, group, or company that issued a certificate to them. Why does this matter? Well, I recently wrote a post about generating self-signed code-signing certificates which can be used for signing PowerShell scripts, and if you chose to distribute scripts signed with one of those certificates, nobody would be able to verify the root CA(Certificate Authority) and so the signatures would never come out as valid.
Is there any usefulness in this? Well, I guess that depends on your perspective, but basically, I think that if I published my scripts signed and tell you on my blog what my certificate thumbprint is … that you’d be more able to trust those scripts than you are now (when they’re not signed at all). Of course, I could go one step further, and publish my own self-signed root CA certificate so you could choose to trust that …
I was recently having a conversation about the future of the PowerShell Script Repository and it involved some discussion of whether it would be safe to use the Repository Scripts to download dependencies automatically… The answer, obviously, is no.
But it started me thinking again about scripts being signed. If you had already chosen to run a script provided by me (which was signed by a certificate you couldn’t verify), maybe you’d be willing to trust other scripts signed by the same certificate, so we could automatically download them. Well, maybe even then you wouldn’t want to trust it, but lets assume that you were running a copy of the PowerShell Script Repository internally at your company …
We could easily have a function that takes the script name and verifies that you have that script available — and if not, it could fetch the script from your designated repository and verify that the signature is valid even if the certificate isn’t signed by a root certificate authority you trust.
Of course, such automatically downloaded scripts would need to be marked as “Remote” so if you had your Execution Policy set to AllSigned or Remote Signed, then the script would only run if you had trusted it’s author (and you wouldn’t even be offered the option if you hadn’t trusted the CA(Certificate Authority) that issued his script. In that case you would need to review the script and re-sign it yourself — or manually remove the “remote” bit.
Imagine something like this:
When you tried to execute Get-Paste, it would check for Get-Webfile, and if it couldn’t find it, would attempt to download it (presumably this would involve asking your permission, and placing it in some specific location that was in your PATH, so that the script could find it when it tried to execute it on the next line).
Perhaps instead of this mechanism, we could use the new embeddable “Data Language” to provide a list of dependencies, like: DATA Dependencies { scripts = Get-WebFile } and run a Resolve-Dependencies function against each script before trying to execute it — this way, if you downloaded a script from the repository using Get-Paste, it could automatically Resolve-Dependencies and offer to download the other scripts at the same time.
The fact is that doing this correctly will require some major reworking of the script repository to allow tracking new versions of scripts better, and to let the script repository track dependencies explicitly so that you don’t have to download the whole script to find out what it’s dependencies are, but this could be done, if people are actually interested in it.
Ad I’m thinking about this, I’m wondering again about the possibility of creating an informal web-of-trust style code-signing certificate tree. The idea would be that the Script Repository would have a CA certificate of it’s own, and would issue code-signing certificates to PowerShell developers cheaply (free?) by skipping over some of the usual verification steps. In an ideal world, Microsoft would issue the PowerShell Community a “SubCA” certificate signed by their root — in the interests of promoting code signing for PowerShell …
However, if we couldn’t get a SubCA certificate for “free” or cheap, we could simply generate and self-sign our own, and publish it on the Script Repository website, requiring users to download and import it into their trusted roots if they wanted to use trust permissions. Regardless of whether they chose to trust it or not, they could still verify the scripts were valid, which is better than what we have now — the rest would be up to the user.
Of course, if we were issuing certificates that were self-signed anyway, we could go a step further and sign SubCAs and distribute them to, say, the Microsoft PowerShell MVPs and trusted community leaders after verifying email addresses and physical mailing addresses etc … trusting them further to issue (less trusted) code-signing certificates to additional developers.
All of this is extra work for the people maintaining the script repository web site (right now, that’s me), but it might be worth it if it makes it easier to use the script repository, easier to trust the scripts on it, and easier to verify that an author is who he says he is … what do you think?
So, I’ve been called out on this latest meme posting by /\/\o\/\/ and although I usually just ignore these things,
As with any curious developer, I had to trace this thing back to it’s root cause … it turns out this started as a Software Development thing, and it was altered into a sort of SysAdmin thing.
So, since I’m putting up with this in the first place, I think I’ll go back to that original developer-oriented list of questions, if you don’t mind. 
One of the major security features of PowerShell is the support for code signing of scripts, so that you can set an execution policy that requires scripts to be signed before they can be run. Of course, it goes a bit further than that. When a script has been signed by a certificate with a root Certificate Authority (CA) that you don’t already “know” or trust it can’t be run at all until you add the root CA to the system’s certificate store.
Even after you trust a specific authority, you haven’t trusted a script author — so any signed script you run will prompt you whether you want to allow it or not, like so:
The important thing to note here is that you’re really being asked not about the script, but about the author. If you choose the Never or Always options, the certificate that was used to sign the script is added to the appropriate certificate store (“Untrusted Certificates” or “Trusted Publishers”, respectively). To be clear: this happens for each every new author certificate, regardless of whether it’s signed by a self-signed cert (where you’ve already installed the root certificate in your root store) or a certificate issued by a commercial CA — there’s no loophole, no matter what anyone may have said in the past.
So, you see … the support for code signing is built into the core of PowerShell — and it’s really a shame not to take advantage of it. There are plenty of articles out there about how to sign your scripts, and more, so I’m not going to get into that much — I want to address the question of how hard it is to create the certificates in the first place (and finish by giving you a sample script which will generate and import them to your dev box with a single line command).
(more…)There are two requests that I get with overwhelming regularity for the PowerShell script repository: first, that I would add some sort of “browsing” functionality, and second, that it should have an RSS feed. Well, browsing may have to wait until a future iteration of the repository, but feeds are easy, because they’re basically just a hack-up of the “recent” items that are in the repository sidebar already, so I did it this evening.
PowerShellCentral.com/scripts/feed
Right now the number of items is limited to about ten, but if traffic picks up I can increase that easily — you can limit the count by passing the number of items you want to list like this: ?list=2.
You can also create a feed for specific search results (the feed will show items in relevance order, but the date is in the RSS so if you want to sort by that, you can). For instance, if you wanted to keep up to date on scripts that used SecureStrings, you would append your search terms like this: ?q=*securestring*. 
As usual, my modifications to the PasteBin.com site are available on the repository site, and without much in the way of documentation. I will say this: in addition to creating the feed.php file, I moved some of the common translation functions into a translate.php file, and modified the dates that were being returned from db.mysql.class.php — it’s all under the Affero General Public License that Paul Dixon wrote PasteBin under in the first place.