SecretManagement
SecretManagement copied to clipboard
VaultName doesn't always make sense - user experience and expectations discussion.
This isn't an issue or feature request but more of a discussion topic as we explore vault creation on various platforms.
I'm finding that in certain scenarios that the concept of a 'Vault Name' doesn't perfectly align.
In situations where authentication is one to many named vaults the concept of $VaultName works well. Authentication is performed, and the specific vault can be engaged by name.
For some projects, this makes a lot of sense:
- SecretStore - ability to create multiple local named vaults, each with a separate set of secrets
- SecretManagement.Hashicorp.Vault.KV - vault server can host multiple name spaces, each storing different sets of secrets
But for some projects, this doesn't make sense. Authentication to the platform gets you a lump set of secrets with no name space. In these projects, the $VaultName parameter isn't even used.
Lets explore two popular cloud providers to see how this can impact the user experience when engaging the capabilities of PowerShell SecretManagement.
- Azure Vault - Azure Vaults are named and store secrets. So here, Azure authentication can occur and the user will provide the appropriate
$VaultNamewhich will engage the desired named Azure vault.- Azure authentication [subscription 1] -->
$VaultName = 'Vault1'--> Azure vault [Vault1] --> [secret1, secret2] - Azure authentication [subscription 1] -->
$VaultName = 'Vault2'--> Azure vault [Vault2] --> [secret15, secret16] - Azure authentication [subscription 2] -->
$VaultName = 'Vault1'--> Azure vault [Vault1] --> throw, no named vault Vault1
- Azure authentication [subscription 1] -->
- AWS Secrets Manager - Secrets Manager does not have the concept of a named vault. Its secrets are stored in the account. So here, authentication is 1:1 and
$VaultNamedoesn't make sense, and can even create confusion.- AWS authentication [account 1] -->
$VaultName = 'Vault1'--> [secret1, secret2] - AWS authentication [account 1] -->
$VaultName = 'Vault2'--> [secret1, secret2] - AWS authentication [account 2] -->
$VaultName = 'Vault1'--> [secret15, secret16]
- AWS authentication [account 1] -->
So in the AWS example, we see that it's authentication that drives the return from the platform. If the user has their default profile set to account 1, they will have access to the secrets in account 1. If the user is instead authenticated with their default profile to account 2, they will have access to that set of secrets.
Is there an expectation or standard we would like to see established for the user experience when engaging SecretManagement?
Mainly around registering a new vault. In the AWS scenario, a Secrets Manager Vault module could be created. Then the user could register that named vault: MyAWSSecrets.
But while that registered vault has a name - the users authentication profile will give them access to a very different set of secrets depending on which account they are authenticated to.
- With account 1 auth
Get-Secret -Name secret1 -Vault MyAWSSecrets -AsPlainText8739raskdsh22372sdas!!#@$@
- With account 2 auth
Get-Secret -Name secret1 -Vault MyAWSSecrets -AsPlainTextNo secrets found named secret1
Disclaimer: Not a MSFT employee
I think you're reading too much into it, it's just a label to reference different vault registrations. By default it's the same name as the vault.
So, in keepass's place, you can have a vault labeled "Personal" thats a personal vault, "Work" that's another, etc.
In your Azure Example, I would probably name each vault after the vault name in Azure, e.g. MyKeyVault1 would be either MyKeyVault1 or maybe paired with subscription or RG name, e.g. MySubscription/MyKeyVault1
In your AWS example (for which I don't think a vault extension exists yet), The vault name might simply reference the entire account, and the individual secrets will be referenced as secrets, e.g. MyAWSAccount as the vault name, and Get-Secret 'tutorials/MyFirstSecret' would fetch that individual secret. It's a very broad abstraction that can be implemented however the extension author wants, however what i laid out in this paragraph is what I think most users would expect. Your AWS example, again, could require a VaultParameter with the accountName to pin it to a specific auth profile, so it would always query against that auth profile.
So vaultname could allow you to reference different vaults from different pinned account contexts, or it can just be a free-roaming one that uses your existing context. It's all in the implementation, and can be toggleable with vault registration parameters. It's entirely up to the extension author.
The issues you bring up can be solved it seems with a proper vault extension implementation (I wrote the keepass, chromium, and credmgr extensions), so in my mind, this should be the de-facto pattern and practice for vaultname
- The vaultname should be the name of the module by default if a name isn't specified and reference the users "current context" or require authentication (whatever that means to the extension)
- The vaultname is always just a label, it doesn't carry with it any meaningful context beyond what the user wants to call it to make it easy for them to remember, and does not influence the operation of the extension vault whatsoever.
- Behavior of a vault (account to connect to, etc.) should be done via the VaultParameters parameter, either directly or via a friendly wrapper command (See Register-ChromiumSecretVault)
- Scripts should generally not reference the secretmanagement syntax directly, but instead take the normal types such as PSCredential, SecureString, etc. as parameters. The user can then opt to supply the secret via secretManagement as a subexpression to your parameter (or not use secretmanagement at all). The exception to this would be if either the secret requires a specific vault for whatever reason, or you want to offer convenient integration as a separate parameter set. Powershell is about choice, and forcing a user to use secretmanagement when they may have a better way to supply the secret is anti-pattern (maybe the only way they can supply the secret is from an API that doesn't have an extension vault yet, for example)
- When referencing a secret in a script meant to be portable, you should not reference a VaultName if at all possible. This allows the user to set their own "default" secretvault and fetch the secret you want to have in your script however they want to.
- A script should allow for the secret name and vault to be a configurable specification, but in some circumstances could be hardcoded to enforce some sort of contract I suppose.