A quick and easy way to automate something is to schedule a PowerShell script using Windows Task Scheduler. However, sometimes you need to connect to remote resources using a username and password. This post will cover some options on how to schedule a PowerShell script with encrypted credentials.
Latest posts by Jeff Brown (see all)

The examples I'm going to focus on primarily relate to scheduling PowerShell scripts for Exchange, Skype for Business, and Office 365 services. Let's start with on-premises Exchange and Skype for Business. I often schedule scripts for creating new mailboxes or user accounts, or for gathering statistics for a dashboard. Connecting to the Exchange or Skype for Business servers from a remote system requires creating a remote PowerShell session, or PSSession. This is done by creating a credential object and using it when creating the PSSession. Here is an example for connecting to on-premises Exchange Server:

$UserCredential = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://<FQDNExchangeServer>/PowerShell/ -Authentication Kerberos -Credential $UserCredential
Import-PSSession $Session

The Get-Credential command will open a dialog box for inputting a username and password. This is great for an interactive session, but the point is to automate the task so you don't need to worry about inputting credentials. Instead of prompting for credentials, you can store them in the script to create the credential object for the session. For example:

$Username = "domain\username"
$Password = "Passw0rd123!" | ConvertTo-SecureString -AsPlainText -Force
$UserCredential = New-Object System.Management.Automation.PSCredential -ArgumentList $Username,$Password

Now you can use the $UserCredential variable to create the PSSession in the first example. However, note that is not secure, and I do not recommend this as an option. This should only be used for testing or troubleshooting and not in a production script.

A better option would be to use the built-in security options to run the task as a different user account. The security options in the Create Task wizard allow for selecting another account in order to run the PowerShell script as that user account.

Task with alternate user account

Task with alternate user account

When you go to save the task, the wizard will prompt for the alternate user account's password, like this:

Task Scheduler password prompt

Task Scheduler password prompt

When creating the PSSession in the script, instead of using Kerberos as the Authentication Type and a credential object, use NegotiateWithImplicitCredential, like this:

$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://<FQDNExchangeServer>/PowerShell/ -Authentication NegotiateWithImplicitCredential

This authentication type will use the credentials of the current logged-on user account for the PowerShell window. For the scheduled task, this account is our ScheduledTaskUser as the task is being run as this service account. The advantages here are that no passwords are being stored in the script and you don't have to create a credential object. However, if this service account's password is changed, you must go into each scheduled task and re-save the password. This could be a chore if you have multiple servers where scripts are stored or if the password must change frequently.

Using the built-in security options when creating a task is useful in most scenarios; however, you will run into an issue using this with Office 365. When creating a PSSession for Exchange Online, you must use a credential object and use Basic for the Authentication Type. This means you cannot use the account that is running the PowerShell window in the scheduled task.

To solve this issue, we have a third option of storing encrypted credentials to a file on the computer. The PowerShell script uses the encrypted password from the file to create a credential object. In order to create the encrypted file, first create and store a credential object on the computer where the task is scheduled using the Get-Credential command:

Create credential object

Create credential object

Next, convert the password stored in the credential object to an encrypted text file using the ConvertFrom-SecureString command:

$UserCredential.Password | ConvertFrom-SecureString | Out-File C:\ps\ScheduledTaskUser.txt

The contents of the text file will not contain the password in plain text but should look something like this:

Encrypted password file

Encrypted password file

To use the password, you will get the contents of this file and use ConvertTo-SecureString to store the password in a variable. You then use it to create a credential object to use when creating the PSSession. An example using this technique looks like this:

$Username = "domain\username"
$SecurePassword = Get-Content C:\ps\ScheduledTaskUser.txt | ConvertTo-SecureString
$UserCredential = New-Object System.Management.Automation.PSCredential -ArgumentList $Username,$SecurePassword
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection
Import-PSSession $Session

You might be thinking that anyone will be able to use this encrypted file, but this is not the case. What makes this method a little more secure is that the encryption uses the Windows Data Protection API; only the person who encrypts the password can decrypt it again and only on the computer it was encrypted on. Even if someone had the credentials of the person who encrypted the file, they would not be able to decrypt it if they copied the file to another computer.

When creating the password file, I suggest starting PowerShell as the service account that will be used in the script in order to create the encrypted password file. Use the same service account in the security options when creating the scheduled task as illustrated earlier.

Subscribe to 4sysops newsletter!

The PowerShell window inside the scheduled task will run as the service account and have permissions to get the password from the encrypted file as it was the one to encrypt it in the first place. This way if anyone gets access to the file, they will not be able to decrypt it unless they have the service account's credentials. This method still requires that the service account's password is kept in a secure place, access to which is limited to a few people.

avataravatar
7 Comments
  1. Paul Abke 6 years ago

    I recall a post by The Scripting Guy that used this command to securely store the credential:

    Get-Credential <domain\usersname> | Export-Clixml c:\data\PowerShell\Secure_credentials.xml

    I then use this function to connect to my Exchange server and recall the script was similar when I used Office365.

    function Connect-Exchange
    {
    $UserCredential = Import-Clixml c:\data\powershell\Secure_credentials.xml

    $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://srvexchange.<domain>/PowerShell/ -Authentication Kerberos -Credential $UserCredential

    Import-PSSession $Session
    }

    Can you explain the difference between ConvertFrom-SecureString  and Export-Clixml ?

    Can you also explain the risks in entering (and storing) the password for a service account in Task Scheduler?  How is that password secured?

    Thank you.

    • Author
      Jeff Brown (Rank 2) 6 years ago

      Hi Paul, apologies for the late reply. I believe you might be referencing this article (https://blogs.technet.microsoft.com/heyscriptingguy/2014/03/25/use-powershell-to-explore-office-365-installation). From what I can tell in the article, Export-CliXml uses ConvertFrom-SecureString, so both commands get to the same result. Just depends on if you want to store it as a text file or in XML code. It looks like XML stores the whole object with both username and password while my method just stores the password. You would still need to provide the username, like I did using a variable.

      As for storing the password for a service account in Task Scheduler, the password is stored in the Windows Credential Manager. It is encrypted and should be pretty secure.

  2. Paul Abke 6 years ago

    Thanks Jeff.

  3. Alvaro Torres Tatis 6 years ago

    You can use Cerdential Manager module to store a user/password in Windows Credential Manager. It’s easy, fast and secure. Check this out: https://www.powershellgallery.com/packages/CredentialManager/1.0

    Great post!!!

  4. Jeremy 5 years ago

    The tidbit about ConvertTo/From-SecureString using Windows Data Protection, rendering the file only of use to the original owner, is very great to hear/know.  It changes everything!

    Thanks for the great article.

    • d 5 years ago

      Original account as well as the original computer 😉

  5. Rune 1 year ago

    Will the “New-PSSession -Authentication NegotiateWithImplicitCredential”-method be possible to use with the Connect-AIPService?

Leave a reply

Your email address will not be published. Required fields are marked *

*

© 4sysops 2006 - 2023

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account