stig/windows/GenerateStigChecklist.ps1 (129 lines of code) (raw):

<# .SYNOPSIS When "Run as administrator" this script will generate a checklist file via PowerSTIG for Windows Server 2016/2019 that can be viewed with DISA's StigViewer (https://public.cyber.mil/stigs/srg-stig-tools/). A checklist is included with this script as an example of the compliance status with manual checklist entries added. Please confirm all security settings once deployed to your environment. .DESCRIPTION This script is able to generate checklist files for Server 2019 and 2016, with applications installed on base images (Windows Defender, Internet Explorer, Windows Firewall, and DotNet Framework 4) .NOTES This script is included to assist with generating a checklist of a newly deployed VM. Modifications to the script may be required based on organization requirements .EXAMPLE .\GenerateChecklist.ps1 #> Import-Module PowerStig -verbose -force # Get OS version and Paths $powerSTIGpath = (Get-Module -Name PowerSTIG).ModuleBase $outputFolder = New-Item -Path "C:\STIG" -ItemType Directory -Force $outputPath = "$outputFolder\$env:COMPUTERNAME-StigChecklist.ckl" $fullOsVersion = (Get-WmiObject Win32_OperatingSystem).Caption switch -Wildcard ($fullOsVersion) { "*2016*" { $osVersion = "2016" break } "*2019*" { $osVersion = "2019" break } } # Wait for configuration to apply and get DSC Results while ((Get-DscLocalConfigurationManager).LCMState -notmatch "Idle") { Start-Sleep 5 Write-Host "Waiting 5 seconds for retry" } $dscResults = Test-DscConfiguration -Detailed # Server STIGs $latestOsVersion = (Get-Stig -ListAvailable | Where-Object { $_.TechnologyVersion -eq $OsVersion -and $_.TechnologyRole -eq "MS" } | Measure-Object -Maximum -Property Version).Maximum $serverOsSTIG = '{0}\StigData\Archive\Windows.Server.{1}\U_MS_Windows_Server_{1}_MS_STIG_V{2}R{3}_Manual-xccdf.xml' -f $powerSTIGpath, $OsVersion, $latestOsVersion.Major, $latestOsVersion.Minor $manServerSTIG = "U_MS_Windows_Server_{0}_MS_STIG_V{1}R{2}_Manual-xccdf.xml" -f $OsVersion, $latestOsVersion.Major, $latestOsVersion.Minor # Windows Defender STIG $latestDefenderVersion = (Get-Stig -ListAvailable | Where-Object Technology -eq "WindowsDefender" | Measure-Object -Maximum -Property Version).Maximum $defenderSTIG = '{0}\StigData\Archive\Windows.Defender\U_MS_Windows_Defender_Antivirus_STIG_V{1}R{2}_Manual-xccdf.xml' -f $powerSTIGpath, $latestDefenderVersion.Major, $latestDefenderVersion.Minor # Internet Explorer STIG $latestIEVersion = (Get-Stig -ListAvailable | Where-Object Technology -eq "InternetExplorer" | Measure-Object -Maximum -Property Version).Maximum $internetExplorerSTIG = '{0}\StigData\Archive\InternetExplorer\U_MS_IE11_STIG_V{1}R{2}_Manual-xccdf.xml' -f $powerSTIGpath, $latestIEVersion.Major, $latestIEVersion.Minor # Windows Firewall STIG $latestFirewallVersion = (Get-Stig -ListAvailable | Where-Object Technology -eq "WindowsFirewall" | Measure-Object -Maximum -Property Version).Maximum $firewallSTIG = '{0}\StigData\Archive\Windows.Firewall\U_Windows_Firewall_STIG_V{1}R{2}_Manual-xccdf.xml' -f $powerSTIGpath, $latestFirewallVersion.Major, $latestFirewallVersion.Minor $manfirewallSTIG = "U_Windows_Firewall_STIG_V{0}R{1}_Manual-xccdf.xml" -f $latestFirewallVersion.Major, $latestFirewallVersion.Minor # Array of STIGS to add to checklist $xccdfPath = @($serverOsSTIG, $defenderSTIG, $internetExplorerSTIG, $firewallSTIG) $status = "NotAFinding" $comments = "Not Applicable" $details = 'Not applicable for this VM as of deployment time {0} any changes to VM after deployement time may impact this rule' -f $(Get-Date) # Set manual rule data $manualRules = @( @{ osVersion = "2019" stig = $manServerSTIG id = @("V-205624", "V-205657", "V-205661", "V-205664", "V-205677", "V-205699", "V-205721", "V-205727", "V-205746", "V-205844", "V-205847", "V-205848", "V-205852", "V-205853", "V-205854", "V-205855", "V-205710", "V-205707", "V-205700", "V-205658", "V-205846") }, @{ osVersion = "2016" stig = $manServerSTIG id = @("V-224819", "V-224820", "V-224822", "V-224823", "V-224824", "V-224825", "V-224827", "V-224836", "V-224837", "V-224841", "V-224842", "V-224843", "V-224845", "V-224848", "V-224849", "V-224860", "V-224861", "V-224863", "V-225007","V-224829","V-224839","V-224846","V-224838") }, @{ osVersion = "2016|2019" stig = $manfirewallSTIG id = @("V-36440") } ) # Generate manual checklist file $outputPath2 = "c:\ManualCheck.xml" $xmlWriterSettings = [System.Xml.XmlWriterSettings]::new() $xmlWriterSettings.Indent = $true $xmlWriterSettings.IndentChars = "`t" $xmlWriterSettings.NewLineChars = "`n" $writer = [System.Xml.XmlWriter]::Create($OutputPath2, $xmlWriterSettings) $writer.WriteStartElement("stigManualChecklistData") foreach ($item in $manualRules) { if ($osVersion -match $item.osVersion) { foreach ($rule in $item.id) { $writer.WriteStartElement("stigRuleData") $writer.WriteStartElement("STIG") $writer.WriteString($item.stig) $writer.WriteEndElement() $writer.WriteStartElement("ID") $writer.WriteString($rule) $writer.WriteEndElement() $writer.WriteStartElement("Status") $writer.WriteString($status) $writer.WriteEndElement() $writer.WriteStartElement("Comments") $writer.WriteString($comments) $writer.WriteEndElement() $writer.WriteStartElement("Details") $writer.WriteString($details) $writer.WriteEndElement() $writer.WriteEndElement() } } } $writer.WriteEndDocument() $writer.Flush() $writer.Close() # Generate Checklist New-StigCheckList -DscResult $dscResults -XccdfPath $xccdfPath -OutputPath $outputPath -ManualChecklistEntriesFile $outputPath2 # Cleanup checklist manual entries Remove-Item -Path $outputPath2 -Force -Confirm:$false # Get CKL Content and set Localhost Data [string]$localIP = (Get-NetIPAddress -AddressFamily IPV4 | Where-Object { $_.IpAddress -notlike "127.*" } | Select-Object -First 1).IPAddress [string]$localMac = (Get-NetAdapter | Where-Object {$_.Status -eq "Up"} | Select-Object MacAddress | Select-Object -First 1).MacAddress $xml = [xml](Get-Content $outputPath) $xml.CHECKLIST.ASSET.ROLE = 'Member Server' $xml.CHECKLIST.ASSET.HOST_NAME = $env:COMPUTERNAME $xml.CHECKLIST.ASSET.HOST_IP = $localIP $xml.CHECKLIST.ASSET.HOST_MAC = $localMac $xml.CHECKLIST.ASSET.HOST_FQDN = $env:COMPUTERNAME # Import Localhost Data to Checklist $stringbuilder = New-Object System.Text.StringBuilder $writer = [System.Xml.XmlWriter]::Create($stringbuilder, $xmlWriterSettings) $xml.WriteContentTo($Writer) $Writer.Close() $xmlDoc = [System.Xml.XmlDocument]::new() $xmlDoc.PreserveWhitespace = $true $xmlDoc.LoadXml($stringbuilder.ToString()) $xmlDoc.save($outputPath)