PoshCode / Metadata

Serialization for the PowerShell metadata format
MIT License
19 stars 2 forks source link

Some objects can't be serialized out of the box #8

Closed DennisL68 closed 8 months ago

DennisL68 commented 8 months ago

When trying to export properties from my Win 10 BitLocker setup, ConvertTo-Metdata fails to convert the datastructure.

$OsBitLockerVolume = Get-BitLockerVolume | where VolumeType -eq OperatingSystem

$OsBitLockerVolume.KeyProtector

KeyProtectorId      : {XXXX}
AutoUnlockProtector :
KeyProtectorType    : RecoveryPassword
KeyFileName         :
RecoveryPassword    : XXXX
KeyCertificateType  :
Thumbprint          :

KeyProtectorId      : {XXXX}
AutoUnlockProtector :
KeyProtectorType    : TpmPin
KeyFileName         :
RecoveryPassword    :
KeyCertificateType  :
Thumbprint          :
$OsBitLockerVolume = Get-BitLockerVolume | where VolumeType -eq OperatingSystem

$OsBitLockerVolume.KeyProtector | ConvertTo-Metadata

WARNING: Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtector is not serializable. Serializing as string
'RecoveryPassword'
WARNING: Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtector is not serializable. Serializing as string
'TpmPin'

where as, ConvertTo-Json will succeed.

$OsBitLockerVolume.KeyProtector | ConvertTo-Json

[
    {
        "KeyProtectorId":  "{XXXX}",
        "AutoUnlockProtector":  null,
        "KeyProtectorType":  3,
        "KeyFileName":  "",
        "RecoveryPassword":  "XXXX",
        "KeyCertificateType":  null,
        "Thumbprint":  ""
    },
    {
        "KeyProtectorId":  "{XXXX}",
        "AutoUnlockProtector":  null,
        "KeyProtectorType":  4,
        "KeyFileName":  "",
        "RecoveryPassword":  "",
        "KeyCertificateType":  null,
        "Thumbprint":  ""
    }
]
Jaykul commented 8 months ago

That's right. We don't do guess-work. As a result, only object types that are specifically configured get serialized properly. The converters in Metadata are full fidelity, so you get actual objects back, not mock PSObjects the way you would with the Json converter.

As a bonus, we don't serialize your RecoveryPassword in plain text 😒

The good news is it's extensible, and it's very easy to write your own converter, taking into account the desire to encode the recovery password, it might look like ...

NOTE: This one seems to work for me, but please don't assume it's production ready!

Add-MetadataConverter @{
    BitLockerVolumeKeyProtector = {
        param($_)
        [Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtector]::new(
            $_.keyProtectorId,
            $_.autoUnlockProtector,
            $_.keyProtectorType,
            $_.keyFileName,
            $(if ($_.recoveryPassword) { ConvertTo-SecureString $_.recoveryPassword | ConvertFrom-SecureString -AsPlainText }),
            $_.certificateType,
            $_.certificateThumbprint)
    }
    [Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtector] = { "BitLockerVolumeKeyProtector @{
    KeyProtectorId = '$($_.KeyProtectorId)'
    AutoUnlockProtector = $($null -eq $_.AutoUnlockProtector ? '$null' : "'"+ $_.AutoUnlockProtector + "'")
    KeyProtectorType = '$($null -eq $_.KeyProtectorType ? '$null' : $_.KeyProtectorType.ToString())'
    KeyFileName = '$($_.KeyFileName)'
    RecoveryPassword = '$(ConvertTo-SecureString $_.RecoveryPassword -AsPlainText -Force | ConvertFrom-SecureString)'
    KeyCertificateType = $($null -eq $_.KeyCertificateType ? '$null' : "'" + $_.KeyCertificateType.ToString() + "'")
    Thumbprint = '$($_.Thumbprint)'
}" }
}