Search code examples
c#.netpowershellx509certificate2

Remotely push PFX Cert and Private Key with .NET and Powershell


The task at hand is to push a certificate from a central server to recipient servers. I'm able to leverage the x509certificate2 methods to accomplish the certificate install. Even tho the storage flags direct the add() method to install the private key, it doesn't install it on the remote machine. In the code below, please trust that $CertObj is a x509certificate2 object created with the storage flags Exportable, MachineKeySet, and PersistKeySet.

Function Import-CertificateObject
{
    Param
    (
        [parameter(mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]
        $Computer
    )

    $CertStore = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Store -ArgumentList "\\$($Computer)\$Location",$Store
    $CertStore.Open("ReadWrite")
    $CertStore.Add($CertObj)
    $CertStore.Close()

}

Using powershell to isolate the installed certificate object I can see that the HasPrivateKey property has been set to true. This is the case when the installed certificate is inspected locally on the server and from the remote server which installed it. Next, if you inspect the PrivateKey property from server which had the certificate installed, it's blank. However, when inspected from the server which installed it, powershell returns object data for the private key.

Using ProcMon I could see that when the certificate is installing the regkey's for the private key it's doing so on the server which is performing the install on the remote server. I need .Net to install the certificate private key on the remote machine. I've read over the x509certificate2 docs but it doesn't touch on remote installs at all, nor is there an in depth explanation as to what these methods do.

I'm hoping it's as simple as changing an environment variable before the add() method, or maybe I've just totally approached this from the wrong angle. So how do I get it to install the private key on the remote server, not the server pushing the cert?


Solution

  • The solution here was to leverage Invoke-Command -ScriptBlock{} to execute the code on the machine locally.