Powershell: How to encrypt and store credentials securely for use with automation scripts.

IT

Powershell: How to encrypt and store credentials securely for use with automation scripts.

I recently worked on a quick and dirty Powershell script to send me email notifications when content on a web page changed. To send the email, I also went for the quick and dirty method and just used SMTP with my Gmail account. After I finished this dirty masterpiece, I couldn’t handle seeing my password sitting in plain text, and I knew something had to be done. Here is how I solved this dilemma:

Step 1: Create your encrypted password file.

First you need a standalone .ps1 script to generate your password file. The following code will achieve this:

<# Set and encrypt credentials to file using default method #>

$credential = Get-Credential
$credential.Password | ConvertFrom-SecureString | Set-Content c:scriptsencrypted_password1.txt

Run this script in Powershell, remember to set the execution policy appropriately, and Windows will prompt you for a username and password. Username isn’t important since we are just storing the password, but go ahead and enter it anyway. This will create a text file in the specified location with a hash of your password. They “key” to this…Wah wah…is your Windows account. If you don’t specify a Key or SecureKey parameter, the default is to use the Windows Data Protection API. Basically, that means using your Windows profile as the key. Note that it’s also specific to the machine where you encrypted it. So, you can’t decrypt with the same account from another machine. For more information check out this long boring article: http://msdn.microsoft.com/en-us/library/ms995355.aspx. Why wouldn’t I specify a key? Laziness mostly, and I like methods that integrate with Windows authentication. More importantly, I didn’t see an obvious way of making the the key secure and accessible. In a production environment, I would recommend a service account used solely for creating and running the encryption and automation scripts.

Step 2: Use the encrypted password file in your automation scripts.

Here is a simplified snippet of code using the encrypted password:

<# 
    Set some variables
    ...
#>
$emailusername = "myemail"
$encrypted = Get-Content c:scriptsencrypted_password.txt | ConvertTo-SecureString
$credential = New-Object System.Management.Automation.PsCredential($emailusername, $encrypted)

if($something = $somethingElse)
{
    <#
        Do some stuff
        ...
    #>

    $EmailFrom = "myemail@gmail.com"
    $EmailTo = "myemail+alerts@gmail.com"
    $Subject = "I did some stuff!" 
    $Body = "This is a notification from Powershell." 
    $SMTPServer = "smtp.gmail.com" 
    $SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587) 
    $SMTPClient.EnableSsl = $true 
    $SMTPClient.Credentials = $credential;
    $SMTPClient.Send($EmailFrom, $EmailTo, $Subject, $Body)
}

Note the secret sauce that imports the password on lines 6 and 7. We don’t specify any parameters with the ConvertTo-SecureString method because we want it to use the Windows account running the script for decryption, exactly like we did with the ConvertFrom-SecureString for the encryption. After that we can use that credential object willy nilly, example on line 23.

I hope this has been helpful in showing that with a small amount of effort you can get away from storing passwords in plain text in your Powershell scripts.

More About the Author

Tim Rhymer

Systems Engineer
How to Use Kaseya to Detect Meltdown and Spectre Vulnerable Machines To help detect client Windows machines that are vulnerable to Meltdown and Spectre at the OS and Hardware level, we built a Kaseya ...
Use This Script to Push or Pull Replication for a Windows Domain Controller (2003, 2008, 2012) If you would like to avoid using the AD Sites and Services GUI to force replication across your domain controllers, consider the script ...

See more from this author →

Subscribe to our newsletter

  • This field is for validation purposes and should be left unchanged.