Skip to content

Commit

Permalink
🚀 [Feature]: Refactor to use metdata for variables (again...) (#30)
Browse files Browse the repository at this point in the history
## Description

- Refactor to use metdata for variables (again...)

## Type of change

<!-- Use the check-boxes [x] on the options that are relevant. -->

- [ ] 📖 [Docs]
- [ ] 🪲 [Fix]
- [ ] 🩹 [Patch]
- [ ] ⚠️ [Security fix]
- [x] 🚀 [Feature]
- [ ] 🌟 [Breaking change]

## Checklist

<!-- Use the check-boxes [x] on the options that are relevant. -->

- [x] I have performed a self-review of my own code
- [x] I have commented my code, particularly in hard-to-understand areas
  • Loading branch information
MariusStorhaug authored Nov 8, 2024
1 parent 14c82f2 commit d1cf656
Show file tree
Hide file tree
Showing 19 changed files with 438 additions and 352 deletions.
87 changes: 47 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,72 +1,79 @@
# Store

A PowerShell module that manages a store of secrets and variables.
This module is designed to be a simple way to store and retrieve secrets and variables in a PowerShell script or module.

The main purpose of the module is to provide a standard way to store and retrieve
module and user configuration for PowerShell modules. The module builds a very thin overlay of functions ontop of the
`Microsoft.PowerShell.SecretManagement` and `Microsoft.PowerShell.SecretStore` modules. As they do not have a good way to manage modifying specific
values in the metadata of a secret, this module provides a way to do that.

## Prerequisites

This module relies on [Microsoft.PowerShell.SecretManagement](https://github.com/powershell/SecretManagement) and
[Microsoft.PowerShell.SecretStore](https://github.com/PowerShell/SecretStore) by default. You can use other secret vault
providers by installing them and setting them as the provider when calling the function.
This module relies on [Microsoft.PowerShell.SecretManagement](https://GitHub.com/powershell/SecretManagement) and
[Microsoft.PowerShell.SecretStore](https://GitHub.com/PowerShell/SecretStore).

## Installation

Provide step-by-step instructions on how to install the module, including any InstallModule commands or manual installation steps.
Install the module from the PowerShell Gallery by running the following command:

```powershell
Install-Module -Name Store
Install-PSResource -Name Store -TrustRepository -Repository PSGallery
Import-Module -Name Store
```

## Usage

Here is a list of example that are typical use cases for the module.
This section should provide a good overview of the module's capabilities.
Modules usually have two types of data that would be great to store, module and user configuration. With this module we aim to store this data
separate 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.

### Initialize the store
### Module configuration

The following command creates a new store with the name 'MyStore'. This results in a `config.json` file being created in `$HOME\.mystore\`.
It also ensures there is a secret vault provider created called 'SecretStore' and sets it as the default provider for the store.
To store module configuration, the module developer can create a secret in the store that defines a "namespace" for the module configuration. All
other configurations done by the module will be stored with a name that is prefixed with the namespace. The secret metadata is where the configuration
is stored. The secret value itself it not used for the namespace secrets.

If a store already exists with the type 'Microsoft.PowerShell.SecretStore', it will be used as the default provider for the store.
Lets say we have a module called `GitHub` that needs to store configuration. The module developer would initialize a store called 'GitHub'. All module
configuration would be stored in this secret. All other configutations would be stored "in" the `GitHub` store, when in reality they are stored flat
in the SecretStore, but uses a hierarchy based naming convention to group the secrets together.

```powershell
Initialize-Store -Name 'MyStore'
```
### User configuration

### Add a variable to the store
To store user configuration, the module developer can create a secret in the store that defines a "namespace" for the user configuration within the
store they have defined. So lets say a developer has implemented this for the `GitHub` module, a user would log in using their details. The module
would call upon `Store` functionality to create a new context under the `GitHub` store.

The following command adds a variable to the store with the name 'MyVariable' and the value 'Something'.
Imagine a user called `BobMarley` logs in to the `GitHub` module. The following would exist in the store:

```powershell
Add-StoreConfig -Name 'MyVariable' -Value 'Something'
```
- `GitHub` containing module configuration, like default user, host and client ID to use if not otherwise specified.
- `GitHub.BobMarley` containing user configuration
- `GitHub.BobMarley.AccessToken` containing the access token for the user with the validity stored in the metadata
- `GitHub.BobMarley.RefreshToken` containing the refresh token for the user with the validity stored in the metadata

As the value is not a secure string, it will be stored in plain text in the store json file.
Lets say the person also has another account on GitHub called `RastaBlasta`. After logging on with the second account the store would also have:

### Add a secret to the store
- `GitHub.RastaBlasta` containing user configuration
- `GitHub.RastaBlasta.AccessToken` containing the access token for the user with the validity stored in the metadata
- `GitHub.RastaBlasta.RefreshToken` containing the refresh token for the user with the validity stored in the metadata

The following command adds a secret to the store with the name 'MySecret' and the value 'Something'. The secret is stored in the default provider.
### Setup for a new module

```powershell
Add-StoreConfig -Name 'MySecret' -Value ('Something' | ConvertTo-SecureString -AsPlainText -Force)
```
To setup a new module to use the `Store` module, the following steps should be taken:

As the value is a secure string, it will be stored securely in the secret vault.
1. Create a new store for the module -> `Set-Store -Name 'GitHub'`
2. Add some module configuration -> `Set-StoreConfig -Store 'GitHub' -Name 'ClientId' -Value '123456'`
3. Get the module configuration -> `Get-StoreConfig -Store 'GitHub' -Name 'ClientId'` -> `123456`
- Get-StoreData -Store 'GitHub' -> Returns all module configuration for the `GitHub` store.
4. Remove the module configuration -> `Remove-StoreConfig -Store 'GitHub' -Name 'ClientId'`

### Get a variable or secret from the store
### Setup for a new context

The following command gets the value of the variable 'MyVariable' from the store.
To setup a new context for a user, the following steps should be taken:

```powershell
Get-StoreConfig -Name 'MyVariable'
```

The following command gets the value of the secret 'MySecret' from the store.

```powershell
Get-StoreConfig -Name 'MySecret'
```
1. Create a new context for the user -> `Set-Store -Store 'GitHub.BobMarley'` -> Secret `GitHub.BobMarley` is created.
2. Add some user configuration -> `Set-StoreConfig -Store 'GitHub.BobMarley.AccessToken' -Name 'Secret' -Value '123456'` -> Secret `GitHub.BobMarley.AccessToken` is created.
3. Get the user configuration -> `Get-StoreConfig -Store 'GitHub.BobMarley.AccessToken' -Name 'Secret' -AsPlainText` -> `123456`
4. Remove the user configuration -> `Remove-Store -Name 'GitHub.BobMarley.AccessToken'` -> Secret `GitHub.BobMarley.AccessToken` is removed.

## Contributing

Expand All @@ -85,6 +92,6 @@ You can either help by picking up an existing issue or submit a new one if you h

## Links

- SecretManagement | [GitHub](https://github.com/powershell/SecretManagement) | [Docs](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.secretmanagement/?view=ps-modules)
- SecretStore | [GitHub](https://github.com/PowerShell/SecretStore) | [Docs](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.secretstore/?view=ps-modules)
- SecretManagement | [GitHub](https://GitHub.com/powershell/SecretManagement) | [Docs](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.secretmanagement/?view=ps-modules)
- SecretStore | [GitHub](https://GitHub.com/PowerShell/SecretStore) | [Docs](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.secretstore/?view=ps-modules)
- [Overview of the SecretManagement and SecretStore modules | Microsoft Learn](https://learn.microsoft.com/en-us/powershell/utility-modules/secretmanagement/overview?view=ps-modules)
28 changes: 0 additions & 28 deletions src/functions/private/Get-StoreVariable.ps1

This file was deleted.

75 changes: 0 additions & 75 deletions src/functions/private/Initialize-SecretStore.ps1

This file was deleted.

69 changes: 69 additions & 0 deletions src/functions/private/Initialize-SecretVault.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#Requires -Modules Microsoft.PowerShell.SecretManagement
#Requires -Modules Microsoft.PowerShell.SecretStore

function Initialize-SecretVault {
<#
.SYNOPSIS
Initialize a SecretStore with open config.
.DESCRIPTION
Initialize a secret vault. If the vault does not exist, it will be created and registered.
The SecretStore is created with the following parameters:
- Authentication: None
- PasswordTimeout: -1 (infinite)
- Interaction: None
- Scope: CurrentUser
.EXAMPLE
Initialize-SecretStore
Initializes a secret vault named 'SecretStore' using the 'Microsoft.PowerShell.SecretStore' module.
.NOTES
For more information about secret vaults, see
https://learn.microsoft.com/en-us/powershell/utility-modules/secretmanagement/overview?view=ps-modules
#>
[OutputType([Microsoft.PowerShell.SecretManagement.SecretVaultInfo])]
[CmdletBinding()]
param (
# The name of the secret vault.
[Parameter()]
[string] $Name = $script:Config.SecretVaultName,

# The type of the secret vault.
[Parameter()]
[string] $Type = $script:Config.SecretVaultType
)
$vault = Get-SecretVault | Where-Object { $_.ModuleName -eq $Type }
if (-not $vault) {
Write-Verbose "[$Type] - Configuring vault type"

$vaultParameters = @{
Authentication = 'None'
PasswordTimeout = -1
Interaction = 'None'
Scope = 'CurrentUser'
WarningAction = 'SilentlyContinue'
Confirm = $false
Force = $true
}
Reset-SecretStore @vaultParameters
Write-Verbose "[$Type] - Done"

Write-Verbose "[$Name] - Registering vault"
$secretVault = @{
Name = $Name
ModuleName = $Type
DefaultVault = $true
Description = 'SecretStore'
}
Register-SecretVault @secretVault
Write-Verbose "[$Name] - Done"
} else {
Write-Verbose "[$Name] - Vault already registered"
}

Get-SecretVault | Where-Object { $_.ModuleName -eq $Type }

}
27 changes: 0 additions & 27 deletions src/functions/private/Initialize-VariableStore.ps1

This file was deleted.

29 changes: 0 additions & 29 deletions src/functions/private/Set-StoreVariable.ps1

This file was deleted.

Loading

0 comments on commit d1cf656

Please sign in to comment.