Private/Value.ps1
|
function Test-HLStrictEquality { [CmdletBinding()] param( [AllowNull()] [object]$Actual, [AllowNull()] [object]$Expected ) if ($null -eq $Actual -and $null -eq $Expected) { return $true } if ($null -eq $Actual -or $null -eq $Expected) { return $false } if ($Actual -is [bool] -or $Expected -is [bool]) { $actualBool = ConvertTo-HLBoolean -Value $Actual $expectedBool = ConvertTo-HLBoolean -Value $Expected return ($null -ne $actualBool) -and ($null -ne $expectedBool) -and ($actualBool -eq $expectedBool) } $numericTypes = @([byte], [sbyte], [int16], [uint16], [int32], [uint32], [int64], [uint64], [single], [double], [decimal]) $actualIsNumeric = @($numericTypes | Where-Object { $Actual -is $_ }).Count -gt 0 $expectedIsNumeric = @($numericTypes | Where-Object { $Expected -is $_ }).Count -gt 0 if ($actualIsNumeric -and $expectedIsNumeric) { return [double]$Actual -eq [double]$Expected } if ($actualIsNumeric -or $expectedIsNumeric) { # Registry policies occasionally store numbers as strings; accept a # culture-invariant numeric string, but no other cross-type coercion. $text = if ($actualIsNumeric) { $Expected } else { $Actual } $number = if ($actualIsNumeric) { $Actual } else { $Expected } $parsed = 0.0 if ([double]::TryParse([string]$text, [Globalization.NumberStyles]::Number, [Globalization.CultureInfo]::InvariantCulture, [ref]$parsed)) { return $parsed -eq [double]$number } return $false } if ($Actual -is [string] -and $Expected -is [string]) { return [string]::Equals([string]$Actual, [string]$Expected, [StringComparison]::OrdinalIgnoreCase) } return $Actual.GetType() -eq $Expected.GetType() -and $Actual -eq $Expected } function Test-HLValue { [CmdletBinding()] param( [AllowNull()] [object]$Actual, [AllowNull()] [object]$Expected, [Parameter(Mandatory)] [ValidateSet('Equals', 'NotEquals', 'In', 'NotIn', 'GreaterOrEqual', 'LessOrEqual', 'ContainsAll')] [string]$Operator ) switch ($Operator) { 'Equals' { return Test-HLStrictEquality -Actual $Actual -Expected $Expected } 'NotEquals' { return -not (Test-HLStrictEquality -Actual $Actual -Expected $Expected) } 'In' { return @(@($Expected) | Where-Object { Test-HLStrictEquality -Actual $Actual -Expected $_ }).Count -gt 0 } 'NotIn' { return @(@($Expected) | Where-Object { Test-HLStrictEquality -Actual $Actual -Expected $_ }).Count -eq 0 } 'GreaterOrEqual' { if ($null -eq $Actual) { return $false } return [double]$Actual -ge [double]$Expected } 'LessOrEqual' { if ($null -eq $Actual) { return $false } return [double]$Actual -le [double]$Expected } 'ContainsAll' { $actualItems = @($Actual | ForEach-Object { [string]$_ }) foreach ($item in @($Expected)) { if ([string]$item -notin $actualItems) { return $false } } return $true } } } function Get-HLValueProbeResult { [CmdletBinding()] param( [AllowNull()] [object]$Actual, [AllowNull()] [object]$Expected, [Parameter(Mandatory)] [string]$Operator, [AllowNull()] [object[]]$WarningValues, [string]$SuccessMessage = 'The effective value matches the baseline.', [string]$FailureMessage = 'The effective value does not match the baseline.', [AllowNull()] [object]$Evidence = $null ) if (Test-HLValue -Actual $Actual -Expected $Expected -Operator $Operator) { return Get-HLProbeResult -Status Pass -Expected $Expected -Actual $Actual -Message $SuccessMessage -Evidence $Evidence } if ($null -ne $WarningValues -and $Actual -in @($WarningValues)) { return Get-HLProbeResult -Status Warning -Expected $Expected -Actual $Actual -Message 'The control is in audit or warning mode and is not fully enforced.' -Evidence $Evidence } return Get-HLProbeResult -Status Fail -Expected $Expected -Actual $Actual -Message $FailureMessage -Evidence $Evidence } |