vCO PowerShell Plugin: Import-CliXml fails with System.Security.Cryptography.CryptographicException

When using the PowerShell plugin for vCenter Orchestrator (vCO) you might receive a ‘System.Security.Cryptography.CryptographicException’ exception when using ‘Import-CliXml’ with a PSCredential object. Furthermore, you might get the message: ‘The requested operation cannot be completed. The computer must be trusted for delegation and the current user account must be configured to allow delegation’.
The reason behind this seems that the security token of the user running in the PowerShell session is constrained and thus cannot implicitly decrypt the password in the credential object. Though it might be possible to configure delegation, I fonud in most of the cases this is not a viable approach. Instead I recommend to use a static password to decrypt and encrypt the credentials. That static password then might be saved in a Configuration DB entry within vCO and passed on to the PowerShell script to be executed.

Within the PowerShell script you would then use that password to decrypt the actual password and convert the resulting object to a proper PSCredential object. I therefore created two Cmdlets that mimic the behaviour of Import-CliXml and Export-CliXml and accept an additional parameter for the static decryption key (‘KeyPhrase’). If you omit a ‘KeyPhrase’ if behaves just like the normal ‘Import-CliXml’:

function Import-Credential{
  [CmdletBinding(
    SupportsShouldProcess=$true,
    ConfirmImpact="Low",
  HelpURI='http://dfch.biz/PS/System/Utilities/Export-Credential/'
    )]
Param(
  [Parameter(Mandatory = $true, ValueFromPipeline = $True, Position = 0)]
  [string] $Path
  ,
  [Parameter(Mandatory = $false, Position = 1)]
  [string] $KeyPhrase = [NullString]::Value
  )

[Boolean] $fReturn = $false;
$OutputParameter = $null;
try {

  # Parameter validation
  # N/A
  if($PSCmdlet.ShouldProcess($Path)) {
    $Credential = Import-CliXml $Path;
    if($KeyPhrase) {
      $KeyPhrase = $KeyPhrase.PadRight(32, '0').Substring(0, 32);
      $Enc = [System.Text.Encoding]::UTF8;
      $k = $Enc.GetBytes($KeyPhrase);
      
      $Credential.Password = $Credential.Password | ConvertTo-SecureString -Key $k;
      $Credential = New-Object System.Management.Automation.PSCredential(
        $Credential.Username, $Credential.Password);
    } else {
      $Credential = Import-CliXml $Path;
    } # if
    $fReturn = $true;
    $OutputParameter = $Credential;
  } # if

} # try
catch {
  # ...
} # catch
finally {
  # ...
} # finally
return $OutputParameter;

} # Import-Credential

To encrypt you call the following Cmdlet with a ‘KeyPhrase’:

function Export-Credential{
  [CmdletBinding(
  SupportsShouldProcess=$true,
  onfirmImpact="Low",
  HelpURI='http://dfch.biz/PS/System/Utilities/Export-Credential/'
  )]
Param(
  [Parameter(Mandatory = $true, Position = 0)]
  [string] $Path
  ,
  [Parameter(Mandatory = $true, ValueFromPipeline = $True, Position = 1)]
  [Alias('Credential')]
  [PSCredential] $InputObject
  ,
  [Parameter(Mandatory = $false, Position = 2)]
  [string] $KeyPhrase = [NullString]::Value
  )

[Boolean] $fReturn = $false;
$OutputParameter = $null;
try {

  # Parameter validation
  # N/A
  if($KeyPhrase) {
    Log-Debug $fn ("Creating KeyPattern from Keyphrase ...");
    $KeyPhrase = $KeyPhrase.PadRight(32, '0').Substring(0, 32);
    $Enc = [System.Text.Encoding]::UTF8;
    $k = $Enc.GetBytes($KeyPhrase);
    
    Log-Debug $fn ("Encrypting password  ...");
    $Cred = Select-Object -Property '*' -InputObject $InputObject;
    $Cred.Password = ConvertFrom-SecureString -SecureString $Cred.Password -Key $k;
  } else {
    $Cred = $InputObject;
  } # if
  if($PSCmdlet.ShouldProcess( ("Cred.Username '{0}' to '{1}'" -f $Cred.Username, $Path) )) {
    Log-Debug $fn ("Saving PSCredential ...");
    $OutputParameter = Export-CliXml -Path $Path -InputObject $Cred -WhatIf:$false -Confirm:$false;
    $fReturn = $true;
  } # if
  
} # try
catch {
  # ...
} # catch
finally {
  # ...
} # finally
return $OutputParameter;

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: