PowerShell v3 in a Year Day 9 about Execution Policies

Execution policies, in many ways, are a throw away concept in PowerShell. Once you understand it, for most people, thats probably the last time you will need to think about it until you log onto a new machine, reinstall Windows, or something along those lines. Yet, it is also one of the first things you will run into with PowerShell. After you run a few commands, chances are you will want to try and run a "script" by saving something to file. Thats when it rears its ugly head. Execution policies, as noted in the help, "let you determine the conditions under which Windows PowerShell loads configuration files and runs scripts."  By default, execution policies are locked down. So, unless you know to modify the setting, one of the first things you will encounter in PowerShell, when you try to run a script, is an error. A simple "Hello world" exercise quickly turns into "What the frack!?"  This is a little unfortunate because lots of folks who take a chance on PowerShell by the themselves get greeted with a simple, but, frustrating hiccup. Hardly a great "introduction" to this great new shell all the koolaid drinkers rave about.

When working with execution policies it is good to know how they really work. You can set them at three levels:
  1. the local computer: The execution policy affects all users on the current computer. It is stored in the HKEY_LOCAL_MACHINE registry subkey.
  2. the current user: The execution policy affects only the current user. It is stored in the HKEY_CURRENT_USER registry subkey.
  3. the current session: The execution policy affects only the current session (the current Windows PowerShell process). The execution policy is stored in the $env:PSExecutionPolicyPreference environment variable, not in the registry, and it is deleted when the session is closed. You cannot change the policy by editing the variable value.
Before getting into the first two, I want to note that the current session setting lives in memory only. So, when a session closes, the session-specific ExecutionPolicy level disappears with it.

If those look familiar to an experienced Windows user they should, because, they work against the registry. When you call Set-ExecutionPolicy (or Get-ExecutionPolicy) you are really reading this registry key:
HKLMSOFTWAREMICROSOFTPowerShell1ShellIdsMicrosoft.PowerShellExecutionPolicy
When you change it, there is an enumeration of type Microsoft.PowerShell.ExecutionPolicy that determines what the settings are. Below is a quick list for reference. You can enter either a string or an integer to update the values when you call Set-ExecutionPolicy using these:
  • 0: Unrestricted
  • 1: RemoteSigned
  • 2: All signed
  • 3: Restricted
  • 4: Bypass
  • 5: Restricted
I am not sure why Restricted is in there twice, but, it is. If you try to do an integer of 6 you get this error,
Set-ExecutionPolicy : Cannot bind parameterExecutionPolicy.Cannot convertvalue "6"to type "Microsoft.PowerShell.ExecutionPolicy"due to enumeration valuesthat arenot valid.Specify oneof thefollowing enumeration valuesand tryagain. Thepossible enumerationvalues are"Unrestricted, RemoteSigned, AllSigned, Restricted, Default, Bypass, Undefined".
At line:1char:21
+ Set-ExecutionPolicy6
+                     ~
    + CategoryInfo          : InvalidArgument:(:) [Set-ExecutionPolicy], ParameterBindingException
    + FullyQualifiedErrorId :CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.SetExecutionPolicyCommand
This is a pretty informative error, as it tells you all about the enumeration and what values are legit. As one of the MSFT guys pointed out, the fastest way to get information about anything enum related, is to put something you know will fail. PowerShell will come back with informative details like this and tell you what you need to know without a lot of research.

Below is a breakdown of the actual execution policies as outlined in the v3 help:
  • Restricted
    • Default execution policy.
    • Permits individual commands, but will not run scripts.
    • Prevents running of all script files, including formatting and configuration files (.ps1xml), module script files (.psm1), and Windows PowerShell profiles (.ps1).
  • AllSigned
    • Scripts can run. 
    • Requires that all scripts and configuration files be signed by a trusted publisher, including scripts that you write on the local computer.
    • Prompts you before running scripts from publishers that you have not yet classified as trusted or untrusted.
    • Risks running signed, but malicious, scripts.
  • RemoteSigned
    • Scripts can run.
    • Requires a digital signature from a trusted publisher on scripts and configuration files that are downloaded from the Internet (including e-mail and instant messaging programs).
    • Does not require digital signatures on scripts that you have written on the local computer (not downloaded from the Internet).
    • Runs scripts that are downloaded from the Internet and not signed, if the scripts are unblocked, such as by using the Unblock-File cmdlet.
    • Risks running unsigned scripts from sources other than the Internet and signed, but malicious, scripts.
  • Unrestricted
    • Unsigned scripts can run. (This risks running malicious scripts.)
    • Warns the user before running srcipts and configuration files that are downloaded from the Internet.
  • Bypass
    • Nothing is blocked and there are no warnings or prompts.
    • This execution policy is designed for configurations in which a Windows PowerShell script is built in to a a larger application or for configurations in which Windows PowerShell is the foundation for a program that has its own security model.
  • Undefined
    • There is no execution policy set in the current scope.
    • If the execution policy in all scopes is Undefined, the effective execution policy is Restricted, which is the default execution policy.
NOTE: One particular gotcha they warn users of focuses on UNC paths. If your script has UNC paths it might pose problems, but, there is no way to know for sure.

One of the things that you need to pay close attention to is the concept of scope. There are several scopes for which you can set/get ExecutionPolicy. The trick is to use the -Scope operator. As outlined below, there are 5 key scopes to pay attention to. As with the ExecutionPolicy enum, you can set/get values by integers as well. In this case, you are dealing with the Microsoft.PowerShell.ExecutionPolicyScope object.
  • MachinePolicy: 4
  • UserPolicy: 3
  • Process: 0
  • CurrentUser: 1
  • LocalMachine: 2
The fact of the matter is that you can have several different settings for an environment. There is no interdependence between each of these. I tried to track down where the settings lived, but, procmon wasnt divulging any secrets on this one. When you do change your execution policy for local computer (default) or current user it writes down to the registry. Also, from Vista forward, UAC requires you to run the shell with elevated privileges in order to make the change.

To set an execution policy you can take two approaches:
  1. Set-ExecutionPolicy Undefined
  2. Set-ExecutionPolicy Undefined -Scope Process
The first option affects the default scope whereas the second one is more precise and focuses on the Process scope.

There is a group policy approach that you can use to manage execution policies as well. If you use the group policy approach these settings override all manual settings. The setting you modify via the GPO is "Turn on Script Execution" and is as follows:
  • If you disable "Turn on Script Execution", scripts do not run. This is equivalent to the "Restricted" execution policy.
  • If you enable "Turn on Script Execution", you can select an execution policy. The Group Policy settings are equivalent to the following execution policy settings (Group policy and execution policy respecitvely):
    • Allow all scripts: Unrestricted
    • Allow local scripts: RemoteSigned and remote signed scripts.
    • Allow only signed: AllSigned scripts.
  • If "Turn on Script Execution" is not configured, it has no effect. The execution policy set in Windows PowerShell is effective.
The GPO creates physical files in the following locations:
  • .adm: Administrative TemplatesWindows ComponentsWindows PowerShell
  • .admx: Administrative TemplatesClassic Administrative TemplatesWindows ComponentsWindows PowerShell
Entries set in the Computer configuration node take precedence over the user configuration node.

For reference, here is the order of precedence to use when trying to evaluate execution policies:
  • Group Policy: Computer Configuration
  • Group Policy: User Configuration
  • Execution Policy: Process (or PowerShell.exe -ExecutionPolicy)
  • Execution Policy: CurrentUser
  • Execution Policy: LocalMachine
Special attention must be paid when dealing with signed scripts. If you use RemoteSigned for your execution policy PowerShell will not run unsigned scripts downloaded from the Internet. This includes emails. PowerShell v3 gives you the ability to use the -Stream parameter to detect files that are blocked because they were downloaded from the Internet. To work with these, use the Unblock-File cmdlet, also new in v3, to remove the limitation from these files.

Related Posts by Categories

0 comments:

Post a Comment