Sometimes I do things in PowerShell just to see what happens. This is a great way to learn about new cmdlets and techniques. Sometimes these experiments lead to useful results. Other times they may end up as teaching devices. Of course the result could serve both purposes and you may have to decide that today as I look at storing credentials in a JSON file.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
Since the early days of PowerShell we've preached the perils of hard-coding credentials in your scripts. If you need a password you should prompt for it, or write your PowerShell tool to accept a credential object. But there may be situations where you need to automate a process AND use an alternate or specific credential. One approach is to use the cliXML cmdlets to securely store a credential.
$secure = ConvertTo-SecureString -String 'P@$$w0rd' -AsPlainText -Force $cred = New-Object -typename PSCredential -ArgumentList @('company\admin',$secure) $cred | Export-clixml c:\work\admin.xml
I manually created a credential so you could see the password. When you use Export-Clixml PowerShell automatically converts the secure string password.
The password is encrypted using native crypto APIs. You can only reverse the process on the same computer.
$in = Import-clixml C:\work\admin.xml
If I copy the file to another computer and try the process I'll get an error.
Oh, and to prove the import worked locally:
But what if, for some reason, you wanted to use a JSON file for the stored credential? How would you do it?
PowerShell won't automatically insert the conversion steps, but they aren't that difficult to implement yourself. First, you have to select the username and convert the password back from a secure string.
$cred | Select Username,@{Name="Password";Expression = { $_.password | ConvertFrom-SecureString }}
This object can now be piped to Convertto-Json:
This cmdlet doesn't create a file so you will need to pipe to Out-File or Set-Content.
One slight advantage of json over XML is that the file overhead is smaller.
But now let's see about brining it back to life. First, convert the content from JSON.
$in = Get-Content -Path c:\work\admin.json | ConvertFrom-Json
Next, convert the password value back to a secure string.
$secure = ConvertTo-SecureString $in.Password -ErrorAction Stop
Finally, create a credential object.
$newcred = New-Object -TypeName PSCredential $in.username,$secure
The whole process is really not that cumbersome, but I went ahead and created a PowerShell module called PSJsonCredential.
The module has commands for exporting, importing and reporting.
Export-PSCredentialToJson -Path c:\work\admin.json -Credential $cred
This command also has a -NoClobber parameter to avoid overwriting an existing file. I also added a metadata property to indicate who, where and when. You can get this data with Get-PSCredentialFromJson:
The import command can ignore the metadata.
$admin = Import-PSCredentialFromJson -Path C:\work\admin.json
I've published the module to the PowerShell gallery if you would like to try it out or look more closely at the code.
As I mentioned at the beginning, this module is hardly groundbreaking and may have no practical use. But at the very least it might offer some insights into working with credentials and JSON files.
Note that storing a credential in *any* form to disk is a potential security risk and may not be allowed in some organizations. It is up to you to determine how suitable these techniques are in your company.
I hope you'll let me know what you think and especially if you find a practical application.
Thanks Jeff for a nice post as usual. I’ve tried it, and as expected, the credentials don’t carry over from one computer to another, whether they’re saved as JSON or XML..
That’s why they are secure strings! But always good to test and see for yourself.
So this can be encrypted by ANY user on THIS computer or can be decrypted only THIS user on THIS computer?
That’s the way secure strings work but you should test to verify.
Nice work Jeff,
Does using JSON also have the added benefit over XML of being able to retrieve the credentials if copied to another system?
Thanks,
Jim
No. The encrypted password can only be decrypted on the original server. JSON is just the format.
No. This is still storing an encrypted secure string that can only be decrypted on the original server.