Don't spill the beans - keep your secrets secure

In the previous post Sleep Worry-Free: The best tips for Local Secrets Management I shared the best tips for managing local secrets. In this post I will take Secrets Management to the next level by showing you how to create manage and use secrets securely by setting up a local secure store using PowerShell SecretManagement and PowerShell SecretStore modules.

Modules explained

Since this approach to Secrets Management depends on the two just mentioned modules the purpose of each of the modules is explained next.

PowerShell SecretManagement module

Important to note here is that this module does not store any secrets it is a uniform interaction layer to to access and manage secrets stored different kind of extension vaults. This module supports managing the following secret data types:

  • byte[]
  • string
  • SecureString
  • PSCredential
  • Hashtable

PowerShell SecretStore

The SecretStore module is an extension vault for the just mentioned PowerShell SecretManagement module. This is the module that stores secrets and it does so locally within the current user context. It uses the .NET crypto APIs to encrypt the file which is used ot store the secrets. Since this modules works in all by PowerShell supported Operating systems it runs on Windows, Linux and macOS.
By default the store requires a password for unlocking it, this is done to provide the strongest. As all other extension vaults this vault is registered to the current logged in user context, and is available only to the user in question. The extension vault registry file is stored in the user account protected directory.

For Windows platforms the location is:

  • %LOCALAPPDATA%\Microsoft\PowerShell\secretmanagement

For non-Windows platforms the location:

  • $HOME/.secretmanagement

Set-up your Secure Store

The first step is to make sure that the two modules are installed and loaded, namely;

  • Microsoft.PowerShell.SecretStore
  • Microsoft.PowerShell.SecretManagement

For this I used a simple ForEach loop which checks if the modules are already installed both are loaded if not both are installed and then loaded. The snippet I use is as follows:

Register a new vault

To register a new vault a SecureString password is required. This password is exported into an XML file and encrypted by Windows Data Protection (DPAPI) using the Export-Clixml command. Next a new vault is created using the Register-SecretVault command. To complete the registration of the vault the just created password is used to secure it and the following configurations values are also set.

  • Authentication <- Setting this parameter to Password Ensures a password is required to secure the concerning vault
  • PasswordTimeout<- The amount of time the vault stays unlocked after using the password, the default is 15 minutes however I like to set it to 3600 seconds (1 hour)
  • Interaction <- Specifies whether the SecretStore should prompt a user when they access it. I used none to be able to run the whole thing via an automation script.
  • Password <- the actual password encrypted using Export-Clixml. Needed when previous parameter is set to none.
  • Confirm <- Prompts you for confirmation before running the cmdlet. I set it to $false since I intend to execute it via an automation script.

I combine the above settings into a function based on the following snippet:

Use the new vault

The first step to start using the newly created vault is to make sure it’s unlocked. For this the password used during the creation must be provided using the Unlock-SecretStore command. With the vault unlocked the Set-Secret and Get-Secret can be used to store and retrieve secrets.

An interesting mention is that it is possible set an expiration date using the -Metadata parameter. Naturally the extension vault itself must support it this as not all do.

Before starting a debug session I simply use the Set-Secret command to store te required secrets in the vault and use them in my throw away / one time use PowerShell script Jevs-Playground.ps1. For details on this script please check out my previous post Sleep Worry-Free: The best tips for Local Secrets Management .

Check-out the next examples as these contain the snippets I used at one time or another for development and debugging.

Unlock the vault

Simply use Unlock-SecretStore command, but make sure to provide path to your secure store password xml file.

Add secrets to the vault

Use the Set-Secret command to add secrets to the vault.

Connect-AzAccount with vault secrets

Get the app id, app secret and the tenant id secrets and pass these into the Connect-AzAccount. The app secret does not need to be read as plain text and should be passed as System.Security.SecureString directly.

Azure DevOps API with vault secrets

Get the PAT token from the vault, craft a authentication header using the token and simply execute Invoke-RestMethod.

Wrapping up

I hope you enjoyed this post and now have a better understanding of the possibilities to manage secrets locally during debugging. If you are interested in the reference material used to make this post, please visit the following links. As always, a big thanks for reading this post. If you liked it, don’t be shy and have a look at my other posts .