Private/_GateEval.ps1
|
function _KriticalLensExtractParamMap { <# .SYNOPSIS Given a FunctionDefinitionAst, returns a hashtable keyed by parameter name, valued by { TypeName; Mandatory; ValidateSet[] }. #> param($FnAst) $map = @{} if (-not $FnAst -or -not $FnAst.Body.ParamBlock) { return $map } foreach ($p in $FnAst.Body.ParamBlock.Parameters) { $pname = $p.Name.VariablePath.UserPath $pTypeName = if ($p.StaticType) { $p.StaticType.Name } else { '' } $mandatory = $false $validateSet = @() foreach ($attr in $p.Attributes) { if ($attr.TypeName.Name -eq 'Parameter') { foreach ($na in $attr.NamedArguments) { if ($na.ArgumentName -eq 'Mandatory') { $mandatory = ($na.Argument -and $na.Argument.Extent.Text -match '\$true') } } } elseif ($attr.TypeName.Name -eq 'ValidateSet') { foreach ($arg in $attr.PositionalArguments) { $v = $arg.Extent.Text -replace "^'|'$",'' $validateSet += $v } } } $map[$pname] = [pscustomobject]@{ TypeName = $pTypeName Mandatory = $mandatory ValidateSet = $validateSet } } return $map } function _KriticalLensEvaluateResource { <# .SYNOPSIS Runs the six gates (C1..C6) for one resource against its primitive candidate. Returns per-gate booleans plus a list of finding rows. #> param( $Resource, $Primitive ) $findings = @() $c1 = ($Primitive -and $Primitive.NewFn) $c6 = ($Primitive -and $Primitive.GetFn) if (-not $c1) { $findings += [pscustomobject]@{ Resource = $Resource.ResourceName Param = '(all)' Class = 'RESOURCE-MISSING-KRITICAL-PRIMITIVE' Detail = 'No New- function with COVERS-DSC-RESOURCE marker was found for this resource' } return [pscustomobject]@{ C1 = $c1 C6 = $c6 PerParam = @() Findings = $findings } } $newParamMap = _KriticalLensExtractParamMap -FnAst $Primitive.NewFnAst $perParam = @() foreach ($p in $Resource.Parameters) { $pname = $p.Name $krit = $newParamMap[$pname] $c2 = $null -ne $krit $c3 = $null; $c4 = $null; $c5 = $null if (-not $c2) { $findings += [pscustomobject]@{ Resource = $Resource.ResourceName Param = $pname Class = 'PARAM-MISSING-IN-KRITICAL' Detail = ('Schema declares {0} ({1}) but the Kritical param block does not' -f $pname, $p.DataType) } $perParam += [pscustomobject]@{ Name=$pname; C2=$false } continue } $schemaMandatory = ($p.Mandatory -eq $true) $c3 = ($schemaMandatory -eq $krit.Mandatory) if (-not $c3) { $findings += [pscustomobject]@{ Resource = $Resource.ResourceName Param = $pname Class = 'MANDATORY-MISMATCH' Detail = ('schema={0} kritical={1}' -f $schemaMandatory, $krit.Mandatory) } } $schemaBase = _KriticalLensCleanBase $p.DataType $expected = $script:KriticalLensDataTypeMap[$schemaBase] $kritBase = _KriticalLensCleanBase $krit.TypeName if ($schemaBase -match '^MSFT_' -or $schemaBase -eq '') { $c4 = $true } elseif ($expected) { $c4 = ($expected -contains $kritBase) -or ($kritBase -eq 'object') } else { $c4 = $true } if (-not $c4) { $findings += [pscustomobject]@{ Resource = $Resource.ResourceName Param = $pname Class = 'TYPE-MISMATCH' Detail = ('schema={0} kritical={1}' -f $p.DataType, $krit.TypeName) } } if ($p.AllowedValues -and $p.AllowedValues.Count -gt 0) { $missing = @($p.AllowedValues | Where-Object { $krit.ValidateSet -notcontains $_ }) $c5 = ($missing.Count -eq 0) if (-not $c5) { $findings += [pscustomobject]@{ Resource = $Resource.ResourceName Param = $pname Class = 'VALIDATESET-MISSING-VALUES' Detail = ('missing: {0}' -f ($missing -join '|')) } } } $perParam += [pscustomobject]@{ Name = $pname; C2 = $true; C3 = $c3; C4 = $c4; C5 = $c5 } } return [pscustomobject]@{ C1 = $c1 C6 = $c6 PerParam = $perParam Findings = $findings } } |