Tuesday, July 31, 2012

HowTo: Run (Signed) Powershell Scripts as Scheduled Tasks with Minimal Rights

This is meant to be a straightforward howto: on the topic. While this sort of thing is quite common, I often times see people missing a few critical details that end up resulting in alot of unnecessary troubleshooting time. I will also cover steps needed to run signed scripts.

Assumes:
  • Powershell 2.0
  • Windows Server 2008 or R2 (will work on others but steps will be slightly different) 
  • If signing script you know how to get a cert and basics about managing certs

Creating a signed script (optional) 

  1. Ensure you have a valid code signing cert installed in your user store and that you're logged on as that user. This is easiest if your organization has PKI with a code signing template enabled. This user should NOT be the service account user, but rather the author of the script. (you I'm guessing)
  2. After finishing your script, execute: 
    1. $cert=@(Get-Childitem cert:\CurrentUser\My -codesigning)[0]  (assuming you have only one code signing cert) 
    2. Set-AuthenticodeSignature .\myscriptname.ps1 $cert
Note: whenever you modify the script you'll need to re-sign it. 

Stage Server/Account 

  1. Create the service account. To be controlled correctly this should be a domain account with no additional privileges above that of a standard user. For additional security, set it so the user can only log on to the computer you intend to run the script on. Use a  good password.
  2. Give that user "Log on as a batch job" rights on the target server using the local security policy or group policy if applicable.
  3. Create the directory the script will be stored in. Give the service account READ access to that directory.
  4. Copy the script to the target directory
  5. Variable step if signing or not:
    1. If Signing: 
      1. If signing execute as admin in powershell on the server: Set-ExecutionPolicy AllSigned
      2. Log onto the server with the service account and run the script manually. This will prompt powershell to ask if you want to trust the publisher based on the cert. Select that you will always trust this publisher. (which is you!) If you can't log on locally or on a VM console you'll need to temporarily grant the service acct RDP access. 
    2. If not signing, execute as admin: Set-ExecutionPolicy Unrestricted

 Setup Scheduled Task

  1. Open Task Scheduler and navigate to the folder you would like the task to reside in. 
  2. In the right plane, right click->Create New Task...
  3. Give the Task a Name and Description. Don't skip the description, it'll save time having it there in the future. 
  4. Select "Run whether user is logged on or not" and ensure the "Do not store password" box is NOT checked. Select "Run with highest privileges" ONLY if your script requires it. (Powershell itself does not) 
  5. Click "Change User or Group" and enter the service account you created earlier. 
  6. Select the "Triggers" tab and set triggers as appropriate
  7. Select the "Actions" tab and click "New..."
  8. Action: "Start a program"; Program/script: "powershell.exe" (full path shouldn't be necessary) ; Add arguments: "-NoLogo -NonInteractive -WindowStyle Hidden D:\path\to\your\script.ps1"
  9. Change settings on the "Settings" tab if desired
  10. Click "OK" and enter the password for the Service Account
That's it! If everything was done correctly it should run without problem. Depending on what the script does you may need to grant additional rights to filesystems, etc, but that's up to you to figure out since you wrote the script. :) I hope this post saved you some time getting your script up and running.