In this article, I want to focus on a cybersecurity topic but from an operations perspective and with a pragmatic approach to tactics that users can implement to implement the security strategy or principles with less friction as possible from the end-users.
Each one of us every single day use at least multiple secrets, passwords, and identities. Modern applications and services will provide identity management (with or without multifactor authentication) and have a form of role-based access control and implementing the least privilege access.
So when we design IT systems we want to provide the best experience to the end-user minimizing friction and to achieve this ideal single-sign-on via federation services or other forms of integrations.
This is a good way of reducing the number of identities and secrets, but for all isolated systems or roles where permissions are decoupled is common practice still to use multiple accounts. The result is that every user will manage if “lucky” just a handful of different usernames and passwords or if you’re a system administrator having access to different environments that can number can grow to hundreds or potentially thousands of different secrets.
The problem of managing secrets is been already solved by password/secret manager solutions a long time ago. Windows has a built-in solution called Credential Manager, MacOs has KeyChain and there a lot of solutions capable of managing your personal vault of secrets or for your entire organization.
But when we deal with automation or even running scripts unattended it means that we need to get secrets from the users of from password managers and this topic is the one I want to dive because of it’s often not even taken into account.
In this scenario, the first approach will be getting familiar with Credential Manager. From the GUI you can access Credential Manager from “Control Panel” and find “Credential Manager”
and even from the command prompt using cmdkey.exe to list all the saved secrets. Most users don’t even know or expect that you can list them from the command prompt or add new one.
1 |
cmdkey.exe /list |
To view the help
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
cmdkey.exe /? Creates, displays, and deletes stored user names and passwords. The syntax of this command is: CMDKEY [{/add | /generic}:targetname {/smartcard | /user:username {/pass{:password}}} | /delete{:targetname | /ras} | /list{:targetname}] Examples: To list available credentials: cmdkey /list cmdkey /list:targetname To create domain credentials: cmdkey /add:targetname /user:username /pass:password cmdkey /add:targetname /user:username /pass cmdkey /add:targetname /user:username cmdkey /add:targetname /smartcard To create generic credentials: The /add switch may be replaced by /generic to create generic credentials To delete existing credentials: cmdkey /delete:targetname To delete RAS credentials: cmdkey /delete /ras |
Why Use Credential Manager?
Most applications (IE, Visual Studio IDE, VS Code, etc..) use Credential Manager to store secrets already so whenever you change your password that is the only place where you need to update the secret.
Having a personal, single and central repository is definitely easier to manage compared to multiple places. It’s built-in, free and just works!
How to access Credential Manager with PowerShell?
There is a Powershell Module from the PowerShell gallery that it’s been largely tested and downloaded (with over 500.000 downloads), big thanks to Dave Garnar for putting his time and effort to develop this module, he’s looking for contributors and if you have a look at the code you’ll find out that is most C# and it’s not a wrapper of cmdkey.exe.
How to install Credential Manager Module?
Let’s start with installing the module first and once we open powershell with admin rights, let’s run this command:
1 2 3 4 5 6 |
PS C:\Windows\system32> install-module credentialmanager Untrusted repository You are installing the modules from an untrusted repository. If you trust this repository, change its InstallationPolicy value by running the Set-PSRepository cmdlet. Are you sure you want to install the modules from 'PSGallery'? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): Y |
How to check if CredentialManager is installed and the new cmd-lets?
The cmd-let included in this new module are basically 3 to Read, Create and Remove secrets from Credential Manager.
1 2 3 4 5 6 7 8 |
PS C:\Windows\system32> get-command -module CredentialManager CommandType Name Version Source ----------- ---- ------- ------ Cmdlet Get-StoredCredential 2.0 CredentialManager Cmdlet Get-StrongPassword 2.0 CredentialManager Cmdlet New-StoredCredential 2.0 CredentialManager Cmdlet Remove-StoredCredential 2.0 CredentialManager |
Not many users I guess use the Get-StrongPassword cmd-let, but that’s a nice bonus to be able to generate a random password, so you can play this to generate a list of password with a one-liner:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
PS C:\Windows\system32> Get-StrongPassword F?%Hb?OLfS PS C:\Windows\system32> 1..10 | %{Get-StrongPassword} !{kdmW;DRJ :C>NSG7bA} n28f0|L=_H t6mPM|$JR* mt(Bs6uz%* +q@;|eIcKY 8X(YG-E5>y gJB?RuA[)u nN7JFR|*I= k[&o97;ss| |
How to check if the Credential for this user (e.g. user@mydomain) is already stored
1 |
Get-StoredCredential -Target user@mydomain |
How to add the new Credential to CredentialManager
1 |
New-StoredCredential -Target "user@mydomain" -UserName "user@mydomain" -Password "PasswordInClearText" |
When can we use this? Give us some examples
- Depending on your role there are unattended scripts that would be useful to run with other user credentials for testing purposes or simply because your user doesn’t have access to that specific environment for instance test or training environment.
- If every user in the organization may have a specific account to access with a separate account a different set of resources the automated/scheduled script will look for the credential in credential manager and if defined will try to run with that identity.
- You can automate password change for some test accounts and store the new secret in the credential manager with a single script on-demand or as a scheduled task.
Wrap up
Having a personal central repository for secrets is very useful and will prevent that users set a simpler / weaker password and avoid the bad habits of sharing the same secret across different accounts or hard-code the secrets in the somewhere in the source code.
In the next article, I will use a centralised secret repository… so if you’re interested I recommend you to keep an eye on scriptinglibrary.com.
I don’t see the follow-on article, “centralised secret repository”. Are you still planning on writing one?
Hi Todd,
There are a lot of drafts and articles which were never completed and can be considered a backlog, that is one of those.
That article was on Hashicorp Vault, but what I’m doing now is a small article on Azure Key Vault, the article will be online in one hour or so.
Regards
the credential disappear as the session closes even if the persistence is set as system any workaround for it ?
Hi Arvy,
Thanks for your comment.
I’m not sure I’ve understood your question, can you please clarify it?
In the meantime, I will try to answer the question anyway.
If your problem is persistence I think that using Credential Manager should solve it.
For instance, if you open 2 distinct PowerShell sessions/windows on the same host with the same user identity.
Let me use a code sample to generate a test where in one session we can create and store a secret and in a second independent session we retrieve it.
In the first PowerShell window you can run:
PS> get-date;hostname;whoami #to make sure your running these agaist the same host, with the same user
New-StoredCredential -Target "user@mydomain" -UserName "user@mydomain" -Password "PasswordInClearText" -Persist LocalMachine
In the second PowerShell window you can run:
PS> get-date;hostname;whoami #to make sure your running these against the same host, with the same user
Get-StoredCredential -Target "user@mydomain"
Pay attention to the -PERSIST parameter of New-StoreCredential. If you look at the documentation the default value is just SESSION, so there is no persistence. But you can also specify LOCAL_MACHINE, ENTERPRISE to survive to logout or reboot.
Keep in mind that Credential Manager is a local repository on your host and each user can just manage his own secrets. If you’re looking for an alternative I can recommend Azure Key Vault, have a look at this article (https://www.scriptinglibrary.com/languages/powershell/secrets-management-with-azure-keyvault-and-powershell/).
Regards,