The_Gribbler
The_Gribbler

Reputation: 21

Import PFX Certificate into separate CurrentUser - Personal store (PowerShell)

I've been wrapping my head around automating a way to perform this task:

We deploy Windows Server 2008 R2 images for our customers. We use PowerShell (version 2) to deploy our proprietary software and make various other changes to the system before shipping. This PowerShell process is run under the local Administrator account until it finishes and disables the local Administrator account.

Now, to the issue - I'm trying to install a .PFX client certificate to a SEPARATE user's CurrentUser\My certificate store. Let's call that user "SQL".

Right now the certificate is getting installed under the LocalMachine\My certificate store but one of our development teams have concerns on that position and would like to replicate the original setup.

Now, I know how to get this done dirty by adding in a reboot-step to our deployment script and having this performed under the "SQL" user but I would like to avoid that as it seems like there has to be a way to get this done while under another account. Here's the basic code we're using now to install the certificate to the LocalMachine\My store. Assume $certPath is the path to the .pfx and $pfxPass is the .pfx's password.

function Import-PfxCertificate {
param([string] $certPath, [string]$pfxPass)

$pfx = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$pfx.Import([string]$certPath, [string]$pfxPass, "Exportable,PersistKeySet")

$store = New-Object System.Security.Cryptography.X509Certificates.X509Store("My", "LocalMachine")
$store.open("MaxAllowed")
$store.add($pfx)
$store.close()
}    

Upvotes: 2

Views: 3170

Answers (1)

briantist
briantist

Reputation: 47872

Since you have the credentials, I would start use Start-Job to do it. You can use the -Credential parameter to control what user the job runs as.

$cred = Get-Credential

$scriptBlock = [ScriptBlock]::Create((Get-Item Function:\Import-PfxCertificate).Definition)

$job = Start-Job -ScriptBlock $scriptBlock -ArgumentList $path,$password -Credential $cred
$job | Wait-Job 
$job | Receive-Job # if you want the output
$job | Remove-Job

Since you've already defined a function that does what you want, I'm creating a script block out of the function and using that for Start-Job. -ArgumentList is how you pass the parameters for the PFX path and the PFX password. I'm using Get-Credential to prompt you for the runas user, but you can provide the credential object however you want.

I think the easiest way is to run something like this:

Get-Credential | Export-Clixml -Path C:\path\to\credentials.xml

This will store the credential object in a way that is encrypted, and can only be decrypted by the same user on the same computer that encrypted it. To read it back in:

$cred = Import-Clixml -Path C:\path\to\credentials.xml

Back to the other code snippet, Wait-Job waits for it to finish. Receive-Job is optional, in case you're returning anything useful from your function.

Remove-Job removes it from the job list (otherwise it sticks around, which you can see with Get-Job).

Upvotes: 3

Related Questions