Private/Get-InfraPulseConfigurationFingerprint.ps1
|
function Get-InfraPulseConfigurationFingerprint { # The fingerprint must be identical for logically equal configurations across # PowerShell editions, so the canonical form uses sorted dictionary keys and # invariant-culture scalar formatting instead of ConvertTo-Json. [CmdletBinding()] param( [Parameter(Mandatory)] [System.Collections.IDictionary]$Configuration ) function ConvertTo-CanonicalText { param( [AllowNull()] [object]$Value ) if ($null -eq $Value) { return '<null>' } if ($Value -is [System.Collections.IDictionary]) { $pairs = foreach ($key in @($Value.Keys | Sort-Object -Property { [string]$_ })) { '{0}={1}' -f [string]$key, (ConvertTo-CanonicalText -Value $Value[$key]) } return '{' + ($pairs -join ';') + '}' } if (($Value -is [System.Collections.IEnumerable]) -and -not ($Value -is [string])) { $items = foreach ($item in $Value) { ConvertTo-CanonicalText -Value $item } return '[' + ($items -join ',') + ']' } if ($Value -is [bool]) { return ([bool]$Value).ToString([System.Globalization.CultureInfo]::InvariantCulture) } if ($Value -is [datetime]) { return $Value.ToUniversalTime().ToString('o') } return [string]::Format([System.Globalization.CultureInfo]::InvariantCulture, '{0}', $Value) } $canonical = ConvertTo-CanonicalText -Value $Configuration $sha256 = [System.Security.Cryptography.SHA256]::Create() try { $hashBytes = $sha256.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($canonical)) } finally { $sha256.Dispose() } return (($hashBytes | ForEach-Object { $_.ToString('x2') }) -join '') } |