Store.psm1
[Diagnostics.CodeAnalysis.SuppressMessageAttribute( 'PSAvoidLongLines', '', Justification = 'Contains long links.')] [CmdletBinding()] param() if ($PSVersionTable.PSVersion -lt '6.0') { [Diagnostics.CodeAnalysis.SuppressMessageAttribute( 'PSAvoidAssignmentToAutomaticVariable', '', Justification = 'Compatibility with PowerShell 6.0 and newer.' )] $IsWindows = [System.Environment]::OSVersion.Platform -eq 'Win32NT' } $scriptName = 'Store' Write-Verbose "[$scriptName] - Importing module" #region - From [init] Write-Verbose "[$scriptName] - [init] - Processing folder" #region - From [init] - [Store] Write-Verbose "[$scriptName] - [init] - [Store] - Importing" $script:Store = [PSCustomObject]@{} Write-Verbose "[$scriptName] - [init] - [Store] - Done" #endregion - From [init] - [Store] Write-Verbose "[$scriptName] - [init] - Done" #endregion - From [init] #region - From [private] Write-Verbose "[$scriptName] - [private] - Processing folder" #region - From [private] - [Get-StoreVariable] Write-Verbose "[$scriptName] - [private] - [Get-StoreVariable] - Importing" function Get-StoreVariable { <# .SYNOPSIS Get a variable from the store. .EXAMPLE Get-StoreVariable Gets all the variables in the store. .EXAMPLE Get-StoreVariable -Name 'Name' Gets the value of the variable with the name 'Name'. #> [CmdletBinding()] [OutputType([object])] param( [Parameter()] [string] $Name ) if (-not $Name) { $script:Store } else { $script:Store.$Name } } Write-Verbose "[$scriptName] - [private] - [Get-StoreVariable] - Done" #endregion - From [private] - [Get-StoreVariable] #region - From [private] - [Initialize-SecretStore] Write-Verbose "[$scriptName] - [private] - [Initialize-SecretStore] - Importing" #Requires -Modules Microsoft.PowerShell.SecretManagement #Requires -Modules Microsoft.PowerShell.SecretStore function Initialize-SecretStore { <# .SYNOPSIS Initialize a secret vault. .DESCRIPTION Initialize a secret vault. If the vault does not exist, it will be created. .EXAMPLE Initialize-SecretStore -Name 'SecretStore' -Type 'Microsoft.PowerShell.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([void])] [CmdletBinding()] param ( # The name of the secret vault. [Parameter()] [string] $Name = 'SecretStore', # The type of the secret vault. [Parameter()] [Alias('ModuleName')] [string] $Type = 'Microsoft.PowerShell.SecretStore' ) $vault = Get-SecretVault | Where-Object { $_.ModuleName -eq $Type } if (-not $vault) { Write-Verbose "[$Type] - Registering" switch ($Type) { 'Microsoft.PowerShell.SecretStore' { $vaultParameters = @{ Authentication = 'None' PasswordTimeout = -1 Interaction = 'None' Scope = 'CurrentUser' WarningAction = 'SilentlyContinue' Confirm = $false Force = $true } Reset-SecretStore @vaultParameters } } Write-Verbose "[$Type] - Done" } else { Write-Verbose "[$Type] - already registered" } $secretStore = Get-SecretVault | Where-Object { $_.Name -eq $Name } if (-not $secretStore) { Write-Verbose "[$Name] - Registering" $secretVault = @{ Name = $Name ModuleName = $Type DefaultVault = $true Description = 'SecretStore' } Register-SecretVault @secretVault Write-Verbose "[$Name] - Done" } else { Write-Verbose "[$Name] - already registered" } Set-StoreVariable -Name 'SecretVaultName' -Value $Name Set-StoreVariable -Name 'SecretVaultType' -Value $Type } Write-Verbose "[$scriptName] - [private] - [Initialize-SecretStore] - Done" #endregion - From [private] - [Initialize-SecretStore] #region - From [private] - [Initialize-VariableStore] Write-Verbose "[$scriptName] - [private] - [Initialize-VariableStore] - Importing" function Initialize-VariableStore { <# .SYNOPSIS Initialize the variable store. #> [CmdletBinding()] [OutputType([void])] param ( [Parameter(Mandatory)] [string] $Name ) $folderName = ".$($Name -replace '^\.')".ToLower() $configFilePath = Join-Path -Path $HOME -ChildPath "$folderName/config.json" if (-not (Test-Path -Path $configFilePath)) { $null = New-Item -Path $configFilePath -ItemType File -Force Set-StoreVariable -Name 'ConfigFilePath' -Value $configFilePath Set-StoreVariable -Name 'Name' -Value $Name } $script:Store = Get-Content -Path $configFilePath | ConvertFrom-Json } Write-Verbose "[$scriptName] - [private] - [Initialize-VariableStore] - Done" #endregion - From [private] - [Initialize-VariableStore] #region - From [private] - [Set-StoreVariable] Write-Verbose "[$scriptName] - [private] - [Set-StoreVariable] - Importing" function Set-StoreVariable { <# .SYNOPSIS Set a variable in the store. .EXAMPLE Set-StoreVariable -Name 'Name' -Value 'MyName' #> [CmdletBinding(SupportsShouldProcess)] param( # The name of the variable to set. [Parameter(Mandatory)] [string] $Name, # The value to set. [Parameter(Mandatory)] [AllowNull()] [object] $Value ) if ($PSCmdlet.ShouldProcess("Set variable '$Name' to '$Value'")) { if ($null -eq $Value) { $script:Store.PSObject.Properties.Remove($Name) } else { $script:Store | Add-Member -MemberType NoteProperty -Name $Name -Value $Value -Force } $script:Store | ConvertTo-Json -Depth 100 | Set-Content -Path $script:Store.ConfigFilePath -Force } } Write-Verbose "[$scriptName] - [private] - [Set-StoreVariable] - Done" #endregion - From [private] - [Set-StoreVariable] Write-Verbose "[$scriptName] - [private] - Done" #endregion - From [private] #region - From [public] Write-Verbose "[$scriptName] - [public] - Processing folder" #region - From [public] - [Get-StoreConfig] Write-Verbose "[$scriptName] - [public] - [Get-StoreConfig] - Importing" #Requires -Modules Microsoft.PowerShell.SecretManagement function Get-StoreConfig { <# .SYNOPSIS Get configuration value. .DESCRIPTION Get a named configuration value from the store configuration. .EXAMPLE Get-StoreConfig -Name ApiBaseUri Get the value of ApiBaseUri config. #> [OutputType([object])] [CmdletBinding()] param ( # Choose a configuration name to get. [Parameter()] [string] $Name, # Return the value as plain text if it is a secret. [Parameter()] [switch] $AsPlainText ) if (-not $Name) { return [pscustomobject]@{ Secrets = Get-SecretInfo | ForEach-Object { [pscustomobject]@{ Name = $_.Name Value = Get-Secret -Name $_.Name -AsPlainText:$AsPlainText -Vault $script:Store.SecretVaultName } } Variables = $script:Store } } $value = Get-StoreVariable -Name $Name if (($null -eq $value) -and ((Get-SecretInfo -Vault $script:Store.SecretVaultName).Name -contains $Name)) { $value = Get-Secret -Name $Name -AsPlainText:$AsPlainText -Vault $script:Store.SecretVaultName } $value } Write-Verbose "[$scriptName] - [public] - [Get-StoreConfig] - Done" #endregion - From [public] - [Get-StoreConfig] #region - From [public] - [Initialize-Store] Write-Verbose "[$scriptName] - [public] - [Initialize-Store] - Importing" function Initialize-Store { <# .SYNOPSIS Initialize the store for a module. .EXAMPLE Initialize-Store -Name 'MyStore' #> [CmdletBinding()] param ( # Name of the store. [Parameter(Mandatory)] [string] $Name, # The name of the secret vault. [Parameter()] [string] $SecretVaultName = 'SecretStore', # The type of the secret vault. [Parameter()] [string] $SecretVaultType = 'Microsoft.PowerShell.SecretStore' ) Initialize-VariableStore -Name $Name Initialize-SecretStore -Name $SecretVaultName -Type $SecretVaultType } Write-Verbose "[$scriptName] - [public] - [Initialize-Store] - Done" #endregion - From [public] - [Initialize-Store] #region - From [public] - [Set-StoreConfig] Write-Verbose "[$scriptName] - [public] - [Set-StoreConfig] - Importing" #Requires -Modules Microsoft.PowerShell.SecretManagement function Set-StoreConfig { <# .SYNOPSIS Set a configuration variables or secret. .DESCRIPTION Set a configuration variable or secret in the configuration store. .EXAMPLE Set-StoreConfig -VariableName "ApiBaseUri" -Value 'https://api.github.com' Sets a variable called 'ApiBaseUri' in the configuration store (json file). .EXAMPLE Set-StoreConfig -SecretName "AccessToken" -Value 'myAccessToken' Sets a secret called 'AccessToken' in the configuration store (secret vault). #> [CmdletBinding(SupportsShouldProcess)] param ( # The name of a variable to set. [Parameter(Mandatory)] [string] $Name, # The value to set. [Parameter(Mandatory)] [AllowNull()] [object] $Value ) if ($PSCmdlet.ShouldProcess("Set variable '$Name' to '$Value'")) { if ($Value -is [SecureString]) { Set-Secret -Name $Name -SecureStringSecret $Value } else { Set-StoreVariable -Name $Name -Value $Value } } } Write-Verbose "[$scriptName] - [public] - [Set-StoreConfig] - Done" #endregion - From [public] - [Set-StoreConfig] Write-Verbose "[$scriptName] - [public] - Done" #endregion - From [public] $exports = @{ Alias = '*' Cmdlet = '' Function = @( 'Get-StoreConfig' 'Initialize-Store' 'Set-StoreConfig' ) Variable = '' } Export-ModuleMember @exports |