{"id":18562,"date":"2020-09-16T11:45:22","date_gmt":"2020-09-16T19:45:22","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/powershell\/?p=18562"},"modified":"2022-04-06T09:55:47","modified_gmt":"2022-04-06T17:55:47","slug":"secretmanagement-module-preview-design-changes","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/powershell\/secretmanagement-module-preview-design-changes\/","title":{"rendered":"SecretManagement Module Preview Design Changes"},"content":{"rendered":"<h2>SecretManagement Module Preview Design Changes<\/h2>\n<p>This article is intended primarily for SecretManagement extension vault developers.\nIt covers design changes that an extension vault implementer must be aware of.<\/p>\n<p>It has been about 6 months since we published a pre-release alpha version of SecretManagement.\nSince that time we have received a bunch of great feedback from the community.\nThere have been a number of incremental changes and improvements (including changing the name of the module).\nBut it also became clear that the original vision and design suffered some shortcomings.\nConsequently, we re-thought the design and have been experimenting with various changes.\nFor this <a href=\"https:\/\/www.powershellgallery.com\/packages\/Microsoft.PowerShell.SecretManagement\/0.5.2-preview3\">preview release<\/a>, we now have what we feel is a better and simpler design providing a consistent cross-platform experience.<\/p>\n<h2>Changes<\/h2>\n<h3>Design Issues<\/h3>\n<p>One problem with the previous alpha release was that it depended on the Windows Credential Manager (CredMan) for the built-in local vault.\nThe built-in local vault is a secure local store that is always available, regardless of whether any extension vaults are registered.\nCredMan is Windows platform only, and so the pre-release version of SecretManagement worked only on Windows.\nThe plan was to eventually find similar third party solutions for non-Windows platforms.\nHowever it turns out that CredMan is pretty unique, and there are no equivalent solutions on non-Windows platforms.\nIn addition community members pointed out that CredMan only works for interactive log-in accounts, and this means SecretManagement pre-release would not work with Windows built-in accounts or over PowerShell remoting.<\/p>\n<p>Another problem was the decision to allow extension vaults to be written either as a binary C# implementing type or a PowerShell module.\nThese two forms of an extension vault are quite different, and the code became complex trying to accommodate them both.\nThe result was that extension vaults written in the two forms would have different behavior.<\/p>\n<p>An original design goal was to abstract both management of secrets and management of secret vaults.\nBut we found that the way we abstracted secret vaults was too restrictive to accommodate the wide variety of existing local and cloud based secure store solutions we saw.\nWith this new design we are focusing on abstracting the management of secrets.\nThe purpose of SecretManagement is to provide scripts a common way to access secrets from widely different secret store solutions.\nSo the new design leaves it to the individual vault solutions how they are installed, configured, and authenticated.<\/p>\n<h3>Built-In Local Vault<\/h3>\n<p>The built-in local vault served two purposes.\nIt provided an out-of-the-box secure local store, and also provided a way to store sensitive registration data for extension vaults.\nBut using CredMan as the local store limited SecretManagement to Windows platform, without any good similar solutions on other platforms.\nNevertheless, a CredMan based extension vault is still useful for many Windows platform scenarios, and so we now have a CredMan based extension vault example available in the GitHub repo.<\/p>\n<p>The original design allowed extension vault implementations to store additional vault registry information securely in the built-in local vault.\nBut we never saw a case where this was needed.\nSecure store solutions have their own way to authenticate a user and don&#8217;t need to store sensitive data.<\/p>\n<p>Consequently, the built-in local vault has been removed from SecretManagement.\nAll storage mechanisms are now extension vaults only.\nBut SecretManagement without an extension vault is not very useful, so we are also publishing a preview release of a new cross-platform secure store extension vault.\nYou can read more about the new <a href=\"\">SecretStore Extension Vault<\/a> in the section below.<\/p>\n<p>We have also added the ability to designate a registered extension vault as a <code>Default<\/code> vault.\nThe default vault works like the built-in vault did.\nIf no vault is specified when adding a secret, it is added to the default vault.\nAlso the default vault is searched before any other registered vault, when retrieving secrets.<\/p>\n<h3>Implementing Type<\/h3>\n<p>Support for an extension vault based on an implementing type has been removed.\nThis greatly simplifies SecretManagement and provides a more uniform development experience.<\/p>\n<p>Now, extension vaults are just PowerShell modules that implement five required functions.\nWhen an extension vault is registered as a module, it is verified to have the correct form and to implement the expected functions.\nThe extension vaults can be PowerShell script modules or binary modules, and the <a href=\"https:\/\/github.com\/PowerShell\/SecretManagement\">SecretManagement GitHub repo<\/a> has examples of both forms.<\/p>\n<h3>Extension Vault User Interaction<\/h3>\n<p>Previously, an extension vault communicated to the user indirectly by passing results and error messages up to SecretManagement.\nHowever, this greatly complicated writing extension vaults around existing secret store solutions on various platforms.\nIt was very difficult or impossible to support different forms of authentication.\nFor example, an extension vault couldn&#8217;t prompt the user directly for some action such as providing a password.<\/p>\n<p>But now extension vaults are just PowerShell modules and their exposed functions (cmdlets) are called on the UI thread.\nSo each extension vault can now write to the pipeline, error or data streams, and can directly prompt users for actions.<\/p>\n<p>This means an extension vault now has much more leeway in how it communicates to the user.\nBut it is also responsible for ensuring a consistent user experience with other vaults.\nAn extension vault should take care to write only expected data to the pipeline, and to write error data only for abnormal conditions specific to the vault implementation.\nCommon error conditions, such as <code>secret not found<\/code> should be left to SecretManagement.<\/p>\n<h3>Extension Vault Module Format<\/h3>\n<p>Now that SecretManagement calls extension vault functions on the UI thread, there have been some changes in how an extension module resides on file.\nEach extension vault module implements the same five functions.\nSecretManagement needs to disambiguate the function calls, and also ensure that these functions do not appear in the user command space.<\/p>\n<p>To do this, an extension vault module must conform a specific file structure.\nThe following is an example of the required file structure for an extension vault named <code>TestVault<\/code>:<\/p>\n<pre><code class=\"powershell\">.\/TestVault\r\n.\/TestVault\/TestVault.psd1\r\n.\/TestVault\/TestStoreImplementation.dll\r\n.\/TestVault\/TestVault.Extension\r\n.\/TestVault\/TestVault.Extension\/TestVault.Extension.psd1\r\n.\/TestVault\/TestVault.Extension\/TestVault.Extension.psm1\r\n<\/code><\/pre>\n<p>The <code>TestVault<\/code> module contains a normal <code>TestVault.psd1<\/code> PowerShell module manifest file.\nIt also has an optional <code>TestStoreImplementation.dll<\/code> binary that implements the actual store.\nThe manifest file looks like this:<\/p>\n<pre><code class=\"powershell\">@{\r\n    ModuleVersion = '1.0'\r\n    RootModule = '.TestStoreImplementation.dll'\r\n    NestedModules = @('.TestVault.Extension')\r\n    CmdletsToExport = @('Set-TestStoreConfiguration','Get-TestStoreConfiguration')\r\n}\r\n<\/code><\/pre>\n<p>The manifest file exports two optional cmdlets used to configure the store.\nBut the only required field is <code>NestedModules<\/code> that tells PowerShell to load the <code>TestVault.Extension<\/code> sub module as a nested module of <code>TestVault<\/code>.<\/p>\n<p>It is the <code>TestVault.Extension<\/code> module that contains the required function implementations.\nIt must be named with the parent module name plus the <code>.Extension<\/code> part appended to it.\nThe <code>TestVault.Extension<\/code> hides the SecretManagement required functions from the user, and also uniquely qualifies the functions for this specific extension vault module.\nThe <code>TestVault.Extension<\/code> sub module contains the expected .psd1 and .psm1 files.\nThe manifest file looks like:<\/p>\n<pre><code class=\"powershell\">@{\r\n    ModuleVersion = '1.0'\r\n    RootModule = '.TestVault.Extension.psm1'\r\n    RequiredAssemblies = '..TestStoreImplementation.dll'\r\n    FunctionsToExport = @('Set-Secret','Get-Secret','Remove-Secret','Get-SecretInfo','Test-SecretVault')\r\n}\r\n<\/code><\/pre>\n<p>The <code>TestVault.Extension<\/code> module is dependent on the <code>TestStoreImplementation.dll<\/code> binary file, which implements the actual store.\nBut this is optional, and a simpler <code>.Extension<\/code> module implementation could implement everything within PowerShell script.\nOne example of this might be a cloud based extension vault that is accessed through PowerShell cmdlets or REST APIs.<\/p>\n<p>For more extension vault module examples, see the <a href=\"https:\/\/github.com\/PowerShell\/SecretManagement\">SecretManagement GitHub repo<\/a>.<\/p>\n<h3>SecretStore Extension Vault<\/h3>\n<p>The <a href=\"https:\/\/github.com\/PowerShell\/SecretStore\">Microsoft.PowerShell.SecretStore<\/a> extension vault module is a secure local store for SecretManagement.\nIt is open source and currently available as a preview version on <a href=\"https:\/\/www.powershellgallery.com\/packages\/Microsoft.PowerShell.SecretStore\/0.5.1-preview1\">PowerShell Gallery<\/a>.\nSecretStore is based on <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/standard\/security\/cross-platform-cryptography\">.NET Core cryptographic APIs<\/a>, and works on all PowerShell supported platforms.\nSecret data is stored at rest in encrypted form on the file system and in memory, and only decrypted when returned to a user request.\nSecretStore works within the scope of the current user, and is configurable.<\/p>\n<p>By default SecretStore is configured to require a password, as this provides the strongest security.\nWhen a password is provided, it remains valid in the current PowerShell session until the <code>PasswordTimeout<\/code> time elapses.\nWhen the password becomes invalid, the store can be configured to prompt the user or otherwise throw an exception.\nThe user can provide the password through an interactive prompt or with the <code>Unlock-SecretStore<\/code> cmdlet.\nThe <code>Unlock-SecretStore<\/code> is intended for automation scenarios where user interaction is not possible.<\/p>\n<pre><code class=\"powershell\">PS C:&gt; Get-SecretStoreConfiguration\r\n\r\n      Scope PasswordRequired PasswordTimeout DoNotPrompt\r\n      ----- ---------------- --------------- -----------\r\nCurrentUser             True             900       False\r\n<\/code><\/pre>\n<p>SecretStore can be configured to not require a password, but will be less secure.\nSecrets are still encrypted on file and in memory.\nBut the encryption key is stored on file and protected only by the platform file system.\nIt is strongly encouraged that SecretStore be configured to require a password.<\/p>\n<p>The following cmdlets are provided to manage SecretStore:<\/p>\n<ul>\n<li>Get-SecretStoreConfiguration<\/li>\n<li>Set-SecretStoreConfiguration<\/li>\n<li>Unlock-SecretStore<\/li>\n<li>Update-SecretStorePassword<\/li>\n<li>Reset-SecretStore<\/li>\n<\/ul>\n<p>Paul Higinbotham<\/br>\nPowerShell Team<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Design changes to SecretManagement module preview<\/p>\n","protected":false},"author":7325,"featured_media":13641,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[3174],"class_list":["post-18562","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-powershell","tag-secretmanagement"],"acf":[],"blog_post_summary":"<p>Design changes to SecretManagement module preview<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/18562","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/users\/7325"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/comments?post=18562"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/18562\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/media\/13641"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/media?parent=18562"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/categories?post=18562"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/tags?post=18562"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}