Modules usually have two types of data that would be great to store and manage in a good way: module and user settings and secrets. With this module,
we aim to store this data using a the concept of Contexts
that are stored locally on the machine where the module is running. It lets module
developers separate user and module data from the module code, so that modules can be created in a way where users can resume from where they left off
without having to reconfigure the module or log in to services that support refreshing sessions with data you can store, i.e., refresh tokens.
The consept of Contexts
is built on top of the functionality provided by the Microsoft.PowerShell.SecretManagement
and
Microsoft.PowerShell.SecretStore
modules. The Context
module manages a set of secrets
that is stored in a SecretVault
instance. A context in
this case is a collection of secrets and data that is combined to represent a context for a module or a user.
A Context
is collection of a name, data and secrets. A context must always have a name and the type of data you can store is:
- Byte[]
- String
- SecureString
- PSCredential
- Hashtable
The context is stored as hashtable and could look something like this:
@{
Name = "GitHub" # Required: Used to store the context in the vault.
AccessToken = "123456",
AccessTokenExpirationDate = '2021-12-31T23:59:59'
RefreshToken = '654321'
RefreshTokenExpirationDate = '2021-12-31T23:59:59'
APIVersion = 'v3'
APIHost = 'https://api.github.com'
ClientId = '123456'
Scope = 'repo, user'
}
This module relies on Microsoft.PowerShell.SecretManagement and Microsoft.PowerShell.SecretStore. The module automatically installs these modules if they are not already installed.
Install the module from the PowerShell Gallery by running the following command:
Install-PSResource -Name Context -TrustRepository -Repository PSGallery
Import-Module -Name Context
As mentioned earlier, there are two types of data that can be stored using the Context
module: module and user settings and secrets.
Lets have a look at how to use the module to store these types of data in abit more detail.
To store module data, the module developer can create a context that defines a "namespace" for the module. This context can store settings and secrets for the module. A module developer can also create additional contexts for additional settings that share the same lifecycle, like settings associated with a module extension.
Let's say we have a module called GitHub
that needs to store some settings and secrets. The module developer could initialize a context called
GitHub
as part of the loading section in the module code. All module configuration could be stored in this context by using the functionality in
this module. The context for the module is stored in the SecretVault
as a secret with the name Context:GitHub
.
To store user data, the module developer can create a new context that defines a "namespace" for the user configuration. So let's say a developer has
implemented this for the GitHub
module, a user would log in using their details. The module would call upon Context
functionality to create a new
context under the GitHub
context.
Imagine a user called BobMarley
logs in to the GitHub
module. The following would exist in the context:
Context:GitHub
containing module configuration, like default user, host, and client ID to use if not otherwise specified.Context:GitHub.BobMarley
containing user configuration, details about the user, secrets and default values for API calls etc.
Let's say the person also has another account on GitHub
called RastaBlasta
. After logging on with the second account, the following context would
also exist in the context:
Context:GitHub.RastaBlasta
containing user configuration, details about the user, secrets and default values for API calls etc.
With this the module developer could allow users to set default context, and store a key of the name of that context in the module context. This way the module could automatically log in the user to the correct account when the module is loaded. The user could also switch between accounts by changing the default context.
To set up a new module to use the Context
module, the following steps should be taken:
- Create a new context for the module ->
Set-Context -Name 'GitHub'
during the module initialization.
src\variable\private\Config.ps1
$script:Config = @{
Name = 'GitHub'
}
src\loader.ps1
Write-Verbose "Initialized secret vault [$($script:Config.Context.VaultName)] of type [$($script:Config.Context.VaultType)]"
### This is the context config for this module
$contextParams = @{
Name = $script:Config.Name
}
try {
Set-Context @contextParams
} catch {
Write-Error $_
throw 'Failed to initialize secret vault'
}
- Add some module configuration ->
Set-ContextSetting -Context 'GitHub' -Name 'ClientId' -Value '123456'
- Get the module configuration ->
Get-ContextSetting -Context 'GitHub' -Name 'ClientId'
->123456
Get-ContextSettign -Context 'GitHub'
-> Returns all module configuration for theGitHub
context.
- Remove the module configuration ->
Remove-ContextSetting -Context 'GitHub' -Name 'ClientId'
To set up a new context for a user, the following steps should be taken:
-
Create a set of integration functions that you can expose to the user and that uses the
Context
module to store user data. Its highly recommended to do this so that you as a module developer can create the structure you want for the context, while also giving the user the expected function names to interact with the module.Set-<ModuleName>Context
that usesSet-Context
.Get-<ModuleName>Context
that usesGet-Context
.Remove-<ModuleName>Context
that usesRemove-Context
Set-<ModuleName>ContextSetting
that usesSet-ContextSetting
Get-<ModuleName>ContextSetting
that usesGet-ContextSetting
Remove-<ModuleName>ContextSetting
that usesRemove-ContextSetting
-
Create a new context for the user ->
Set-Context -Context 'GitHub.BobMarley'
-> ContextGitHub.BobMarley
is created. -
Add some user configuration ->
Set-ContextSetting -Context 'GitHub.BobMarley.AccessToken' -Name 'Secret' -Value '123456'
-> SecretGitHub.BobMarley.AccessToken
is created. -
Get the user configuration ->
Get-ContextSetting -Context 'GitHub.BobMarley.AccessToken' -Name 'Secret' -AsPlainText
->123456
-
Remove the user configuration ->
Remove-Context -Name 'GitHub.BobMarley.AccessToken'
-> SecretGitHub.BobMarley.AccessToken
is removed.
Coder or not, you can contribute to the project! We welcome all contributions.
If you don't code, you still sit on valuable information that can make this project even better. If you experience that the product does unexpected things, throws errors, or is missing functionality, you can help by submitting bugs and feature requests. Please see the issues tab on this project and submit a new issue that matches your needs.
If you do code, we'd love to have your contributions. Please read the Contribution guidelines for more information.
- SecretManagement | GitHub | Docs
- SecretStore | GitHub | Docs
- Overview of the SecretManagement and SecretStore modules | Microsoft Learn