DSC problems with Credentials and build 10586

2019-07-13 05:16发布

问题:

The latest windows 10 build pushed out an updated version of powershell (10586).

In addition to the change required for the certificate documented at https://dscottraynsford.wordpress.com/2015/11/15/windows-10-build-10586-powershell-problems/ i seem to have an additional problem, while trying to apply the configuration:

WarningMessage An error occured while applying the partial configuration [PartialConfiguration]ExternalIntegrationConfiguration. The error message is : Decryption failed..

Using the same certificate I can successfully create a MOF with build 10.0.10240.16384 , and successfully apply it. So looking at the difference between the two MOFs I see that the MOF built by build 10586 looks like:

instance of MSFT_Credential as $MSFT_Credential6ref
{
Password = "-----BEGIN CMS-----
    \nBase64 encrypted
\n-----END CMS-----";
UserName = "SomeUser";
};

instead of what it used to be like in build (10.0.10240.16384):

instance of MSFT_Credential as $MSFT_Credential6ref
{
Password = "Base64 encrypted";
UserName = "SomeUser";
};

So the content is different. I did check to see whether I could decrypt the credential using Get-CmsMessage and unprotect-CmsMessage, and I could. So the public/private key stuff appears to be good.

Should there be an update to the machine that the configuration is being applied to? I don't see any new powershell build.

Any ideas would be appreciated.

回答1:

Update 2015-12-18: Installing Windows Management Framework (WMF) 5.0 RTM edition that was released 2015-12-17 on the nodes being configured will resolve this error. WMF 5.0 can be downloaded here.

MS has changed the Get-EncryptedPassword function in the PSDesiredStateConfiguration to generate the new format for Password field in a MOF. This prevents DSC nodes from decrypting the password if WMF has not been upgraded to support it. But as MS has not released an update to allow WMF to read this new format then this should be considered a completely broken release.

I have managed to find a work around: Copy the PSDesiredStateConfiguration module from a pre 10586 machine (e.g. Windows Server 2012 R2 with latest WMF 5.0) to the PowerShell modules folder on the Built 10586 machine.

E.g. Replace the C:\Windows\System32\WindowsPowerShell\v1.0\Modules\PSDesiredStateConfiguration folder with an older version

Note: You'll need to take ownership of this folder and give yourself permission to write into it because by default only TrustedInstaller can write to this folder.

As far as I'm concerned this version of PSDesiredStateConfiguration is completely broken and you're better off rolling it back until MS can fix it. This will also fix some other reported problems (module versions, new certificate Policy requirements).

FYI, here is the changed code that changes the credential encryption:

Old code in PSDesiredStateConfiguration.psm1:

    # Cast the public key correctly
    $rsaProvider = [System.Security.Cryptography.RSACryptoServiceProvider]$cert.PublicKey.Key

    # Convert to a byte array
    $keybytes = [System.Text.Encoding]::UNICODE.GetBytes($Value)

    # Add a null terminator to the byte array
    $keybytes += 0
    $keybytes += 0

    try
    {
        # Encrypt using the public key
        $encbytes = $rsaProvider.Encrypt($keybytes, $false)

        # Reverse bytes for unmanaged decryption
        [Array]::Reverse($encbytes)

        # Return a string
        [Convert]::ToBase64String($encbytes)
    }
    catch
    {
        if($node)
        {
            $errorMessage = $LocalizedData.PasswordTooLong -f $node
        }
        else
        {
            $errorMessage = $LocalizedData.PasswordTooLong -f 'localhost'
        }

        $exception = New-Object -TypeName System.InvalidOperationException -ArgumentList $errorMessage
        Write-Error -Exception $exception -Message $errorMessage -Category InvalidOperation -ErrorId PasswordTooLong
        Update-ConfigurationErrorCount
    }

New code in PSDesiredStateConfiguration.psm1:

    # Encrypt using the public key
    $encMsg =Protect-CmsMessage -To $CmsMessageRecipient -Content $Value

    # Reverse bytes for unmanaged decryption
    #[Array]::Reverse($encbytes)

    #$encMsg = $encMsg -replace '-----BEGIN CMS-----','' 
    #$encMsg = $encMsg -replace "`n",'' 
    #$encMsg = $encMsg -replace '-----END CMS-----','' 

    return $encMsg