PowerShell / SecretManagement

PowerShell module to consistent usage of secrets through different extension vaults
MIT License
335 stars 47 forks source link

Secret object type for deeper integration #212

Open mgreenegit opened 1 year ago

mgreenegit commented 1 year ago

Summary of the new feature / enhancement

User story

As a PowerShell module author, I want to use secrets in my custom functions without needing to learn about and run the individual cmdlets that deal with secrets.

Current Experience

Currently, module authors need to use the Get-Secret cmdlet from the SecretManagement module to retrieve secrets within their functions. This requires additional code and makes it less convenient to work with secrets stored in a vault.

Enhanced Experience

With the proposed enhancement, module authors can use a new [Secret] type for their function parameters. This type allows referencing the name of a secret stored in a vault the user has access to, providing a deep integration with the PowerShell Secret Store.

Proposed technical implementation details (optional)

In the following mock-ups, the first example demonstrates the current experience. In the second example, the author enjoys integration with secret store without needing to learn about and handle the integration. Although this mock-up is overly simple, the implementation could handle additional scenarios such as argument completion (list of secrets) and handling securestring vs plain text.

# Current approach using Get-Secret
function Invoke-SecureAction {
    param (
        [string]$SecretName
    )

    $SecretValue = Get-Secret -Name $SecretName
    # Perform secure action using $SecretValue
}

# Proposed approach with [Secret] type
function Invoke-SecureAction {
    param (
        [Secret]$MySecret
    )

    # Perform secure action using $MySecret.Value
}

Very limited POC.


class secret {
    [ValidateNotNullOrEmpty()]
    [string]$Name
    [secureString] hidden $Secret

    secret ($Name) {
        $this.Name = $Name
        [secureString]$this.Secret = Get-Secret -Name $Name
    }

    [string]asplaintext () {
        [string]$asplaintext = Get-Secret -Name $this.Name -AsPlainText
        return $asplaintext
    }
}
``
JustinGrote commented 1 year ago

It's a reasonably convenient approach, I've always like how Microsoft.Extensions.Configuration basically takes a lot of complex inputs and boils them down to a key-value store and this is a similar concept.

Thoughts:

  1. What if I, as a user, don't want to use secretmanagement to give you my credential? You'd need to instruct module authors to use parametersets probably which is an even more complicated scenario.
  2. What if I don't want to use the default vault? How am I going to specify it? And how is your class going to know?
mgreenegit commented 1 year ago

@JustinGrote good point. could have an optional parameter for vault name. I only run into that when I store the same name for a secret in multiple vaults, but it happens.