I have written about authenticating with the Pure1 REST API, and my PowerShell module in the past:
https://www.codyhosterman.com/2019/01/using-the-pure1-rest-api-part-i-powershell/
NOTE: This workaround is not really needed anymore with the default behavior of the module. See this post: https://www.codyhosterman.com/2019/12/pure1-rest-api-authentication-made-easy/
One of the issues is that if you followed my default instructions, you would need to run the PowerShell window as an admin to be able to create the connection. The answer–now that I think about it is fairly obvious: non-admin users (or admins not running in admin mode) don’t have security rights to it. Duh!
The internal method used in the cmdlet is GetRSAPrivateKey:
You will see a cryptic error: “Exception calling “GetRSAPrivateKey” with “1” argument(s): “Invalid provider type specified.”
So a couple ways to fix this.
MMC
First in the GUI. Launch MMC, and add/remove snapin and choose certificates. Depending on where your cert is dictates which one you choose. My cert is stored in the personal folder on the local machine group:
Cert:\LocalMachine\my\6D75482829CBDB7FCF8AADD193A71BB4299AC1BD
You can see my cert here:
So right-click and choose Properties > Manage Private Keys…
Click Add then add the user you want to be able to access the private key.
It defaults to full control, but you do not need that, you can just give read access if you prefer:
Now you can run it without being in admin mode:
PowerShell
If you want to do this in PowerShell, it is fairly simple too. This part does need to be run as admin! But once done, the Pure1 module can be run as a regular user.
Grab your cert:
$CertObj= Get-ChildItem Cert:\LocalMachine\my\6D75482829CBDB7FCF8AADD193A71BB4299AC1BD
Pull out the key:
$rsaCert = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($CertObj)
Then grab the permissions of the key:
$fileName = $rsaCert.key.UniqueName $path = "$env:ALLUSERSPROFILE\Microsoft\Crypto\Keys\$fileName" $permissions = Get-Acl -Path $path
Now create the permission. In this case the username is “cody” and I want to provide “read” permissions:
$rule = new-object security.accesscontrol.filesystemaccessrule "cody", "read", allow
Now apply the new permission:
$permissions.AddAccessRule($rule) Set-Acl -Path $path -AclObject $permissions
All good now!
I appreciate your post. This helped me a ton, but was ultimately incomplete.
I think you’re missing a variable in your powershell script. You reference $rsaCert but never define it. It should be:
$rsaCert = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($CertObj)
Oops I dont know how I screwed that up. Or how no one has called me on it yet… Thanks!!
Very elegant script.
My file path was slightly different to the unique file:
$env:\ALLUSERSPROFILE\Microsoft\Crypto\RSA\MachineKeys\$fileName.
very cool script, thank you.
On Windows server 2016 Core I have got stuck:
PS C:\Users\user1> $permissions = Get-Acl -Path $path
Get-Acl : Cannot find path
‘C:\ProgramData\Microsoft\Crypto\Keys\a21bcefc54bc606d7991d5cc3092f26a_68d2a3f4-d951-404c-a8d1-4f9fce5b3323’ because
it does not exist.
At line:1 char:16
+ $permissions = Get-Acl -Path $path
+ ~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (:) [Get-Acl], ItemNotFoundException
+ FullyQualifiedErrorId : GetAcl_PathNotFound_Exception,Microsoft.PowerShell.Commands.GetAclCommand
PS C:\Users\user1> $filename
a21bcefc54bc606d7991d5cc3092f26a_68d2a3f4-d951-404c-a8d1-4f9fce5b3323
PS C:\Users\user1> $Path
C:\ProgramData\Microsoft\Crypto\Keys\a21bcefc54bc606d7991d5cc3092f26a_68d2a3f4-d951-404c-a8d1-4f9fce5b3323
Very Helpful script. Thank you.
I am getting an error for the following line:
$rsaCert = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($CertObj)
The error is :
Cannot convert argument “certificate”, with value: “624F8DDDA7B85966DE276B65DAFAE616BC63E4BD”, for “GetRSAPrivateKey”
to type “System.Security.Cryptography.X509Certificates.X509Certificate2”: “Cannot convert value
“” to type “System.Security.Cryptography.X509Certificates.X509Certificate2”.
Error: “The system cannot find the file specified.
Any ideas?
At first glance it looks like your $certObj doesnt actually store the cert object but just the string value.
Cody, I should mention that I tested your script successfully using a PowerShell-created self-signed certificate on Windows 10. Works like a champ. On Windows Server 2012 R2 and a PFX-formatted certificate from our CA, I get the “cannot convert value” error.
Problem Solved. I was borrowing code from a previous line where I was actually grabbing the Thumbprint. So the error stems from the fact that I was calling Get-RSAPrivateKey with the thumbprint instead of the entire certificate object.
Once I removed the extra “| Select -ExpandProperty Thumbprint” from the “$CertObj = ” line, the error cleared. Thank You for the script.
Ah yeah that will just pull the string of the thumbprint. Glad it worked!
Thanks so much, this was very helpful!
I also had to change the path to $env:\ALLUSERSPROFILE\Microsoft\Crypto\RSA\MachineKeys\$fileName.
I think the best is to use this :
$File = get-childitem “C:\ProgramData\Microsoft\Crypto\” -Recurse $rsaCert.key.UniqueName
$ACL = $file | get-acl
Hello Cody, thank you so much for this detailed article!
One observation after following the flow: when you say “So right-click and choose Properties > Manage Private Keys…” it should be “So right-click and choose All Tasks > Manage Private Keys…”. It took me a bit to figure it out hehe
Thanks again!