Skip to content

Commit

Permalink
Fixed Functions.Checklist Manual Checks need to leverage psd1 files -…
Browse files Browse the repository at this point in the history
… Backward Compat Issue (#751)

* introducing back compat functions to checklist

* new-checklist back compat fix

* updated functions based on feedback

* updated ConvertTo-ManualCheckListHashTable with
 correct property id

* updated changelog.md

* removed unneeded comments.

* updated comment based help.

* updated throw message
  • Loading branch information
bcwilhite committed Oct 11, 2020
1 parent 34bbc2d commit 6ba15fc
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 6 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## [Unreleased]

* Fixed [#746](https://github.com/microsoft/PowerStig/issues/746): Functions.Checklist Manual Checks need to leverage psd1 files - Backward Compat Issue

## [4.5.0] - 2020-09-01

* Update PowerSTIG to successfully parse/apply Windows 2012 R2 DC Version 2, Rev 21: [#677](https://github.com/microsoft/PowerStig/issues/677)
Expand Down
161 changes: 155 additions & 6 deletions source/Module/STIG/Functions.Checklist.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@
The location where the checklist .ckl file will be created. Must include the filename with .ckl on the end.
.PARAMETER ManualChecklistEntriesFile
Location of a .xml file containing the input for Vulnerabilities unmanaged via DSC/PowerSTIG.
Location of a .xml or .psd1 file containing the input for Vulnerabilities unmanaged via DSC/PowerSTIG i.e.: Document/Manual Rules.
This file can be created manually or by exporting an Excel worksheet as XML. The file format should look like the following:
This file can be created manually or by exporting an Excel worksheet as XML or psd1. The file format should look like the following:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<stigManualChecklistData>
Expand Down Expand Up @@ -136,7 +136,7 @@ function New-StigCheckList
}
else
{
throw "$($_) is not a valid path to a ManualChecklistEntriesFile.xml file. Provide a full valid path and filename."
throw "$($_) is not a valid path to a Manual Checklist Entries File. Provide a full valid path and filename."
}
}
)]
Expand Down Expand Up @@ -171,7 +171,7 @@ function New-StigCheckList

if ($PSBoundParameters.ContainsKey('ManualChecklistEntriesFile'))
{
[xml] $manualCheckData = Get-Content -Path $ManualChecklistEntriesFile
$manualCheckData = ConvertTo-ManualCheckListHashTable -Path $ManualChecklistEntriesFile -XccdfPath $XccdfPath
}

# Values for some of these fields can be read from the .mof file or the DSC results file
Expand Down Expand Up @@ -356,7 +356,7 @@ function New-StigCheckList
if ($PSCmdlet.ParameterSetName -eq 'mof')
{
$setting = Get-SettingsFromMof -ReferenceConfiguration $ReferenceConfiguration -Id $vid
$manualCheck = $manualCheckData.stigManualChecklistData.stigRuleData | Where-Object -FilterScript {$_.STIG -eq $stigFileName -and $_.ID -eq $vid}
$manualCheck = $manualCheckData | Where-Object -FilterScript {$_.STIG -eq $stigFileName -and $_.ID -eq $vid}
if ($setting)
{
$status = $statusMap['Open']
Expand All @@ -377,7 +377,7 @@ function New-StigCheckList
}
elseif ($PSCmdlet.ParameterSetName -eq 'dsc')
{
$manualCheck = $manualCheckData.stigManualChecklistData.stigRuleData | Where-Object -FilterScript {$_.STIG -eq $stigFileName -and $_.ID -eq $vid}
$manualCheck = $manualCheckData | Where-Object -FilterScript {$_.STIG -eq $stigFileName -and $_.ID -eq $vid}
if ($manualCheck)
{
$status = $statusMap["$($manualCheck.Status)"]
Expand Down Expand Up @@ -794,3 +794,152 @@ function ConvertTo-SafeXml
$escapedXml = [System.Security.SecurityElement]::Escape($UnescapedXmlString)
return $escapedXml
}

<#
.SYNOPSIS
Converts the xml or psd1 in to a consistent data structure (hashtable) for use with the New-StigCheckList function.
.DESCRIPTION
Converts the xml or psd1 in to a consistent data structure (hashtable) for use with the New-StigCheckList function.
.PARAMETER Path
Location of a .xml or .psd1 file containing the input for Vulnerabilities unmanaged via DSC/PowerSTIG i.e.: Document/Manual Rules.
.PARAMETER XccdfPath
The path to a DISA STIG .xccdf file. PowerSTIG includes the supported files in the /PowerShell/StigData/Archive folder.
.EXAMPLE
PS> ConvertTo-ManualCheckListHashTable -Path C:\dev\ManualEntryData.psd1 -XccdfPath $xccdfPath
Returns a hashtable that constains checklist data that will be used to inject into the ckl in the New-StigCheckList function.
.NOTES
Internal use only function, not for Export-ModuleMember
#>
function ConvertTo-ManualCheckListHashTable
{
[OutputType([hashtable[]])]
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[string]
$Path,

[Parameter(Mandatory = $true)]
[string[]]
$XccdfPath
)

$fileDetail = Get-Item -Path $Path

switch ($fileDetail.Extension)
{
'.xml'
{
# Import ManualCheckList xml contents to convert to hashtable to match psd1 back compat
[xml] $xmlToConvert = Get-Content -Path $Path

foreach ($stigRuleData in $xmlToConvert.stigManualChecklistData.stigRuleData)
{
$stigRuleManualCheck = @{}
$stigRuleDataPropertyNames = (Get-Member -InputObject $stigRuleData -MemberType 'Property').Name
foreach ($stigRuleDataPropertyName in $stigRuleDataPropertyNames)
{
$stigRuleManualCheck.Add($stigRuleDataPropertyName, $stigRuleData.$stigRuleDataPropertyName)
}
$stigRuleManualCheck
}
}
'.psd1'
{
$formattedPsd1ToConvert = (Get-Content -Path $Path -Raw) -replace '"|@{' -split '}'
$convertedPsd1HashTable = $formattedPsd1ToConvert | ConvertFrom-StringData
foreach ($stigRuleManualCheck in $convertedPsd1HashTable)
{
if ($stigRuleManualCheck.Count -ne 0)
{
$stigFileName = Get-StigXccdfFileName -VulnId $stigRuleManualCheck.VulID -XccdfPath $XccdfPath
$stigRuleManualCheck.Add('STIG', $stigFileName)
$stigRuleManualCheck.Add('Details', $stigRuleManualCheck.Comments)
$stigRuleManualCheck.Add('ID', $stigRuleManualCheck['VulId'])
$stigRuleManualCheck.Remove('VulId')
$stigRuleManualCheck
}
}
}
}
}

<#
.SYNOPSIS
Used to detect the correct STIG property when a psd1 is specified.
.DESCRIPTION
Used to detect the correct STIG property when a psd1 is specified.
.PARAMETER VulnId
The VulnId or RuleId for a given STIG Rule
.PARAMETER XccdfPath
The path to a DISA STIG .xccdf file. PowerSTIG includes the supported files in the /PowerShell/StigData/Archive folder.
.EXAMPLE
PS> Get-StigXccdfFileName -VulnId 'V-1114' -XccdfPath C:\PowerStig\StigData\Archive\Windows.Server.2012R2\U_MS_Windows_2012_and_2012_R2_DC_STIG_V2R19_Manual-xccdf.xml
Returns U_MS_Windows_2012_and_2012_R2_DC_STIG_V2R19_Manual-xccdf.xml as the correct xccdf file specified by the user.
.NOTES
Internal use only function, not for Export-ModuleMember
#>
function Get-StigXccdfFileName
{
[CmdletBinding()]
[OutputType([string])]
param
(
[Parameter(Mandatory = $true)]
[string]
$VulnId,

[Parameter(Mandatory = $true)]
[string[]]
$XccdfPath
)

$processedXmlPath = Join-Path -Path $PSScriptRoot -ChildPath '..\..\StigData\Processed\*.xml'
$processedXml = Select-String -Path $processedXmlPath -Pattern $VulnId -Exclude '*.org.default.xml' | Sort-Object -Property Pattern

$stigVersionData = @()
foreach ($xmlPath in $processedXml.Path)
{
[xml] $xml = Get-Content -Path $xmlPath
$stigVersionData += [PSCustomObject] @{
Version = [version] $xml.DISASTIG.fullversion
FileName = $xml.DISASTIG.filename
}
}

# populate the STIG value based on Xccdf Path passed by user
$compareObjectParams = @{
ReferenceObject = $(Split-Path -Path $XccdfPath -Leaf)
DifferenceObject = $stigVersionData.FileName
IncludeEqual = $true
ExcludeDifferent = $true
}

$xccdfFileDetection = (Compare-Object @compareObjectParams).InputObject

if ($xccdfFileDetection.Count -eq 1)
{
return $xccdfFileDetection
}
elseif ($xccdfFileDetection.Count -gt 1)
{
throw 'Unable to determine correct Xccdf file for psd1 usage, ensure that the correct Xccdf file(s) are used.'
}
else
{
return ($stigVersionData | Sort-Object -Property Version -Descending | Select-Object -First 1).FileName
}
}

0 comments on commit 6ba15fc

Please sign in to comment.