Search code examples
sslencryptiondsc

DSC - client error - The private key could not be aquired


I have a Windows 2012R2 DSC Pull server under WMF5 and a Windows 2008R2 client under WMF5.1. Due to the need to access network resources, credentials are encoded into the MOF by the Pull server, and encrypted using a certificate which resides in Cert:\LocalMachine\My

Based on https://msdn.microsoft.com/en-us/powershell/dsc/securemof the Key was created using:

New-SelfsignedCertificateEx `
-Subject "CN=${ENV:ComputerName}.${ENV:UserDnsDomain}" `
-EKU 'Document Encryption' `
-KeyUsage 'KeyEncipherment, DataEncipherment' `
-SAN ${ENV:ComputerName}.${ENV:UserDnsDomain} `
-FriendlyName 'DSC Credential Encryption certificate' `
-Exportable `
-StoreLocation 'LocalMachine' `
-StoreName 'My' `
-KeyLength 2048 `
-ProviderName 'Microsoft Enhanced Cryptographic Provider v1.0' `
-AlgorithmName 'RSA' `
-SignatureAlgorithm 'SHA256' `
-NotBefore $effDate `
-NotAfter $expiryDate

I have exported this cert, and imported it into the client computer, also in Cert:\LocalMachine\My using this command

certutil -addstore My C:\DSC\DscPublicKey.cer

Both machines can find the cert with the following code (run with an interactive admin user)

$Cert =  Get-ChildItem -Path cert:\LocalMachine\My | Where-Object {
    (
        ($_.Issuer -eq $IssuerCN) -and ($_.Subject -eq $IssuerCN)
    )
} 
Write-Host " Thumbprint : " $Cert.Thumbprint

and I can see in the MOF on the Pull server, the encrypted credentials. The encryption seems to be working as intended.

On the client side, the MOF processing log shows an instance of MSFT_DSCMetaConfiguration with the matching CertificateID that was used for encryption, and the LCM was initialized with a function to pull the correct cert.

function Get-LocalEncryptionCertificateThumbprint 
{ 
    (dir Cert:\LocalMachine\my) | %{
        # Verify the certificate is for Encryption and valid 
        If (($_.Issuer -eq $encryCertCN ) -and ($_.Subject -eq $encryCertCN )  )
        { 
            return $_.Thumbprint 
        } 
    } 
}

however, the Get-DSCConfigurationStatus shows a failure status. When I look into the logs, I see the error

Status = "Failure";
Error = "The private key could not be acquired.";

and all my pipeline stages are eventually switched from InDesiredState = False; to being InDesiredState = True; (I'm assuming DSC is doing this to avoid a perpetual attempt at doing something it has no hope of achieving).

At this point my only thought is that the cert on the client side is not in a location that the SYSTEM user can access - but I've not been able to identify this as the cause.

If Cert:\LocalMachine\My is not the correct location - where should the cert be installed?

EDIT:

The certificate is created on the PULL Server and the .CER file exported and manually imported into the target node (for now - eventually to be handled in AD). I have also tried exporting the full PFX and importing it into the target node, with the same result.

At this point, my suspicion is that the cert generated, being self-signed, is insufficient for purpose...


Solution

  • Base on some assumptions, you are creating the cert on the Pull server, including the public and private keys. Then only importing the public key (the .cer file) on the target node. The problem is the Pull Server isn't the machine which needs the private key. The target node needs the private key. The process should look more like this.

    1. Creating the cert on the target node of the configuration, including the public and private keys. See Securing the MOF File - Creating the Certificate on the Target Node.
    2. Exporting the public key
    3. Importing the public key on Pull Server
    4. Compiling the configuration on the Pull Server
    5. Somehow the configuration is running on the target node

    This is considered a bad practice but if you want to have one cert the process would look like this:

    1. Creating the cert on the Pull Server, including the public and private keys. See Securing the MOF File - Creating the Certificate on the Target Node.
    2. Exporting the full cert using Export-PfxCertificate
    3. securely transport the key to the target node (this is usually not done securely and why it is a bad practice)
    4. Importing the pull key on target node of the configuration
    5. Compiling the configuration on the Pull Server
    6. Somehow the configuration is running on the target node