powershellpowershell-4.0powershell-v5.1

Powershell Script not working using Import-Clixml command


I had a script that was working in Powershell 4.0 in Windows Server 2012 R2. Now I installed Windows Server 2016 and I have Powershell V5.1.17134.590.

In my script I have this:

$credFile = "c:\Program Files\Scripts\MyCredentials.xml"
$credentials = Import-Clixml $credFile

return $credentials

This is my MyCredentials.xml:

<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
  <Obj RefId="0">
    <TN RefId="0">
      <T>System.Management.Automation.PSCredential</T>
      <T>System.Object</T>
    </TN>
    <ToString>System.Management.Automation.PSCredential</ToString>
    <Props>
      <S N="UserName">corp\tfsservice</S>
      <SS N="Password">01000000d08c9ddf0115d1118c7a00c04fc297eb01000000f64c30e2720cc64c970ed0d8972b88400000000002000000000003660000c000000010000000bd0a6bf0e5025f1ae6ba8d5b9637db0400000000048</SS>
    </Props>
  </Obj>
</Objs>

Now I am confused because in my old machine (windows server 2012 R2) when I run the script I got this:

enter image description here

As you can see the command is run with success.

However in my Windows Server 2016 machine when I run the same script i get this:

enter image description here

I don't understand why is this not working now.

Can anyone help me?


Solution

  • As Mathias R. Jenssen commented, *-CliXml is using DPAPI which ties encryption key management to specific user account on specific computer.

    To work around the issue, encryption key needs to be managed. Now there's a problem of key management. It's needed for decrypting, but anyone with the key can see the secrets. This is a well-known problem in encryption. Anyway, for a quick solution see an article on web. In case of link rot, let's see the code:

    # Pre-generate a key and save it for later use.
    $Key = New-Object Byte[] 32
    [Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($Key)
    $Key | out-file C:\passwords\aes.key
    # Copy the key file into remote computer
    
    # Get a credential and use pre-generated key for encryption
    # Save the encrypted password on a file
    (get-credential).Password | ConvertFrom-SecureString -key (get-content C:\passwords\aes.key) | set-content "C:\Passwords\password.txt"
    # Copy the password file into remote computer
    
    # On remote computer, read the key from file
    # and decrypt the password file too. 
    # Generate a SecureString and credential object
    $password = Get-Content C:\Passwords\password.txt | ConvertTo-SecureString -Key (Get-Content C:\Passwords\aes.key)
    $credential = New-Object System.Management.Automation.PsCredential("Luke",$password)