Skip to content

Overview

You can register and mount secret values from secret vaults, like Azure KeyVault or HashiCorp Vault, into Pode for use in Routes, Middleware, etc.

Secrets can also be referenced from a vault in an adhoc manner, without needing to mount them first. You can also create, update, and remove secrets in vaults.

The values of mounted secrets may also be cached for a period of time, to reduce load on the vault as well as speed up lookups.

Registering

To reference Secrets from a vault you first need to register that vault using Register-PodeSecretVault. Registering a vault registers the vault within Pode, but will also call any logic needed by the registration type being used. For example, if using Secret Management then Pode will call Register-SecretVault for you.

A further example, as follows, will use the Secret Management PowerShell module to register an Azure KeyVault within Pode:

Register-PodeSecretVault -Name 'FriendlyVaultName' -ModuleName 'Az.KeyVault' -VaultParameters @{
    AZKVaultName = 'VaultNameInAzure'
    SubscriptionId = $SubscriptionId
}

You can find more information on the Secret Management page. The general parameters for all types are:

Parameter Description
Name This is a friendly name for the vault within Pode that you can reference
VaultParameters This is a hashtable of options, for the vault, that is supplied to vault scripts

Note

You can unregister a vault via Unregister-PodeSecretVault. All vaults are automatically unregistered when the server stops - unless it was auto-imported.

Types

At present, there are just two registration types implemented for registering secret vaults:

Tip

For the SecretManagement module you can read a "getting started" guide here when using the module in automated scenarios.

Vault Examples

You can find some quick examples for some vault providers below:

Initialise

If there is any logic that needs to be invoked before a vault is registered, such as connecting to a cloud provider first (ie: Connect-AzAccount), this can be achieved via the -InitScriptBlock parameter on Register-PodeSecretVault.

This scriptblock is run just before Pode invokes any registration logic, and applies to all registration types. The scriptblock is supplied the -VaultParameters hashtable as a parameter:

Register-PodeSecretVault -Name 'VaultName' -ModuleName 'Az.KeyVault' `
    -VaultParameters @{
        AZKVaultName = 'VaultNameInAzure'
        SubscriptionId = $SubscriptionId
    } `
    -InitScriptBlock {
        param($config)
        Connect-AzAccount -Subscription $config.SubscriptionId
    }

Auto-Import

Similar to modules and functions, Pode will auto-import any secret vaults registered outside of Pode. You can find more information here

Unlock

Some vaults require unlocking first, or an authorization token to be acquired to access the vault. Unlocking applies to all registration types, and to configure unlocking for use you'll first need to supply either an -UnlockSecret or an -UnlockSecureSecret to Register-PodeSecretVault.

Important

If you're using a custom registration type, you'll also need to supply an -UnlockScriptBlock.

Register-PodeSecretVault -Name 'VaultName' -ModuleName 'Az.KeyVault' -UnlockSecret 'some-vault-password' `
    -VaultParameters @{
        AZKVaultName = 'VaultNameInAzure'
        SubscriptionId = $SubscriptionId
    } `
    -UnlockScriptBlock {
        param($config, $secret)
        Unlock-SomeVault -Secret $secret
    }

Pode will automatically call the unlock logic after registration, but you can stop this from occurring by passing -NoUnlock. If you do, you'll need to call Unlock-PodeSecretVault to unlock the vault:

Unlock-PodeSecretVault -Name 'VaultName'

If you need to periodically check/unlock your vault, then Pode can do this automatically for you. To achieve this you can supply a number of minutes for the -UnlockInterval parameter on Register-PodeSecretVault, this will tell Pode to automatically check/unlock the vault after the first unlock has occurred.

Mounting

After registering a secret vault, you can now mount secrets from that vault for use within Pode Routes, Middleware, etc. The logic for mounting a secret is the same regardless of vault type or registration type. A secret can be mounted via Mount-PodeSecret:

Mount-PodeSecret -Name 'SecretName' -Vault 'VaultName' -Key 'SecretKeyNameInVault'

The -Name is the name of the secret you'll be using to reference the secret throughout Pode. The -Vault parameter is the name of the vault from Register-PodeSecretVault, and the -Key is the path/name of the secret within the vault itself.

Some secrets will be returned as hashtables - such as from HashiCorp Vault. In some cases, you might only want certain properties to be returned from this secret, and you can limit the properties returned by using the -Property parameter. For example, if a secret has 5 keys named key1 to key5, you can limit this to just key2 and key4:

Mount-PodeSecret -Name 'SecretName' -Vault 'VaultName' -Key 'SecretKeyNameInVault' -Property key2, key4

Or, you can limit the result to a single property, and expand on it - so now you get a string returned and not a hashtable:

Mount-PodeSecret -Name 'SecretName' -Vault 'VaultName' -Key 'SecretKeyNameInVault' -ExpandProperty key3

Note

When using -ExpandProperty and you want to update the value, just pass a raw string (or whatever the inner type is). Pode will automatically wrap the original property key back for you.

Note

You can dismount a mounted secret via Dismount-PodeSecret. If you also supply the -Remove switch the secret will be deleted within the vault as well.

Secret Scope

To retrieve the values of mounted secrets you can use Get-PodeSecret, and then to update the value of the secret you can use Update-PodeSecret:

# get secret
Add-PodeRoute -Method Get -Path '/secret' -ScriptBlock {
    Write-PodeJsonResponse @{ Value = (Get-PodeSecret -Name 'SecretName') }
}

# update secret
Add-PodeRoute -Method Post -Path '/secret' -ScriptBlock {
    $WebEvent.Data.Value | Update-PodeSecret -Name 'SecretName'
}

Or, you can do the same but using the $secret: scope:

# get secret
Add-PodeRoute -Method Get -Path '/secret' -ScriptBlock {
    Write-PodeJsonResponse @{ Value = $secret:SecretName }
}

# update secret
Add-PodeRoute -Method Post -Path '/secret' -ScriptBlock {
    $secret:SecretName = $WebEvent.Data.Value
}

Caching

Important

The cache is an in-memory in-application cache, and is unencrypted. It is never stored on disk, and cached values are wiped once their expiry is up; the cache is also wiped when the server is stopped.

To reduce round-trip time by constantly going to a vault, as well as to reduce stress on a vault, you can optionally enable caching on secrets - the cache by default is disabled.

You can either supply a -CacheTtl as a number of minutes to Register-PodeSecretVault and all secrets mounted will be cached. Or you can supply a -CacheTtl only to specific mounted secrets - you can also use this option to disable caching for a secret, by supplying a value of 0, even if the vault itself is registered with a cache TTL.

To enable caching for all mounted secrets from a vault - but with one disabled, and one overriding:

# register a vault with a secret cache TTL of 5 minutes
Register-PodeSecretVault -Name 'FriendlyVaultName' -ModuleName 'Az.KeyVault' -CacheTtl 5 -VaultParameters @{
    AZKVaultName = 'VaultNameInAzure'
    SubscriptionId = $SubscriptionId
}

# mount a secret, that will use the vault cache of 5mins
Mount-PodeSecret -Name 'SecretName1' -Vault 'VaultName' -Key 'SecretKeyNameInVault1'

# mount a secret, that will use a custom cache TTL of 10mins
Mount-PodeSecret -Name 'SecretName2' -Vault 'VaultName' -Key 'SecretKeyNameInVault2' -CacheTtl 10

# mount a secret, that uses no caching
Mount-PodeSecret -Name 'SecretName3' -Vault 'VaultName' -Key 'SecretKeyNameInVault3' -CacheTtl 0

And then to enable caching for just specific mounted secrets:

# register a vault with no secret cache
Register-PodeSecretVault -Name 'FriendlyVaultName' -ModuleName 'Az.KeyVault' -VaultParameters @{
    AZKVaultName = 'VaultNameInAzure'
    SubscriptionId = $SubscriptionId
}

# mount a secret, that won't be cached
Mount-PodeSecret -Name 'SecretName1' -Vault 'VaultName' -Key 'SecretKeyNameInVault1'

# mount a secret, that will use a custom cache TTL of 10mins
Mount-PodeSecret -Name 'SecretName2' -Vault 'VaultName' -Key 'SecretKeyNameInVault2' -CacheTtl 10

Adhoc

There is also support for creating/updating, retrieving, and removing secrets in an adhoc manner from registered vaults - without having to mount them.

Create

To create a new secret, as well as update an existing value, you can use Set-PodeSecret:

Add-PodeRoute -Method Post -Path '/adhoc/:key' -ScriptBlock {
    Set-PodeSecret -Key $WebEvent.Parameters['key'] -Vault 'VaultName' -InputObject $WebEvent.Data['value']

    # if you needed to, afterwards, you could mount the secret as well
    Mount-PodeSecret -Name $WebEvent.Data['name'] -Vault 'VaultName' -Key $WebEvent.Parameters['key']
}

Read

To retrieve the secret's value you can use Read-PodeSecret:

Add-PodeRoute -Method Get -Path '/adhoc/:key' -ScriptBlock {
    $value = Read-PodeSecret -Key $WebEvent.Parameters['key'] -Vault 'VaultName'
    Write-PodeJsonResponse @{ Value = $value }
}

Remove

To remove the secret from the vault you can use Remove-PodeSecret:

Add-PodeRoute -Method Delete -Path '/adhoc/:key' -ScriptBlock {
    # if the secret wasn't mounted, you can just call Remove-PodeSecret directly
    Remove-PodeSecret -Key $WebEvent.Parameters['key'] -Vault 'VaultName'

    # if the secret was mounted, you can dismount and remove from the vault via
    Dismount-PodeSecret -Name $WebEvent.Parameters['key'] -Remove
}