When it comes to automation with PowerShell we come across scenarios where credentials are needed for the script to run and I’ve seen scripts being used by admins where the passwords are there in plain-text. It starts with..’this is only for testing‘,’oh!..that’s just a service account‘ and next thing you know, it is in production and the said service account has more previleged roles attached to it than when it was in testing.
I’ve done it too but I’ve realized that I can spend some time to understand and make it a practice on storing the passwords securely. I went over this issue briefly in a different post when earlier. In this post, I will go over the steps on how to use the Microsoft’s SecretManagement and Secret Store modules to manage passwords securely in a script and interactively.
And yes, there is a long list of 3rd party secret vaults that can be used to accomplish this like HashiCorp Vault, LastPass, KeePass, etc. I’ve started using Azure Key Vault which is great and doesn’t cost a lot. The Azure Key Vault is great for storing and sharing secrets in an organization and also to set a process around it. I will cover this in a future post.
Installing the modules
To start storing and managing passwords from a encrypted vault, we need to install the PowerShell SecretManagement and SecretStore modules. These modules require Windows PowerShell version 5.1 or PowerShell Core 6.x, 7.x
Microsoft.PowerShell.SecretManagement – Provides a convenient way to store and retrieve secrets
Microsoft.PowerShell.SecretStore – Provides local secure store extension vault for Microsoft.PowerShell.SecretManagement module
To install the modules,
- Open PowerShell as admin
- Set PowerShell’s execution policy to RemoteSigned
Set-ExecutionPolicy RemoteSigned
- Run the following command
- On confirmation prompt, press A to continue
Install-Module -Name Microsoft.PowerShell.SecretManagement, Microsoft.PowerShell.SecretStore
- To confirm successful installation,
Get-Module -ListAvailable Microsoft.PowerShell.SecretManagement, Microsoft.PowerShell.SecretStore
and to display all the available cmdlets in both modules,
Get-Command -Module Microsoft.PowerShell.SecretManagement, Microsoft.PowerShell.SecretStore | Sort-Object Source
Create a secret store vault
First, we need to create a local secret vault. I will name mine CredsDB
$vaultName = Read-Host "Enter a name for the vault"
$vaultDesc = Read-Host "Enter vault description"
Register-SecretVault -Name $vaultName -ModuleName Microsoft.PowerShell.SecretStore -Description $vaultDesc
To display the registered vault,
Get-SecretVault
To set a master password to the SecretStore vault
To create a master password to access the SecretStore,
Get-SecretStoreConfiguration
The following settings determine access to the password stores,
- Scope – The Scope is always CurrentUser. AllUsers Scope is not supported
- Authentication – Access vault using a master password
- PasswordTimeout – 900 seconds, duration of the session before we need to enter the master password
- Interaction – Prompt – to make changes
Note: If you forget the vault master password, you won’t be able to access stored data.
To change master password,
$oldPassword = Read-Host "Enter old password" -AsSecureString
$newPassword = Read-Host "Enter new password" -AsSecureString
Set-SecretStorePassword -NewPassword $newPassword -Password $oldPassword
Storing and updating secrets
Now that we have created a new secret vault, we are ready to start storing sensitive information into it. The secret store accepts the following data types as secrets,
- Byte[]
- Hashtable
- PSCredential
- SecureString
- String
To add a new username and password, PSCredential object to the store,
$credential = Get-Credential
Set-Secret -Name Cred1 -Secret $credential
If you missed to set the master password in the earlier step I described, you’ll be prompted to set the master password while running the Set-Secret cmdlet for the first time.
If you need to update the secret at a later point in time, use the same Set-Secret cmdlet to overwrite the existing secret
Retrieving secrets
To retrieve the entries in the vault, we can use the below cmdlet to unlock the vault first. Type the vault’s password and press enter,
Unlock-SecretStore
To display entries in the secret vault,
Get-SecretInfo
To retrieve a secret’s value shown as System.Security.SecureString,
$Secret = Read-Host "Enter name of the secret"
Get-Secret -Name $Secret
To view the password in plaintext,
$Secret = Read-Host "Enter name of the secret"
(Get-Secret -Name $Secret).GetNetworkCredential() | Select UserName, Password
Using secrets in PowerShell automation
We’ve registered, created a new vault and also created a new secret and also retrieved the stored secret in the above steps. The above retrieval process needs manual interaction and in automation we need to avoid that. I know what you are thinking, if there is a master password, we’ll need to type that in anyway to unlock the stored secret.
You might be tempted to disable the request of the master password request to access the secret by using the below cmdlet, but please don’t. This method might be good to do some quick testing but is not recommended in production environments.
Set-SecretStoreConfiguration -Authentication None
There are many options to unlocking the secret store without manually entering the master password while making sure it is not stored anywhere in plain text. One method is to save the master password in an encrypted xml file.
Use the below command to save master password in a CliXml file.
- The command will prompt for credentials
- Type any username
- Type the master password
- You can name the xml file to your preference
- It is recommended to store the xml file in a location where you can lock down the permissions
Get-Credential | Export-CliXml c:\scripts\vpd.xml
We can confirm the credential file exists and contains the encrypted master password. The XML file will not display the password in plain text as you can see in the screenshot.
Get-Content c:\scripts\vpd.xml
Now we can import the encrypted password from the xml file to a variable
$vpwd = (Import-CliXml c:\scripts\vpd.xml).Password
We can use this above variable to unlock the Secret Store,
Unlock-SecretStore -Password $vpwd
To retrieve the secret,
$Secret = Read-Host "Enter name of the secret"
(Get-Secret -Name $Secret).GetNetworkCredential() | Select Username,Password
With this in place, to keep things simple you can use the variable and Unlock-SecretStore in PowerShell automation scripts. We can use this to connect to Azure AD tenant or to O365.
Here is how I do it,
$vpwd = (Import-CliXml c:\scripts\vpd.xml).Password
Unlock-SecretStore -Password $vpwd
$credential = Get-Secret -Vault CredsDB -Name Cred1
Connect-AzureAD -Credential $credential
Connect-ExchangeOnline -credential $credential
Hope this post helped you in understanding how to store credentials securely with the SecretManagement and Secret Store modules.
Thank you for stopping by.✌