none
DSC secure credentials - client error - "The private key could not be acquired." RRS feed

  • Question

  • I'm trying to use DSC (based on WMF 5.1) with secured credentials to access network resources to deploy software.    This is an on-prem vm, not an Azure instance.

    The pull server is a Win2012R2 server.  The Client server is a Win2008R2 server.

    My client registers with the pull server, and downloads its config, but is unable to process all the stages due to this "The private key could not be acquired" error  and the overall status of the configuration ends up as failure.  What is weird though is that although the stages fail, they're all showing up as being in the desired state (perhaps thats a second issue - I'll worry about that later).

    I have a cert loaded into Cert:\LocalMachine\My on both the pull server and client, and an admin user can access it.  I'm not sure how to prove that the SYSTEM user can access it.  (DSCPullServer in the following block is actually a FQDN - I've changed it for public posting)

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

    The certificate was created on the pull server using the following script, and deployed to the client:

    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

    It was imported into the Win2008R2 client using

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


    And the cert can be found on the client using the above PS code.

    The pull server is encrypting the credentials into the client's MOF multiple times as "instance of MSFT_Credential as $MSFT_Credential(n)ref" and this is referenced in multiple resource references inside the MOF on the pull server.  The MOF includes a configuration block for the LocalConfigurationManager and a meta file is also produced with the certificate thumbprint.

    The client is registered using the following script:

    #Server to configure for
    $hostname = $env:COMPUTERNAME + "." + $env:USERDNSDOMAIN
    
    #pull server to configure against
    $pullServer = "---FQDN of Pull server---"
    
    #Certificate CN that restricts to the certificate to be used for encryption
    $encryCertCN = "CN=$($pullServer)"
    
    #DSC Registration key - without this, the DSC server wont let you in
    $regkey = "--guid for registration--"
    
    # Get the certificate that works for encryption 
    function Get-LocalEncryptionCertificateThumbprint 
    { 
        (dir Cert:\LocalMachine\my) | %{ 
            If (($_.Issuer -eq $encryCertCN ) -and ($_.Subject -eq $encryCertCN )  )
            { 
                return $_.Thumbprint 
            } 
        } 
    }
    
    [DscLocalConfigurationManager()]
    Configuration RegistrationMetaConfig
    {
        Node localhost
        {
            Settings
            {
                ActionafterReboot="ContinueConfiguration";
                AllowModuleOverwrite  = $true;
                CertificateID = Get-LocalEncryptionCertificateThumbprint
                ConfigurationMode = "ApplyAndAutocorrect";
                ConfigurationModeFrequencyMins = 15;
                RebootNodeIfNeeded = $true;
                RefreshFrequencyMins = 30;
                RefreshMode = "Pull";
            }
    
            ConfigurationRepositoryWeb ConfigurationManager
            {
                ServerURL = "https://$($pullServer):8080/PSDSCPullServer.svc"
                RegistrationKey = $regkey  
                ConfigurationNames = @($hostname)
    
            }
    
            ReportServerWeb DSCPull
            {
                ServerURL = "https://$($pullServer):8080/PSDSCPullServer.svc"
                RegistrationKey = $regkey
            }
    
        }
    
    }
    
    
            $ConfigData= @{ 
                AllNodes = @(     
                            @{  
                                # Common to all nodes
                                NodeName = "*"
    
                                # The path to the .cer file containing the 
                                # public key of the Encryption Certificate 
                                # used to encrypt credentials for this node 
                                CertificateFile = "C:\DSC\DscPublicKey.cer"
    
    
                                # The thumbprint of the Encryption Certificate 
                                # used to decrypt the credentials on target node 
                                Thumbprint = 'A64EA0C88D6B5026D98E1B09AAB3C4AE1739DB85'
                            }
                        )
                     }
    
    Write-Host "Disabling DSC Debug"
    Disable-DscDebug
    
    Write-Host "Removing current DSC config"
    Remove-DscConfigurationDocument -Stage Current, Pending, Previous -Verbose
    
    Write-Host "Creating new DSC Config" 
    RegistrationMetaConfig -ConfigurationData $ConfigData -OutputPath C:\DSC -Verbose
    
    Write-Host "Configuring LCM to use new config"
    Set-DscLocalConfigurationManager -ComputerName localhost -Path C:\DSC -Verbose -Force
    
    Write-Host "Start DSC Configuration"
    Start-DSCConfiguration -ComputerName localhost.meta -Path C:\DSC -Verbose 
    

    and I can see its trying to converge the configuration, but it fails

    PS C:\Windows\system32> Get-DscConfigurationStatus
    
    Status     StartDate                 Type            Mode  RebootRequested      NumberOfResources             
    ------     ---------                 ----            ----  ---------------      -----------------             
    Failure    2/7/2017 12:30:01 PM      Consistency     Pull  False                4                             
    
    
    

    The Thumbprint that is reported in the log does match the certificate that I'm expecting - but for some reason, LCM is unable to obtain the key.

    I'm hoping someone can point me to what I'm missing....

    Tuesday, February 7, 2017 5:53 PM

All replies

  • Some more information - which I'm finding confusing.

    I added xDscDiagnostics and found the following issue:

    EventType    : ERROR
    TimeCreated  : 2/7/2017 12:44:07 PM
    Message      : Message Cannot load encryption certificate. The certificate setting 'A64EA0C88D6B5026D98E1B09AAB3C4AE1739DB85' does not represent a valid base-64 
                   encoded certificate, nor does it represent a valid certificate by file, directory, thumbprint, or subject name. 
                   HResult -2146233087 
                   StackTrack    at System.Management.Automation.Runspaces.PipelineBase.Invoke(IEnumerable input)
                      at System.Management.Automation.PowerShell.Worker.ConstructPipelineAndDoWork(Runspace rs, Boolean performSyncInvoke)
                      at System.Management.Automation.PowerShell.Worker.CreateRunspaceIfNeededAndDoWork(Runspace rsToUse, Boolean isSync)
                      at System.Management.Automation.PowerShell.CoreInvokeHelper[TInput,TOutput](PSDataCollection`1 input, PSDataCollection`1 output, 
                   PSInvocationSettings settings)
                      at System.Management.Automation.PowerShell.CoreInvoke[TInput,TOutput](PSDataCollection`1 input, PSDataCollection`1 output, 
                   PSInvocationSettings settings)
                      at System.Management.Automation.PowerShell.CoreInvoke[TOutput](IEnumerable input, PSDataCollection`1 output, PSInvocationSettings settings)
                      at System.Management.Automation.PowerShell.Invoke[T](IEnumerable input, IList`1 output, PSInvocationSettings settings)
                      at System.Management.Automation.PowerShell.Invoke[T](IEnumerable input, PSInvocationSettings settings)
                      at Microsoft.PowerShell.DesiredStateConfiguration.Internal.ResourceProviderAdapter.CMS_DecryptMessage(String thumbprint, String 
                   encryptedMessage, IStreamsHandler plugInStreamsHandler, String& outputResult, IntPtr& errorInstanceHandle)
    ComputerName : -------------
    JobID        : 04f9bcf3-ed5d-11e6-8a11-0050569272c7
    SequenceID   : 10
    Event        : System.Diagnostics.Eventing.Reader.EventLogRecord

    It complains that its not a valid cert "...by file, dfirectory, thumbprint or subjectname...", however, the cert does exist, as I can do this:

    PS C:\Windows\system32> dir Cert:\LocalMachine\my | %{if ($_.Thumbprint -eq "A64EA0C88D6B5026D98E1B09AAB3C4AE1739DB85") {Write-Host $_.Thumbprint }}
    A64EA0C88D6B5026D98E1B09AAB3C4AE1739DB85

    and you see, it shows the cert thumbprint....

    Is this a permissions problem, or a more generic issue where the DSC user simply can not see the certificate in Cert:\LocalMachine\My ??

    Tuesday, February 7, 2017 6:32 PM
  • Hi JScottBrown

    I have a similar problem, did you find a solution?

    Friday, February 17, 2017 3:24 PM
  • Based on my question on StackOverflow ( http://stackoverflow.com/questions/42033834/dsc-client-error-the-private-key-could-not-be-aquired/42150738#42150738 ) , I seem to have all the pieces together, but I'm now getting a Decoding error that I cant figure out

    Job {506A66C9-F47E-11E6-8A11-0050569272C7} : 
    Message The enveloped-data message does not contain the specified recipient.
     
    HResult -2146233087 
    StackTrack    at System.Management.Automation.Runspaces.PipelineBase.Invoke(IEnumerable input)
       at System.Management.Automation.PowerShell.Worker.ConstructPipelineAndDoWork(Runspace rs, Boolean performSyncInvoke)
       at System.Management.Automation.PowerShell.Worker.CreateRunspaceIfNeededAndDoWork(Runspace rsToUse, Boolean isSync)
       at System.Management.Automation.PowerShell.CoreInvokeHelper[TInput,TOutput](PSDataCollection`1 input, PSDataCollection`1 output, PSInvocationSettings settings)
       at System.Management.Automation.PowerShell.CoreInvoke[TInput,TOutput](PSDataCollection`1 input, PSDataCollection`1 output, PSInvocationSettings settings)
       at System.Management.Automation.PowerShell.CoreInvoke[TOutput](IEnumerable input, PSDataCollection`1 output, PSInvocationSettings settings)
       at System.Management.Automation.PowerShell.Invoke[T](IEnumerable input, IList`1 output, PSInvocationSettings settings)
       at System.Management.Automation.PowerShell.Invoke[T](IEnumerable input, PSInvocationSettings settings)
       at Microsoft.PowerShell.DesiredStateConfiguration.Internal.ResourceProviderAdapter.CMS_DecryptMessage(String thumbprint, String encryptedMessage, IStreamsHandler plugInStreamsHandler, String& outputResult, IntPtr& errorInstanceHandle)
    Job {506A66C9-F47E-11E6-8A11-0050569272C7} : 
    MIResult: 1
    Error Message: Decryption failed.
    Message ID: Windows System Error 13
    Error Category: 6
    Error Code: 13
    Error Type: WIN32

    I've changed out the cert I'm using, and I can find the cert in the Cert:\LocalMachnine\My store, and it meets KeyExchange and validity requirements

        (dir Cert:\LocalMachine\My) | %{
            # Verify the certificate is for Encryption and valid 
            If ($_.PrivateKey.KeyExchangeAlgorithm -and ($_.Verify )  )
            { 
                Write-Output "Thumbprint $($_.Thumbprint)"
    
            } 
        } 
    Thumbprint EB55B9898CC5D47A4EBC47A86D72F24ED47732AD
    Thumbprint C1A7A70FEFB5EF42255BB12E4C8F83C6E71362A9
    Thumbprint A64EA0C88D6B5026D98E1B09AAB3C4AE1739DB85
    Thumbprint 34E8C7B9EBD52898E4E887C54B3B3783BEEA87FD
    (I have a set of certs installed which meet the criteria now... but my LCM is configured to specify C1A... 

    ActionAfterReboot              : ContinueConfiguration
    AgentId                        : 7B72DB65-A2A2-11E6-A42D-0050569272C7
    AllowModuleOverWrite           : True
    CertificateID                  : C1A7A70FEFB5EF42255BB12E4C8F83C6E71362A9
    ConfigurationDownloadManagers  : {[ConfigurationRepositoryWeb]ConfigurationManager}
    ConfigurationID                : 
    ConfigurationMode              : ApplyAndAutoCorrect
    ConfigurationModeFrequencyMins : 15
    Credential                     : 
    DebugMode                      : {NONE}
    DownloadManagerCustomData      : 
    DownloadManagerName            : 
    LCMCompatibleVersions          : {1.0, 2.0}
    LCMState                       : PendingConfiguration
    LCMStateDetail                 : 
    LCMVersion                     : 2.0
    StatusRetentionTimeInDays      : 10
    SignatureValidationPolicy      : NONE
    SignatureValidations           : {}
    MaximumDownloadSizeMB          : 500
    PartialConfigurations          : 
    RebootNodeIfNeeded             : True
    RefreshFrequencyMins           : 30
    RefreshMode                    : Pull
    ReportManagers                 : {}
    ResourceModuleManagers         : {}
    PSComputerName                 : 

    To me, this is pointing back to the cert itself.. but i'm not a crypto person... and my go-to-guy is off right now.

    Friday, February 17, 2017 3:55 PM
  • Thanks for this information. However I gave up and changed to recommended "Method 1" that is - create certificates on all Target Nodes. This works for me (https://msdn.microsoft.com/en-us/powershell/dsc/securemof#creating-the-certificate-on-the-target-node).
    • Edited by Przlwo Friday, February 17, 2017 6:13 PM add url
    Friday, February 17, 2017 6:11 PM
  • Logistically, that is a problem for me - I have 200+ nodes (and growing) to manage, and managing a cert/key for each....  

    Method 2, if it worked, would solve that nightmare

    Tuesday, February 21, 2017 4:01 PM
  • I need to give you an update about the Method 2. I send you previous information when I run this configuration by Powershell ISE. Next day I tried by standard Powershell console and this option didn't work. This is crazy but exactly the same ps1 file works perfect when it's being run by PS ISE but does not work in case of the standard console....nightmare

    I tried to get some help but still don't know how to solve the issue.

    https://powershell.org/forums/topic/powershell-ise-vs-console-dsc-executing/#post-64807

    http://stackoverflow.com/questions/42348286/dsc-desired-state-configuration


    • Edited by Przlwo Tuesday, February 21, 2017 6:50 PM
    Tuesday, February 21, 2017 6:50 PM