PowerShell / SecretStore

MIT License
154 stars 23 forks source link

Utilize the Windows Credential Manager as the secret store #103

Open ohadschn opened 8 months ago

ohadschn commented 8 months ago

Summary of the new feature / enhancement

The current design allows 2 configurations:

  1. Password-based, which can get a bit tedious as each new session requires to input it again, and every 15 minutes even if you stay on the same shell
  2. No password, where they key is stored in some file in the user's location. This option is highly discouraged by the docs.

However, on Windows at least, there is a third option - use the built-in Credential Manager. As I understand the latter, it should be very secure, especially when Credential Guard is enabled (https://learn.microsoft.com/en-us/windows/security/identity-protection/credential-guard/). And since the current credentials are used, there is no need for passwords. As a bonus, you get a free editor/viewer built-in Windows.

Indeed, it seems exactly one such credential store has been created: https://www.powershellgallery.com/packages/SecretManagement.JustinGrote.CredMan/1.0.0. However, I can't even find the code for it, it hasn't been updated in more than 3 years, there was only one version ever released, and that version has only been downloaded around 6,600 times in all that time... so you can see why I find it hard to install and manage my passwords. Really in such matters I would typically only trust something much more popular, or something with a big company behind it - especially if that company was the one behind PowerShell itself...

Proposed technical implementation details (optional)

Perhaps you could contact the developer of said secret store, who I believe is @JustinGrote, to incorporate his code into this project. Alternatively, you could take the code from the "original" PS Credential Manager module (more precisely, it's current continuation where @echalone is carrying the torch): https://github.com/echalone/PowerShell_Credential_Manager

I just tested the latter and it works great - Windows already did all the hard work to let us access secrets conveniently and securely, would be a shame not to use it!

ThomasNieto commented 8 months ago

I may have missed it but why should this project use cred man? SecretsManagements allows use of different vault providers to store to various systems. SecretStore is a cross platform implementation and CredMan module uses CredMan and is Windows exclusive. If you want to use CredMan use that module.

ohadschn commented 8 months ago

SecretsManagements allows use of different vault providers to store to various systems. SecretStore is a cross platform implementation and CredMan module uses CredMan and is Windows exclusive.

Right, which is why I'm suggesting that the Windows implementation of SecretStore uses the Credential Manager under the covers (specifically when configured not to use a password, or alternatively introduce a third configuration that uses the Credential Manager on Windows and falls back to something else on the other OS). That we way we get to eat our cake and have it too.

Using SecretManagement.JustinGrote.CredMan as-is would lose the cross-platform benefit, not to mention the entire paragraph I dedicated to explaining why I wouldn't use it even if it were cross-platform...

I can't even find the code for it, it hasn't been updated in more than 3 years, there was only one version ever released, and that version has only been downloaded around 6,600 times in all that time... so you can see why I find it hard to install and manage my passwords. Really in such matters I would typically only trust something much more popular, or something with a big company behind it - especially if that company was the one behind PowerShell itself...

ThomasNieto commented 8 months ago

Look back at the RFC. That was the original plan but was changed to the same implementation for all platforms.

You already have the option to use CredMan leverage an existing module that has that capability or make your own if you don't trust their implementation. The PowerShell team made the decision to use a single implementation for all platforms and left creation of other vault providers to the community.

ohadschn commented 8 months ago

Look back at the RFC. That was the original plan but was changed to the same implementation for all platforms.

That is unfortunate. So you're saying that not only does the SecretStore not use CredMan on Windows, but it doesn't use Keychain on Mac and doesn't use keyring on linux?

You already have the option to use CredMan leverage an existing module that has that capability or make your own if you don't trust their implementation. The PowerShell team made the decision to use a single implementation for all platforms and left creation of other vault providers to the community.

Sure, I could roll my own, but instead of every person rolling their own - I humbly suggest the PowerShell team to revisit their RFC plan which looks great (assuming this is the one: https://github.com/SydneyhSmith/PowerShell-RFC/blob/master/1-Draft/RFCxxxx-Secrets-Management.md)...

ThomasNieto commented 8 months ago

That is unfortunate. So you're saying that not only does the SecretStore not use CredMan on Windows, but it doesn't use Keychain on Mac and doesn't use keyring on linux?

It stores secrets locally on file for the current user account context, and uses .NET crypto APIs to encrypt file contents.

That is correct look at the README on this repo and you'll see what it uses.

Sure, I could roll my own, but instead of every person rolling their own - I humbly suggest the PowerShell team to revisit their RFC plan which looks great (assuming this is the one: https://github.com/SydneyhSmith/PowerShell-RFC/blob/master/1-Draft/RFCxxxx-Secrets-Management.md)...

I didn't say you had to roll your own. As you point out in your post there are vault providers that leverage your desired vault type (CredMan). What is the issue with using either of the two modules you reference? You seem to be conflating SecretStore which is a cross platform vault which does not leverage native functionality with wanting a Microsoft owned vault provider that uses native functionality.

ohadschn commented 8 months ago

As you point out in your post there are vault providers that leverage your desired vault type (CredMan). What is the issue with using either of the two modules you reference?

I already explained my reservations with this approach - perhaps you remain unconvinced, and that's fair enough :)

You seem to be conflating SecretStore which is a cross platform vault which does not leverage native functionality with wanting a Microsoft owned vault provider that uses native functionality.

I don't see any conflation here, that is exactly what I'm asking for :) Specifically, I submit that this project (SecretStore) should use native functionality, instead of what it does now (hence opening the issue in this repo).

JustinGrote commented 8 months ago

There are two vault providers that already provide this functionality: https://www.powershellgallery.com/packages/SecretManagement.JustinGrote.CredMan/1.0.0 https://www.powershellgallery.com/packages/SecretManagement.DpapiNG/0.3.0

The second one is particular interesting because you can use DpapiNG and encrypt secrets that can be decrypted by members of an AD group, allowing some secrets to be portable. It also has full source code available since that was expressed as one of your concerns and JBorean is a well regarded PS developer. I would investigate that for your use case.

@ohadschn SecretStore would not be cross platform if it used credman, hence why that was changed. Windows is not the only platform that SecretManagement must support.

The team provided an API with SecretManagement, and an example implementation with SecretStore. My version is a slightly reworked version of the example in the SecretManagement repo, that would be the "original" one.

If I get some time maybe I'll adapt my vault extension to https://github.com/echalone/PowerShell_Credential_Manager and PR it there so it can live on, but mine was again just a compilation of what's in the SecretManagement repo already.

ohadschn commented 8 months ago

@JustinGrote Thank you Justin, as I mentioned above my suggestion was to use the Credential Manager only for the Windows implementation (and ideally use Keychain for mac and Keyring for Linux - just as the original RFC detailed).

I agree that the DPAPI extension is interesting, but even if I trust the developer (who I'm ashamed to admit I haven't heard of), it still isn't cross-platform and has a total of 22 download at this point... I think it just goes to highlight the need of something "MS official" to solve this once and for all (again, exactly as the original RFC suggested).

I guess I'm asking the PS team for something that's more than a "sample implementation", because IMHO the community based approach hasn't proven itself. AFAIK there no proper (i.e. native OS based) cross-plat solution was created (something like node-keytar / electron safeStorage / chromius OS_Crypt), and even the non-xplat ones that were created are not popular / well-known enough for the layperson to trust blindly.

Perhaps the "community" part would be better if this repo simply accepted PRs. MS could at least provide the native Windows implementation via DPAPI/ Credential Manager (seems like a reasonable request, as it's in-house) and perhaps rely on the community to fill in the mac/Linux gaps if they don't have the resources to work on those.

JustinGrote commented 8 months ago

NOTE: I am not an MS team member, just a community member

@ohadschn I understand your concerns and your want, but the PS team is limited in size and effort, and creating a "cross platform" native OS solution requires making lots of choices, and supporting a lot more than the list you have here because plenty of esoteric OSes may have their own managers. That's not only a lot of upfront development, but worse, a lot of maintenance upkeep. It's my opinion that SecretStore was a good compromise given those constraints.

You're fine with whatever your criteria is for "proving" extension vaults, but I use several in production just fine every day. Further, you could contribute to the community and create an extension vault yourself that meets the criteria you need:

https://devblogs.microsoft.com/powershell/secrets-management-module-vault-extensions/ https://www.youtube.com/watch?v=J86GYcyZAZs https://www.youtube.com/watch?v=Y7U-dreIiXc

The reality is the team is unlikely to have the bandwidth to take this on for this module itself, it went through a lot of rounds of revision during development and as was mentioned, using the OS-specific operations was attempted but deemed not maintainable to keep the quality high, so to reopen that discussion I imagine would take a lot of developer feedback.

ohadschn commented 8 months ago

I thought about it some more, and perhaps cross-platform implementation is not that important. I mean, the whole point of the SecretManagement is that each developer could register their own vault on their machine as a one-time operation, according to their requirements and preferences (depending on their OS, password manager of choice, etc.) From that point on, shared scripts that manipulate secrets would work because they won't be referencing said underlying vault (they'd just use Get-Secret etc.)

In light of this, I suggest the following to the team:

  1. Clarify in the README that this secret store is basically a generic sample. In the vast majority of cases (let's say excluding esoteric OS scenarios), there would be significantly better options:
    • DPAPI/CredentialManager for Windows
    • Keychain for Mac
    • libsecret/gnome-keyring/kwallet for linux
  2. Take ownership of specific implementations that don't require high maintenance.
ohadschn commented 8 months ago

The team provided an API with SecretManagement, and an example implementation with SecretStore. My version is a slightly reworked version of the example in the SecretManagement repo, that would be the "original" one.

Somehow I completely missed this - only today did I realize you were referring to a seemingly fully, working Credential Manager store implementation, namely Microsoft.PowerShell.CredManStore.Extension, provided by the PowerShell team (specifically @PaulHigin), which is exactly what I was after all this time: https://github.com/PowerShell/SecretManagement/tree/master/ExtensionModules/CredManStore

A shame that it's basically not mentioned anywhere, and I found it completely by accident, out of curiosity to see what the ExtensionModules folder contained (fun fact, it also contains an Azure KeyVault implementation: https://github.com/PowerShell/SecretManagement/tree/master/ExtensionModules/AKVaultScript).

So for my bullet (2) above, the PS team can just take the existing sample - it doesn't look like it would require much maintenance... And until that happens, maybe document the existence of these working samples with some basic instructions on how to get them to work? Ideally there'd be a GitHub release that contains the module binaries, because for me it was a pain to build them:

  1. git clone https://github.com/PowerShell/SecretManagement.git
  2. cd .\SecretManagement\ExtensionModules\CredManStore\
  3. .\build.ps1 -Build
  4. Copy-Item .\Microsoft.PowerShell.CredManStore.Extension\ .\out\Microsoft.PowerShell.CredManStore\ -Recurse
  5. There is a bug in the publish script's local PS resource repository creation, so we need to create it ourselves:
    $sourceName = 'pspackageproject-local-repo'
    $packageLocation = Join-Path -Path ([System.io.path]::GetTempPath()) -ChildPath $sourceName
    $modulesLocation = Join-Path -Path $packageLocation -ChildPath 'modules'
    $locationAsUri = "file://$modulesLocation" -as [System.Uri]
    Register-PSResourceRepository -Name $sourceName -Uri $locationAsUri
  6. .\build.ps1 -Publish
  7. Install-PSResource -Repository 'pspackageproject-local-repo' -Name Microsoft.PowerShell.CredManStore
  8. Register-SecretVault -Name CredManStore -ModuleName Microsoft.PowerShell.CredManStore -DefaultVault

You can now use secret management as normal e.g.

I realize this probably very similar to what @JustinGrote did with SecretManagement.JustinGrote.CredMan, but this way you maintain the MS chain of trust.