Tuesday, June 22, 2010

Either My Scripts Don’t Run Or They All Do!

So, you’re all excited about this PowerShell thing – You went and bought a couple of books, started browsing the web, and were looking forward to having a tool kit chock full of scripting goodness.

The first thing you did was start PowerShell. I am assuming here that you were running PowerShell 2.0 (x64) because you were wanting to use it with SharePoint 2010. If you are not sure what version you have, take a look at my previous post about PowerShell versions – http://blog.sharepointcookbook.com/2010/06/what-version-of-powershell-am-i-using.html

So you went and downloaded a killer looking .PS1 script from Microsoft or some other place, and proceeded to run it on your system. You opened the PowerShell window, tried to run the script “./MyNewDownloadedScript.ps1”, and PowerShell refused to run your script saying “the execution of scripts is disabled on this system”.

SNAGHTML1c5accb

Now what? Well, this restriction is a well-intentioned (and pretty effective) effort on Microsoft’s part to keep us SharePoint Admins from downloading PowerShell code that may be buggy or malicious in origin.

If you do a typical internet search on this error message, you’ll find that the default setting for the Execution Policy is set to “Restricted”. You can see this in the PowerShell environment by typing Get-ExecutionPolicy.

image

A little more searching, and Voila! You have one solution – simply shut off the ExecutionPolicy by typing Set-ExecutionPolicy Unrestricted. Now you can just run your scripts.

image

But wait a second, what did you just do? Is this really the right solution in the long term?

Looking at the screenshot above, did you notice the warning - “Changing the execution policy might expose you to security risks”? Setting the Execution Policy to Unrestricted simply bypassed all of the security measures meant to protect you from potentially damaging PowerShell scripts. What’s worse is that this setting will survive a reboot of the server. That’s right, the security stays off until you tell it to come back on!!!

It will even survive an uninstall and reinstall of PowerShell.

I’m just like you. I usually would not have a problem turning the Execution Policy off, running a known, trusted script I downloaded from the web, and then turning the Execution Policy back on. But someday I am going to get a phone call, lunch invite, or help desk ticket that is going to help me forget to turn the Execution Policy back on. When that happens, I will not have any security in place – Not good.

So, what’s a good SharePoint admin to do? As usual, we have to read the manual, or in this case, the help file. To see help about Execution Policies, type in help about_Execution_Policies in your PowerShell window.

SNAGHTML1e1bacf[9]

Lots of reading in that one – pages and pages of information. In fact, you may be surprised how many different settings can be affected by one tiny PowerShell command. But what we care about (for now) is the Execution Policies – there are six total, but really only need to know about four. We already know about “Restricted” and “Unrestricted”, but there are two new ones:

  • AllSigned – Will run all scripts that are signed by a trusted publisher (either home-grown or from the Internet)
  • RemoteSigned – Will run all scripts that are signed by a trusted publisher AND will run any script that is written on the local computer

In my case, I did not want to set up the infrastructure necessary to sign my PowerShell script. So I chose to look at the Remote Signed option. And I wondered how could take a script that I had downloaded and use it as a “local” script?

Well, obviously, the first order of business is to look at the contents of the script to make sure that there is nothing malicious inside it. So far, so good.

Something in Windows itself knows that we downloaded this script; that something is the Alternate Data Stream (ADS). Alternate Data Stream (ADS) information is added by NTFS when a file is downloaded from the internet. To see the Zone.Identifier information for a downloaded script, open a Command Prompt, change to the directory where your script is stored and type in DIR/R.

SNAGHTML1edd986

Both the file itself and another version of the listing (with :Zone.Identifier:$DATA appended to the end of it) appear in the file system. The one with the zone.identifier suffix is the Alternate Data Stream. To review the contents of this file, we simply open it up in Notepad by typing

notepad MyNewDownloadedScript.ps1:zoneidentifier

SNAGHTML1f3296a

All this file does is state the origin of the file by ZoneId, per this MSDN PowerShell article – http://blogs.msdn.com/b/powershell/archive/2007/03/07/how-does-the-remotesigned-execution-policy-work.aspx

This article states that items with a ZoneId greater than or equal to 3 are considered remote.

Decision Time – At this point, you can either:

  • Remove the Zone.Identifier information from this file, or
  • Change the ZoneId value to 2 to indicate that it is “Trusted”

Either of these choices would assume that you have actually reviewed the PowerShell script and deemed it to be safe.

Removing the Zone.Identifier

To remove the Zone.Identifier, you can download and use the streams utility by Mark Russinovich from http://technet.microsoft.com/en-us/sysinternals/bb897440.aspx, or you can simply remove the Zone.Identifier using the command line:

echo.>MyNewDownloadedScript.ps1:Zone.Identifier

Changing the Zone.Identifier

I much prefer this method because (1) the Zone.Identifier tells me that I most likely did download and review the file at some point, and (2) it’s fairly easy to change ZoneId value from a “3” to a “2”. To change the Zone.Identifier, type:

notepad MyNewDownloadedScript.ps1:ZoneIdentifier

Change the ZoneId value to 2, and save the file.

SNAGHTML20ceb23

Don’t miss this part!

You really should not to run your file with the Execution Policy set to Unrestricted. Open up PowerShell (don’t forget to run as Administrator) and set your Execution Policy to RemoteSigned by typing:

Set-ExecutionPolicy RemoteSigned

and choosing [Y] Yes at the prompt

SNAGHTML214b036

You now have a system that can accept either signed PowerShell scripts –or– locally generated/modified PowerShell scripts. If you ever do convert your entire environment to using fully signed scripts, all you need to do is revisit these servers and change the Execution Policy to “Signed”. In addition, all Execution Policy settings we have made are addressable by Group Policy in your environment.

What Version of PowerShell am I using?

OK, this seems like like a basic question, but even without SharePoint or the PowerShell IDE (Integrated Development Environment) loaded, there are two distinct versions of PowerShell on any given system. Both versions are listed under All Programs –> Accessories –> Windows PowerShell, and as you might imagine, there are 32-bit (x86) and 64-bit (x64) variants:

  • Windows PowerShell (x86)
  • Windows PowerShell

The reason I bolded that last one is because this is most likely the only one we will use when it comes to SharePoint administration.

But hey, hold on a moment before you start PowerShell. Most often, you will be interacting with the system (assuming you are on a server) in an administrative role. This role is necessary to execute some PowerShell scripts you will encounter.

From All Programs –> Accessories –> Windows PowerShell, Right-Click Windows PowerShell and select Run as administrator.

image

If you have UAC (User Account Control) enabled, you will receive a prompt, indicating that you are intending to start PowerShell as an Administrator. Select “Yes” to continue.

PowerShell should now start in the proper user context: Administrator; this is verified by the Title line of the PowerShell window:

SNAGHTML152233f

Interestingly enough, the image above also indicates that the 64-bit (x64) version of PowerShell is currently running; it does so simply by not showing the (x86) by PowerShell in the title. Below is what the same screen would look like in (x86) mode.

SNAGHTML1581683

So now, the only question is, what version of PowerShell am I running, 1.0 or 2.0? The way to tell this is simply ask PowerShell itself by typing $host and pressing <Enter>.

SNAGHTML15c8d86

If you have PowerShell 1.0 installed (maybe you are running on Windows Server 2008 instead of Windows Server 2008 R2), uninstall it and go get PowerShell 2.0 (as part of the Windows Management Framework) from Microsoft at http://support.microsoft.com/kb/968929.

By the way, if you are installing the prerequisite files for SharePoint 2010, it will download PowerShell 2.0 as part of these files. But you will miss your chance to make changes before SharePoint is ever installed onto your system.

In for a Penny, In for a PowerShell Script

Lately I have seen several good blog posts about setting up SharePoint 2010 using PowerShell. I have to admit, coming from a DOS/Scripting background at some point in my past, the notion of scripting an installation thoroughly captivates me.

As I was working through my own virtual SharePoint farm installation, two thoughts occurred to me:

  • Most installation instructions I have seen are particularly focused on a Single Server SharePoint installation.
  • If I was going to configure SharePoint itself via scripts, why not configure as many other server settings as possible this way?

So, there will be several posts on this over the next few days addressing these details. I have spent quite a bit of time trying to configure all the server minutia via PowerShell to accompany my installation – and have the dents and scratches to prove it. I am sure that several of these PowerShell configuration tips exist scattered across the web, but I will try and gather as many as I can into one place, adding information I find along the way.

Stay Tuned!

P.S. Bring a bottle of headache medicine – you might need it, if you have had as many questions as I’ve had.