module/StigRepo.psm1
function Initialize-StigRepo { [CmdletBinding()] param ( [Parameter()] [string] $RootPath = (Get-Location).Path ) Write-Output "Beginning Stig Compliance Automation Repository (SCAR) Build" Write-Output "`tBuilding Repository Folder Structure" # Systems Folder $systemsPath = New-Item -Path "$RootPath\Systems" -ItemType Directory -Force $stagingPath = New-Item -Path "$SystemsPath\Staging" -ItemType Directory -Force # Configurations Folder $configPath = New-Item -Path "$RootPath\Configurations" -ItemType Directory -Force # Artifacts Folder $artifactPath = New-Item -Path "$RootPath\Artifacts" -ItemType Directory -Force $dscConfigPath = New-Item -Path "$artifactPath\DscConfigs" -ItemType Directory -Force $mofPath = New-Item -Path "$artifactPath\Mofs" -ItemType Directory -Force $CklPath = New-Item -Path "$artifactPath\Stig Checklists" -ItemType Directory -Force # Resources Folder $resourcePath = New-Item -Path "$RootPath\Resources" -ItemType Directory -Force $modulePath = New-Item -Path "$resourcePath\Modules" -ItemType Directory -Force $stigDataPath = New-Item -Path "$resourcePath\Stig Data" -ItemType Directory -Force $xccdfPath = New-Item -Path "$stigDataPath\Xccdfs" -ItemType Directory -Force $orgSettingPath = New-Item -Path "$stigDataPath\Organizational Settings" -ItemType Directory -Force $mancheckPath = New-Item -Path "$stigDataPath\Manual Checks" -ItemType Directory -Force $wikiPath = New-Item -Path "$resourcePath\Wiki" -ItemType Directory -Force Write-Output "`tExtracting DSC Configurations and Wiki Files" $stigRepoModulePath = (Get-Module StigRepo).Path $stigRepoRoot = Split-Path -Path (Split-Path $stigRepoModulePath -Parent) -Parent $configZip = "$stigRepoRoot\Resources\Configurations.zip" $wikiZip = "$stigRepoRoot\Resources\wiki.zip" Expand-Archive $configZip -DestinationPath $RootPath -force Expand-Archive $wikiZip -DestinationPath $ResourcePath -force Update-StigRepo -RemoveBackup Write-Output "`n`tInstalling/Importing SCAR Modules" Sync-DscModules -LocalHost -Force Import-Module PowerSTIG -Force Import-Module StigRepo -Force Write-Output "STIG Compliance Automation Repository Build Complete." Write-Output "Run New-SystemData to begin System Data creation.`n`n" } function Update-StigRepo { [CmdletBinding()] param ( [Parameter()] [string] $RootPath = (Get-Location).Path, [Parameter()] [switch] $RemoveBackup ) Write-Output "Starting SCAR Update" $stigDataPath = (Resolve-Path -Path "$RootPath\Resources\Stig Data").Path $modulePath = (Resolve-Path -Path "$RootPath\Resources\Modules" -erroraction Stop).Path $modules = Get-Childitem $ModulePath # Update Dependent Modules Write-Output "`tRemoving old Dependencies" foreach ($module in $modules) { Write-Output "`t`tRemoving $($module.name)" Remove-Item $module.fullname -force -Recurse -Confirm:$false } Write-Output "`tInstalling Dependencies" Save-Module StigRepo -Path $ModulePath -Verbose Save-Module PowerSTIG -Path $ModulePath -Verbose #endregion Update Dependent Modules #region Update STIG Data Files Write-Output "`tUpdating STIG Data Files" # Backup STIG Data Folder Write-Output "`n`t`tBacking up current STIG Data" $resourcePath = Split-Path $StigDataPath -Parent $backupPath = "$resourcePath\Stig Data-Backup" Copy-Item $stigDataPath -Destination $backupPath -Force -Recurse # Update Xccdfs Write-Output "`n`t`tUpdating STIG XCCDF Files" Get-Item "$StigDataPath\Xccdfs" | Remove-Item -Recurse -Force -Confirm:$false $currentXccdfFolders = Get-Childitem "$StigDataPath-Backup\Xccdfs\*" -Directory $newXccdfPath = New-Item -ItemType Directory -Path $StigDataPath -Name "Xccdfs" -Force -Confirm:$false $newXccdfFolders = Get-Childitem "$ModulePath\PowerSTIG\*\StigData\Archive\*" -Directory $newXccdfFolders | Copy-Item -Destination "$StigDataPath\Xccdfs" -Force -Recurse -Confirm:$false $customxccdfs = $currentXccdfFolders | where { ((Compare-Object -ReferenceObject $currentXccdfFolders.name -DifferenceObject $newXccdfFolders.name).inputobject) -contains $_.name } $customXccdfs.FullName | Copy-Item -Destination $newXccdfPath -Recurse -Force -Confirm:$false -ErrorAction SilentlyContinue # Update Org Settings Write-Output "`n`t`tUpdating Organizational Setting Files" Get-Item "$StigDataPath\Organizational Settings" | Remove-Item -Recurse -Force -Confirm:$false $currentOrgSettings = Get-Childitem "$StigDataPath-Backup\Organizational Settings\*org.default.xml" $null = New-Item -ItemType Directory -Path $StigDataPath -Name "Organizational Settings" -Force -Confirm:$false $newOrgSettings = Get-Childitem "$ModulePath\PowerSTIG\*\StigData\Processed\*.org.default.xml" $newOrgSettings | Copy-Item -Destination "$StigDataPath\Organizational Settings" -Force -Confirm:$false # Manual Checks Write-Output "`n`t`tUpdating Manual Check Files" $powerStigXccdfPath = (Resolve-Path "$modulePath\PowerStig\*\StigData\Archive").Path $powerStigProcessedPath = (Resolve-Path "$ModulePath\PowerSTIG\*\StigData\Processed").Path $xccdfs = Get-Childitem "$powerStigXccdfPath\*.xml" -recurse $processedXccdfs = Get-Childitem "$powerStigProcessedPath\*.xml" -recurse | where {$_.name -notlike "*org.default*"} $newManualCheckPath = New-Item -ItemType Directory -Path $StigDataPath -Name "Manual Checks" -Force -Confirm:$False $oldManualCheckPath = (Resolve-Path "$StigDataPath-Backup\Manual Checks").Path $currentManualChecks = Get-ChildItem -Path $oldManualCheckPath $currentManualChecks | Copy-Item -Destination $StigDataPath -Force -Recurse -Confirm:$false foreach ($xccdf in $processedXccdfs) { switch -Wildcard ($xccdf.name) { "WindowsServer*2019*" {$xccdfFolderName = "Windows.Server.2019"} "WindowsServer*2016*" {$xccdfFolderName = "Windows.Server.2016"} "WindowsServer*2012*" {$xccdfFolderName = "Windows.Server.2012R2"} "*Firewall*" {$xccdfFolderName = "Windows.Firewall"} "*DNS*" {$xccdfFolderName = "Windows.DNS"} "*Defender*" {$xccdfFolderName = "Windows.Defender"} "*Client*" {$xccdfFolderName = "Windows.Client"} "*IISServer*" {$xccdfFolderName = "WebServer"} "*IISSite*" {$xccdfFolderName = "WebSite"} "*VSphere*" {$xccdfFolderName = "VSphere"} "*SQL*Server*" {$xccdfFolderName = "Sql Server"} "*Oracle*" {$xccdfFolderName = "OracleJRE"} "*Office*" {$xccdfFolderName = "Office"} "*McAfee*" {$xccdfFolderName = "McAfee"} "*Ubuntu*" {$xccdfFolderName = "Linux.Ubuntu"} "*RHEL*" {$xccdfFolderName = "Linux.RHEL"} "*InternetExplorer*" {$xccdfFolderName = "InternetExplorer"} "*Edge*" {$xccdfFolderName = "Edge"} "*DotNet*" {$xccdfFolderName = "DotNet"} "*Chrome*" {$xccdfFolderName = "Chrome"} "*FireFox*" {$xccdfFolderName = "FireFox"} "*Adobe*" {$xccdfFolderName = "Adobe"} } [xml]$xccdfcontent = Get-Content $xccdf.FullName -Encoding UTF8 $manualRules = $xccdfContent.DisaStig.ManualRule.Rule.id $manualCheckContent = New-Object System.Collections.ArrayList $manualCheckFolder = "$StigDataPath\Manual Checks\$xccdfFolderName" $stigVersion = $xccdf.basename.split("-") | Select -last 1 if (-not(Test-Path $manualCheckFolder)) { $null = New-Item -ItemType Directory -Path $manualCheckFolder } $manualCheckFilePath = "$manualCheckFolder\$($xccdfContent.DisaStig.StigId)-$stigVersion-manualChecks.psd1" if ($null -ne $manualRules) { Write-Output "`t`t`tGenerating Manual Check file for $($xccdf.Name)" foreach ($vul in $manualRules) { $null = $manualCheckContent.add("@{") $null = $manualCheckContent.add(" VulID = `"$($vul)`"") $null = $manualCheckContent.add(" Status = `"NotReviewed`"") $null = $manualCheckContent.add(" Comments = `"EXAMPLE: This Comment was provided by the STIG Compliance Automation Repository. Modify $manualCheckFilePath to customize the status/comments for this finding.`"") $null = $manualCheckContent.add("}`n") } $manualCheckContent | Out-File $manualCheckFilePath -force } else { Write-Output "`t`t`tGenerating Manual Check file for $($xccdf.Name)" $null = $manualCheckContent.add("@{") $null = $manualCheckContent.add(" VulID = `"V-XXXX`"") $null = $manualCheckContent.add(" Status = `"NotReviewed`"") $null = $manualCheckContent.add(" Comments = `"EXAMPLE: This Comment was provided by the STIG Compliance Automation Repository. Modify $manualCheckFilePath to customize the status/comments for this finding.`"") $null = $manualCheckContent.add("}`n") $manualCheckContent | Out-File $manualCheckFilePath -force } } if ($RemoveBackup) { Get-Item "$resourcePath\Stig Data-Backup" | Remove-Item -Force -Recurse -Confirm:$false } } function Start-DscBuild { <# .SYNOPSIS Executes SCAR functions that compile dynamic configurations for each machine based on the parameters and parameter values provided within that VM's configuration data. .PARAMETER Rootpath Path to the root of the SCAR repository/codebase. .PARAMETER ValidateModules Executes the Sync-DscModules cmdlet and sync modules/versions with what is in the "5. resouces\Modules" folder of SCAR. .PARAMETER ArchiveFiles Switch parameter that archives the artifacts produced by SCAR. This switch compresses the artifacts and places them in the archive folder. .PARAMETER CleanBuild Switch parameter that removes files from the MOFs and Artifacts folders to create a clean slate for the SCAR build. .PARAMETER CleanArchive Switch Parameter that r$dscdataemoves files from the archive folder. .PARAMETER SystemFiles Allows users to provide an array of configdata files to target outside of the Systems folder. .PARAMETER PreRequisites Executes nodededata generation, DSC module copy, and WinRM configuration as part of the SCAR build process. .EXAMPLE Start-DscBuild -RootPath "C:\DSC Management" -CleanBuild -CleanArchive -PreRequisites #> [cmdletbinding()] param( [Parameter()] [string] $RootPath = (Get-Location).Path, [Parameter()] [string] $TargetFolder, [Parameter()] [switch] $CopyModules, [Parameter()] [switch] $ArchiveFiles, [Parameter()] [switch] $CleanBuild, [Parameter()] [System.Collections.ArrayList] $SystemFiles, [Parameter()] [switch] $PreRequisites ) # Root Folder Paths $SystemsPath = (Resolve-Path -Path "$RootPath\*Systems").Path $dscConfigPath = (Resolve-Path -Path "$RootPath\*Configurations").Path $resourcePath = (Resolve-Path -Path "$RootPath\*Resources").Path $artifactPath = (Resolve-Path -Path "$RootPath\*Artifacts").Path $reportsPath = (Resolve-Path -Path "$RootPath\*Artifacts\Reports").Path $mofPath = (Resolve-Path -Path "$RootPath\*Artifacts\Mofs").Path # Begin Build Write-Output "Beginning Desired State Configuration Build Process`r`n" # Remove old Mofs/Artifacts if ($CleanBuild) { Remove-BuildItems -RootPath $RootPath } # Validate Modules on host and target machines if ($CopyModules) { Sync-DscModules -Rootpath $RootPath } # Import required DSC Resource Module Import-DscModules -ModulePath "$ResourcePath\Modules" # Combine PSD1 Files $allNodesDataFile = "$artifactPath\DscConfigs\AllNodes.psd1" $SystemFiles = New-Object System.Collections.ArrayList if ('' -eq $SystemFiles) { if ('' -eq $TargetFolder) { $null = Get-ChildItem -Path "$SystemsPath\*.psd1" -Recurse | Where-Object { ($_.Fullname -notmatch "Staging") -and ($_.Fullname -Notlike "Readme*")} | ForEach-Object {$null = $systemFiles.add($_)} Get-CombinedConfigs -RootPath $RootPath -AllNodesDataFile $allNodesDataFile -SystemFiles $SystemFiles Export-DynamicConfigs -SystemFiles $SystemFiles -ArtifactPath $artifactPath -DscConfigPath $dscConfigPath Export-Mofs -RootPath $RootPath } else { $null = Get-ChildItem -Path "$systemsPath\$TargetFolder\*.psd1" -Recurse | Where-Object { ($_.Fullname -notmatch "Staging") -and ($_.Fullname -Notlike "Readme*")} | ForEach-Object {$null = $Systemfiles.add($_)} Get-CombinedConfigs -RootPath $RootPath -AllNodesDataFile $allNodesDataFile -SystemFiles $SystemFiles -TargetFolder $TargetFolder Export-DynamicConfigs -SystemFiles $SystemFiles -ArtifactPath $artifactPath -DscConfigPath $dscConfigPath -TargetFolder $TargetFolder Export-Mofs -RootPath $RootPath -TargetFolder $TargetFolder } } # Archive generated artifacts if ($archiveFiles) { Compress-DscArtifacts -Rootpath $RootPath } # DSC Build Complete Write-Output "`n`n`t`tDesired State Configuration Build complete.`n`n" } function Get-CombinedConfigs { <# .SYNOPSIS Generates configuration data for each node defined within a targeted folder and generates a single .psd1 for each node with their combined "AppliedConfigurations" and parameters to generate MOFs off of. Also generates a single configuration data file containing all nodes/configurations. .PARAMETER RootPath Path to the Root of the SCAR platforms .EXAMPLE Get-CombinedConfigs -RootPath "C:\SCAR" #> [cmdletBinding()] param ( [Parameter()] [string] $RootPath = (Get-Location).Path, [Parameter()] [string] $AllNodesDataFile, [Parameter()] [array] $TargetFolder, [Parameter()] [System.Collections.ArrayList] $SystemFiles ) $allconfigfiles = New-Object System.Collections.ArrayList if ($null -eq $SystemFiles) { $SystemsPath = (Resolve-Path -Path "$Rootpath\*Systems").Path if ('' -ne $targetFolder) { $null = Get-ChildItem -Path "$SystemsPath\*.psd1" -Recurse | Where-Object { ($_.Fullname -notmatch "Staging") -and ($_.Fullname -Notlike "Readme*") } | ForEach-Object {$null = $allconfigfiles.add($_)} } else { $null = Get-ChildItem -Path "$SystemsPath\$TargetFolder\*.psd1" -Recurse | Where-Object { ($_.Fullname -notmatch "Staging") -and ($_.Fullname -Notlike "Readme*") } | ForEach-Object {$null = $allconfigfiles.add($_)} } } foreach ($configFile in $allConfigFiles) { $data = Invoke-Expression (Get-Content $nodeConfig.FullName | Out-String) if ($null -ne $data.AppliedConfigurations) { $null = $SystemFiles.add($configFile) } } if ($SystemFiles.count -lt 1) { Write-Output "No DSC configdata files were provided." } else { Write-Output "`n`tBeginning Powershell Data File build for $($SystemFiles.count) targeted Machines.`n" New-Item -Path $AllNodesDataFile -ItemType File -Force | Out-Null $string = "@{`n`tAllNodes = @(`n" $string | Out-File $AllNodesDataFile -Encoding utf8 [int]$countOfConfigurations = ($SystemFiles | Measure-object | Select-Object -expandproperty count) for ($i = 0; $i -lt $countOfConfigurations; $i++) { Get-Content -Path $($SystemFiles[$i].FullName) -Encoding UTF8 | ForEach-Object -Process { "`t`t" + $_ | Out-file $AllNodesDataFile -Append -Encoding utf8 } if ($i -ne ($countOfConfigurations - 1) -and ($countOfConfigurations -ne 1)) { "`t`t," | Out-file $allNodesDataFile -Append -Encoding utf8 } } "`t)`n}" | Out-File $allNodesDataFile -Append -Encoding utf8 } } function Export-DynamicConfigs { <# .SYNOPSIS Generates DSC scripts with combined parameter and parameter values based on provided configuration data. .PARAMETER SystemFiles Array of configuration data files. Targets all .psd1 files under the "Systems" folder that are not located in the staging folder. Example -SystemFiles $ConfigDataArray .PARAMETER ArtifactPath Path to the Artifacts Folder. Defaults to the "4. Artifacts" folder from the Rootpath provided by the Start-DscBuild function. .EXAMPLE Export-DynamicConfigs -SystemFiles $SystemFiles -ArtifactPath $artifactPath #> [cmdletBinding()] param ( [Parameter()] [System.Collections.ArrayList] $SystemFiles, [Parameter()] [string] $TargetFolder, [Parameter()] [string] $ArtifactPath, [Parameter()] [string] $DscConfigPath ) $jobs = New-Object System.Collections.ArrayList foreach ($SystemFile in $SystemFiles) { $machinename = $SystemFile.basename if ('' -ne $TargetFolder -and $SystemFile.fullname -notlike "*\$TargetFolder\*") { Continue } else { Write-Output "`t`tStarting Job - Compile DSC Configuration for $($SystemFile.basename)" $job = Start-Job -Scriptblock { $SystemFile = $using:SystemFile $dscConfigPath = $using:dscConfigPath $artifactPath = $using:ArtifactPath $machinename = $using:machinename $nodeConfigScript = "$ArtifactPath\DscConfigs\$machineName.ps1" $data = Invoke-Expression (Get-Content $SystemFile.FullName | Out-String) if ($null -ne $data.AppliedConfigurations) { $appliedConfigs = $data.appliedconfigurations.Keys $lcmConfig = $data.LocalConfigurationManager.Keys $nodeName = $data.NodeName Write-Output "`t$machineName - Building Customized Configuration Data`n" New-Item -ItemType File -Path $nodeConfigScript -Force | Out-Null foreach ($appliedConfig in $appliedConfigs) { if (Test-Path $SystemFile.fullname) { Write-Output "`t`tConfigData Import - $appliedConfig" $dscConfigScript = "$DscConfigPath\$appliedConfig.ps1" $fileContent = Get-Content -Path $dscConfigScript -Encoding UTF8 -ErrorAction Stop $fileContent | Out-file $nodeConfigScript -Append -Encoding utf8 -ErrorAction Stop . $dscConfigScript Invoke-Expression ($fileContent | Out-String) #DevSkim: ignore DS104456 } else { Throw "The configuration $appliedConfig was specified in the $($SystemFile.fullname) file but no configuration file with the name $appliedConfig was found in the \Configurations folder." } } $mainConfig = New-Object System.Collections.ArrayList $null = $mainConfig.add("Configuration MainConfig`n{`n`tNode `$AllNodes.Where{`$_.NodeName -eq `"$nodeName`"}.NodeName`n`t{") foreach ($appliedConfig in $appliedConfigs) { Write-Output "`t`tParameter Import - $AppliedConfig" $syntax = Get-Command $appliedConfig -Syntax -ErrorAction Stop $appliedConfigParameters = [Regex]::Matches($syntax, "\[{1,2}\-[a-zA-Z0-9]+") | Select-Object @{l = "Name"; e = { $_.Value.Substring($_.Value.IndexOf('-') + 1) } }, @{l = "Mandatory"; e = { if ($_.Value.IndexOf('-') -eq 1) { $true }else { $false } } } $null = $mainconfig.add("`n`t`t$appliedConfig $appliedConfig`n`t`t{`n") foreach ($appliedConfigParameter in $appliedConfigParameters) { if ($null -ne $data.appliedconfigurations.$appliedConfig[$appliedConfigParameter.name]) { $null = $mainConfig.add("`t`t`t$($appliedConfigParameter.name) = `$node.appliedconfigurations.$appliedConfig[`"$($appliedConfigParameter.name)`"]`n") } elseif ($true -eq $appliedConfigParameter.mandatory) { $errorMessage = New-Object System.Collections.ArrayList $null = $errorMessage.add("$nodeName configuration $appliedConfig has a mandatory parameter $($appliedConfigParameter.name) and was not specified.`n`n") $null = $errorMessage.add("$appliedConfig = @{`n") foreach ($appliedConfigParameter in $appliedConfigParameters) { $null = $errorMessage.add("`t$($appliedconfigParameter.name) = `"VALUE`"`n") } $null = $errorMessage.add("}") Throw $errorMessage } } $null = $mainConfig.add("`t`t}`n") } $null = $mainConfig.add("`t}`n}`n") $mainConfig | Out-file $nodeConfigScript -nonewline -Append -Encoding utf8 #endregion Build configurations and generate MOFs #region Generate data for meta.mof (Local Configuration Manager) if ($null -ne $lcmConfig) { Write-Output "`t`tGenerating LCM Configuration" [array]$lcmParameters = "ActionAfterReboot", "AllowModuleOverWrite", "CertificateID", "ConfigurationDownloadManagers", "ConfigurationID", "ConfigurationMode", "ConfigurationModeFrequencyMins", "DebugMode", "StatusRetentionTimeInDays", "SignatureValidationPolicy", "SignatureValidations", "MaximumDownloadSizeMB", "PartialConfigurations", "RebootNodeIfNeeded", "RefreshFrequencyMins", "RefreshMode", "ReportManagers", "ResourceModuleManagers" $localConfig = New-Object System.Collections.ArrayList $null = $localConfig.add("[DscLocalConfigurationManager()]`n") $null = $localConfig.add("Configuration LocalConfigurationManager`n{`n`tNode `$AllNodes.Where{`$_.NodeName -eq `"$nodeName`"}.NodeName`n`t{`n`t`tSettings {`n") foreach ($setting in $lcmConfig) { if ($null -ne ($lcmParameters | Where-Object { $setting -match $_ })) { $null = $localConfig.add("`t`t`t$setting = `$Node.LocalconfigurationManager.$Setting`n") } else { Write-Warning "The term `"$setting`" is not a configurable setting within the Local Configuration Manager." } } $null = $localConfig.add("`t`t}`n`t}`n}") $localConfig | Out-file $nodeConfigScript -nonewline -Append -Encoding utf8 } Write-Output "`n`t$nodeName configuration file successfully generated.`r`n" } } } $null = $jobs.add($job.Id) } Write-Output "`n`tJob Creation complete. Waiting for $($jobs.count) Jobs to finish processing. Output from Jobs will be displayed below once complete.`n`n" Get-Job -ID $jobs | Wait-Job | Receive-Job } function Export-Mofs { <# .SYNOPSIS .PARAMETER Rootpath Path to the root of the SCAR repository/codebase. .EXAMPLE Export-Mofs -RootPath "C:\SCAR" #> [cmdletbinding()] param( [Parameter()] [string] $RootPath = (Get-Location).Path, [Parameter()] [string] $TargetFolder, [Parameter()] [System.Collections.ArrayList] $SystemFiles ) $mofPath = (Resolve-Path -Path "$RootPath\*Artifacts\Mofs").Path $dscConfigPath = (Resolve-Path -Path "$RootPath\*Artifacts\DscConfigs").Path $allNodesDataFile = (Resolve-Path -Path "$dscConfigPath\Allnodes.psd1").path $SystemFiles = New-Object System.Collections.ArrayList $dscNodeConfigs = New-Object System.Collections.ArrayList $jobs = New-Object System.Collections.ArrayList if ($SystemFiles.count -lt 1) { if ('' -ne $TargetFolder) { $null = Get-Childitem "$RootPath\Systems\$TargetFolder\*.psd1" -Recurse | ForEach-Object {$null = $SystemFiles.add($_)} } else { $SystemFiles = New-Object System.Collections.ArrayList $null = Get-Childitem "$RootPath\Systems\*.psd1" -Recurse | ForEach-Object {$null = $SystemFiles.add($_)} } } foreach ($file in $SystemFiles) { $basename = $file.basename if (Test-Path "$dscConfigPath\$basename.ps1") { $null = Get-Item -path "$dscConfigPath\$basename.ps1" -erroraction SilentlyContinue | ForEach-Object {$null = $dscNodeConfigs.add($_)} } else { Write-Warning "No DSC Configuration script exists for $basename." continue } } foreach ($nodeConfig in $DscNodeConfigs) { $nodeName = $nodeConfig.BaseName $configPath = $nodeConfig.FullName $allNodesPath = $allNodesDataFile.FullName $SystemFile = (Resolve-Path -Path "$RootPath\Systems\*\$nodeName.psd1").Path $data = Invoke-Expression (Get-Content $SystemFile | Out-String) if ($null -ne $data.AppliedConfigurations) { Write-Output "`t`tStarting MOF Export Job - $($nodeConfig.BaseName)" try { Write-Output "`t`tStarting Job - Generate MOF and Meta MOF for $nodeName" $job = Start-Job -Scriptblock { $nodeConfig = $using:nodeConfig $nodeName = $using:nodeName $allNodesDataFile = $using:allNodesDataFile $mofPath = $using:mofPath $configPath = $using:ConfigPath # Execute each file into memory . "$configPath" # Execute each configuration with the corresponding data file Write-Output "`t`tGenerating MOF for $nodeName" $null = MainConfig -ConfigurationData $allNodesDataFile -OutputPath $mofPath -ErrorAction Stop 3> $null # Execute each Meta Configuration with the corresponding data file Write-Output "`t`tGenerating Meta MOF for $nodeName" $null = LocalConfigurationManager -ConfigurationData $allNodesDataFile -Outputpath $mofPath -Erroraction Stop 3> $null } $null = $jobs.add($job.id) } catch { Throw "Error occured executing $SystemFile to generate MOF.`n $($_)" } } } Write-Output "`n`tMOF Export Job Creation Complete. Waiting for $($jobs.count) to finish processing. Output from Jobs will be displayed below once complete.`n" Get-Job -ID $jobs | Wait-Job | Receive-Job } function Remove-ScarData { <# .SYNOPSIS Removes all existing artifacts the SCAR repository including System data, Compiled DSC Scripts, MOFs, and STIG Checklists All files removed from the following locations: - Systems - Artifacts\Mofs - Artifacts\DscConfigs - Artifacts\STIG Checklists .PARAMETER Rootpath Path to the root of the SCAR repository/codebase. .EXAMPLE Clean-ScarRepo -Rootpath "C:\SCAR" #> [cmdletBinding()] param ( [Parameter()] [string] $RootPath = (Get-Location).Path ) $artifactPath = (Resolve-Path "$RootPath\*Artifacts").Path $mofPath = (Resolve-Path "$ArtifactPath\Mofs").Path $cklPath = (Resolve-Path "$ArtifactPath\STIG Checklists").Path $dscConfigPath = (Resolve-Path "$ArtifactPath\DscConfigs").Path $SystemsPath = (Resolve-Path "$RootPath\Systems").Path $mofs = Get-Childitem -Path "$MofPath\*.mof" -Recurse $dscConfigs = Get-Childitem -Path "$dscConfigPath\*.ps1" -Recurse $checklists = Get-Childitem -Path "$cklPath\*.ckl" -Recurse $SystemFiles = Get-Childitem -Path "$SystemsPath\" -Recurse | Where {$_.name -notlike "*.keep*"} Write-Output "`n`tRemoving all systems and artifacts from the SCAR repository." foreach ($item in $removeItems) { Write-Output "Removing $($item.Name)" Remove-Item $item.Fullname -Confirm:$false -ErrorAction SilentlyContinue } Write-Output "`r`n" } function Import-DscModules { <# .SYNOPSIS Imports the required modules stored in the "Resources\Modules" folder on the local system. .PARAMETER Rootpath Path to the root of the SCAR repository/codebase. .EXAMPLE Import-DscModules -ModulePath "$RootPath\Resouces\Modules" #> [cmdletbinding()] param( [Parameter()] [String] $ModulePath ) $modules = @(Get-ChildItem -Path $ModulePath -Directory -Depth 0) Write-Output "`n`tBUILD: Importing required modules onto the local system." foreach ($module in $modules) { Write-Output "`t`tImporting Module - $($module.name)." $null = Import-Module $Module.name -Force } $null = Set-PowerCLIConfiguration -Scope AllUsers -ParticipateInCEIP $false -Confirm:$false Write-Output "`n" } function Compress-DscArtifacts { <# .SYNOPSIS Compresses the configuration scripts and MOFs generated by SCAR and stores them in the Archive folder .PARAMETER RootPath Path to the root of the SCAR repository/codebase. .EXAMPLE #> [cmdletbinding()] param( [Parameter()] [String] $RootPath = (Get-Location).Path ) # Archive the current MOF and build files in MMddyyyy_HHmm_DSC folder format $artifactPath = (Resolve-Path -Path "$Rootpath\*Artifacts").Path $datePath = (Get-Date -format "MMddyyyy_HHmm") Compress-Archive -Path $artifactPath -DestinationPath ("$archivePath\{0}_DSC.zip" -f $datePath) -Update } function Set-WinRMConfig { <# .SYNOPSIS This function will validate that the WinRM Service is running on target machines, that the MaxEnevelopeSize is set to 10000, and has a switch parameter to include the staging directory. .PARAMETER Rootpath Path to the root of the SCAR repository/codebase. .PARAMETER MaxEnevelopeSize MaxEnevelopeSize is a configuration setting in WinRM. SCAR requires this setting to be at (10000). This parameter allows you to set it to any number which easily allows you to reset WinRM to the default value (500). The default setting of this parameter is set to 10000. .PARAMETER IncludeStaging Switch Parameter that also includes the target machines in the Staging directory under 1.\Node Data .EXAMPLE Example Set-WinRmConfig -RootPath "C:\Your Repo\SCAR" In this example, the target machines (not including staging) would be validated that WinRM is running and the value of MaxEnvelopeSize is set to 10000. If it is set to a number other than 10000, it would be modified to match 10000. Example Set-WinRmConfig -RootPath "C:\Your Repo\SCAR" -MaxEnvelopeSize "500" In this example, the target machines (not including staging) would be validated that WinRM is running and the value of MaxEnvelopeSize is set to 500. If it is set to a number other than 500, it would be modified to match 500. Example Set-WinRmConfig -RootPath "C:\Your Repo\SCAR" -MaxEnvelopeSize "500" -IncludeStaging In this example, the target machines (including staging) would be validated that WinRM is running and the value of MaxEnvelopeSize is set to 500. If it is set to a number other than 500, it would be modified to match 500. #> [cmdletbinding()] param( [Parameter()] [array] $RootPath = (Get-Location).Path, [Parameter()] [string] $MaxEnvelopeSize = "10000", [Parameter()] [switch] $IncludeStaging, [Parameter()] [System.Collections.ArrayList] $TargetMachines ) $SystemsPath = (Resolve-Path -Path "$RootPath\Systems").Path $jobs = new-object System.Collections.ArrayList if ($null -eq $TargetMachines) { $TargetMachines = new-object System.Collections.ArrayList $null = (Get-Childitem -Path $SystemsPath -recurse | Where-Object { $_.FullName -like "*.psd1" -and $_.fullname -notlike "*staging*" }).basename | ForEach-Object {$null = $targetmachines.add($_)} } Write-Output "`tBUILD: Performing WinRM Validation and configuration." if ($IncludeStaging) { $null = (Get-ChildItem -Path $SystemsPath -recurse | Where-Object { $_.FullName -like "*.psd1" }).basename | ForEach-Object {$null = $targetmachines.add($_)} } foreach ($machine in $TargetMachines) { # Test for whether WinRM is enabled or not Write-Output "`t`tStarting Job - Configure WinRM MaxEnvelopeSizeKB on $machine" $job = Start-Job -Scriptblock { $machine = $using:machine $RootPath = $using:rootPath $MaxEnvelopeSize = $using:MaxEnvelopeSize try { $remoteEnvelopeSize = Invoke-Command $machine -ErrorAction Stop -Scriptblock { Return (Get-Item -Path WSMan:\localhost\MaxEnvelopeSizeKb).value } } catch { Write-Warning "`t`tUnable to connect to $machine. Ensure WinRM access is enabled." Continue } if ($MaxEnvelopeSize -eq $remoteEnvelopeSize) { Write-Output "`t`tCurrent MaxEnvelopSize size for $machine matches Desired State" Continue } else { Write-Output "`t`tCurrent MaxEnvelopSizeKB for $machine is $remoteEnvelopeSize. Updating to $MaxEnvelopeSize" try { $remoteEnvelopeSize = Invoke-Command $machine -ErrorAction Stop -ArgumentList $MaxEnvelopeSize -Scriptblock { param ($RemoteMaxEnvelopeSize) $machineEnvSize = (Get-Item -Path WSMan:\localhost\MaxEnvelopeSizeKb).value if ($machineEnvSize -ne $RemoteMaxEnvelopeSize) { Set-Item -Path WSMan:\localhost\MaxEnvelopeSizeKb -Value $RemoteMaxEnvelopeSize } return (Get-Item -Path WSMan:\localhost\MaxEnvelopeSizeKb).value } } catch { Write-Warning "Unable to set MaxEnvelopSize on $machine." continue } } } $null = $jobs.add($job.ID) } Get-Job -ID $jobs | Wait-Job | Receive-Job Write-Output "`tBUILD: WinRM Validation Complete.`n" } function Sync-DscModules { <# .SYNOPSIS This function validates the modules on the target machines. If the modules are not preset or are the incorrect version, the function will copy them to the target machines. .PARAMETER TargetMachines List of target machines. If not specificied, a list will be generated from configurations present in "C:\Your Repo\SCAR\Systems" .PARAMETER Rootpath Path to the root of the SCAR repository/codebase. .PARAMETER ModuleName Specify a single module to sync across target machines. .PARAMETER LocalHost Restrict Module sync to local computer/server. .EXAMPLE Example Sync-DscModules -rootpath "C:\SCAR" #> [cmdletbinding()] param( [Parameter()] [array] $TargetMachines, [Parameter()] [string] $RootPath = (Get-Location).Path, [Parameter()] [string] $ModuleName, [Parameter()] [switch] $LocalHost, [Parameter()] [switch] $Force ) $ModulePath = "$RootPath\Resources\Modules" $SystemsPath = "$RootPath\Systems" $jobs = @() if ($LocalHost) { $TargetMachines = "LocalHost" } elseif ($TargetMachines.count -lt 1) { $targetMachines = @(Get-ChildItem -Path "$SystemsPath\*.psd1" -Recurse | Where-Object { ($_.Fullname -notmatch "Staging") -and ($_.Fullname -Notlike "Readme*") }).basename } Write-Output "`tPerforming DSC Module Sync." foreach ($machine in $TargetMachines) { Write-Output "`t`tStarting Job - Syncing DSC Modules on $machine." $job = Start-Job -Scriptblock { $machine = $using:machine $RootPath = $using:RootPath $ModulePath = $using:ModulePath $Force = $using:Force $currentMachineCount += 1 if ($machine -eq 'localhost' -or $machine -eq $env:ComputerName) { $destinationPath = "C:\Program Files\WindowsPowershell\Modules" $destinationModulePaths = @( "C:\Program Files\WindowsPowershell\Modules" "C:\Program Files(x86)\WindowsPowershell\Modules" "C:\Windows\System32\WindowsPowershell\1.0\Modules" ) } else { $destinationPath = "\\$Machine\C$\Program Files\WindowsPowershell\Modules" $destinationModulePaths = @( "\\$Machine\C$\Program Files\WindowsPowershell\Modules" "\\$Machine\C$\Program Files(x86)\WindowsPowershell\Modules" "\\$Machine\C$\Windows\System32\WindowsPowershell\1.0\Modules" ) } $modulePathTest = Test-Path $ModulePath -ErrorAction SilentlyContinue $destinationPathTest = Test-Path $destinationPath -ErrorAction SilentlyContinue if ($destinationPathTest -and $modulePathTest) { if ("" -eq $ModuleName) { $modules = Get-Childitem -Path $modulePath -Directory -Depth 0 | Where-Object { $_.Name -match $ModuleName } } else { $modules = Get-Childitem -Path $modulePath -Directory -Depth 0 } foreach ($module in $modules) { [int]$completedChecks = 0 $moduleVersion = (Get-ChildItem -Path $Module.Fullname -Directory -Depth 0).name foreach ($destinationModulePath in $destinationModulePaths) { $modulecheck = Test-Path "$destinationPath\$($Module.name)" -ErrorAction SilentlyContinue if ($force) { Write-Output "`t`t[Force] Installing $($Module.name) on $machine." try { if ($moduleCheck) { Write-Output "`t`t[Force] Removing $($module.Name) from $machine" } $null = Copy-Item -Path $Module.Fullname -Destination $destinationPath -Container -Recurse -force -erroraction SilentlyContinue } catch { Write-Output "`t`tThere was an issue installing DSC Modules on $machine." throw $_ exit } continue } else { if ($moduleCheck) { $versionCheck = Test-Path "$destinationPath\$($Module.name)\$moduleVersion" -ErrorAction SilentlyContinue } else { $completedChecks += 1 } if ($modulecheck -and $versioncheck) { $copyModule = $false } elseif ($True -eq $moduleCheck -and ($false -eq $versionCheck)) { $destinationVersion = Get-Childitem "$destinationPath\$($Module.name)" -Depth 0 Write-Output "`t`t$($Module.name) found with version mismatch." Write-Output "`t`tRequired verion - $moduleVersion." Write-Output "`t`tInstalled version - $destinationVersion." Write-Output "`t`tRemoving $($Module.name) from $machine." $null = Remove-Item "$destinationModulePath\$($module.name)" -Confirm:$false -Recurse -Force -ErrorAction SilentlyContinue $copyModule = $true } } } if ($completedChecks -ge 3) { $copyModule = $true } if ($copyModule) { Write-Output "`t`tInstalling $($Module.name) on $Machine." $null = Copy-Item -Path $Module.Fullname -Destination $destinationPath -Container -Recurse -force -erroraction SilentlyContinue } } } else { Write-Output "`t`tThere was an issue connecting to $machine to transfer the required modules." Continue } } [array]$jobs += $job.ID } Write-Output "`n`t$($jobs.count) Module sync jobs created. Waiting for jobs to finish processing." do { Start-Sleep -Seconds 30 $completedJobs = (Get-Job -ID $jobs | where {$_.state -ne "Running"}).count $runningjobs = (Get-Job -ID $jobs | where {$_.state -eq "Running"}).count Write-Output "`t`tSystem Data Job Status:`t$runningJobs Jobs Currently Processing`t$completedJobs/$($jobs.count) Jobs Completed" } while ((Get-Job -ID $jobs).State -contains "Running") Write-Output "`n`t`t$($jobs.count) System Data jobs completed. Receiving job output" Get-Job -ID $jobs | Wait-Job | Receive-Job Write-Output "`tModule Validation Complete.`n" } function New-SystemData { <# .SYNOPSIS Generates configuration data based on a provided Organizational Unit DistinguishedName searchbase. .PARAMETER SearchBase Distringuised Name of the Active Directory Security Group you want to target for Node Data generation. Example -searchbase "CN=SCAR Target Machines,OU=_Domain Administration,DC=corp,DC=contoso,DC=com" .PARAMETER SystemsPath Path to the SCAR Node Data folder. Example -SystemsPath "C:\SCAR\Systems" .PARAMETER DomainName DomainName should be set to the domain name of your domain. Defaults to local system's Domain. Example -DomainName "corp.contoso" .PARAMETER ForestName ForestName should be set to the forest name of your domain. Defaults to local system's Forest. Example -ForestName "com" .EXAMPLE New-SystemData -Rootpath "C:\SCAR" -SearchBase "CN=Servers,CN=Enterprise Management,DC=contoso,DC=com" #> [cmdletbinding()] param( [Parameter()] [string] $SearchBase, [Parameter()] [switch] $LocalHost, [Parameter()] [switch] $RootOrgUnit, [Parameter()] [array] $ComputerName, [Parameter()] [string] [ValidateSet("MemberServers","AllServers","Full","OrgUnit","Targeted","Local")] $Scope = "MemberServers", [Parameter()] [string] $RootPath = (Get-Location).path, [Parameter()] [hashtable] $LcmSettings = @{ actionAfterReboot = "" agentId = "" allowModuleOverwrite = $True certificateID = "" configurationDownloadManagers = "" configurationID = "" configurationMode = "ApplyAndAutoCorrect" configurationModeFrequencyMins = "15" credential = "" debugMode = "" downloadManagerCustomData = "" downloadManagerName = "" lcmStateDetail = "" maximumDownloadSizeMB = "500" partialConfigurations = "" rebootNodeIfNeeded = $False refreshFrequencyMins = "30" refreshMode = "PUSH" reportManagers = "{}" resourceModuleManagers = "{}" signatureValidationPolicy = "" signatureValidations = "{}" statusRetentionTimeInDays = "10" } ) $SystemsPath = (Resolve-Path -Path "$RootPath\*Systems").Path $targetMachineOus = New-Object System.Collections.ArrayList $targetMachines = New-Object System.Collections.ArrayList $orgUnits = New-Object System.Collections.ArrayList Write-Output "`tBeginning DSC Configuration Data Build - Identifying Target Systems." if ('' -ne $SearchBase) {$Scope = "OrgUnit"} elseif ($LocalHost) {$Scope = "Local"} elseif ($ComputerName.count -eq 1) {$Scope = "Targeted"} switch ($Scope) { "OrgUnit" {$targetMachines = @(Get-ADComputer -SearchBase $SearchBase -Filter * -Properties "operatingsystem", "distinguishedname");break} "MemberServers" {$targetMachines = @(Get-ADComputer -Filter {OperatingSystem -like "**server*"} -Properties "operatingsystem", "distinguishedname" | Where-Object {$_.DistinguishedName -Notlike "*Domain Controllers*"});break} "AllServers" {$targetMachines = @(Get-ADComputer -Filter {OperatingSystem -like "**server*"} -Properties "operatingsystem", "distinguishedname");break} "Full" {$targetMachines = @(Get-ADComputer -Filter * -Properties "operatingsystem", "distinguishedname");break} "Targeted" {$targetMachines = @(Get-AdComputer -Identity "$ComputerName" -Properties "operatingsystem","distinguishedname");break} "Local" { $targetMachines = @( @{ Name = $env:computerName OperatingSystem = "Windows 10" distinguishedname = "Computers" } ) } } Write-Output "`tIdentifying Organizational Units for $($targetMachines.count) systems." if (-not($Localhost)) { if ($RootOrgUnit) { $orgUnits = Get-ADOrganizationalUnit -SearchBase $SearchBase -SearchScope OneLevel } else { foreach ($targetMachine in $targetMachines) { if ($targetMachine.distinguishedname -like "CN=$($targetMachine.name),OU=Servers*") { $null = $targetMachineOus.add($targetMachine.distinguishedname.Replace("CN=$($targetMachine.name),OU=Servers,","")) } elseif ($targetMachine.distinguishedName -like "*OU=Servers*") { $oustring = '' ($targetMachine.DistinguishedName.split(',')[3..10] | ForEach-Object { $null = $oustring += "$_," }) $null = $targetMachineOus.add($ouString.trimend(',')) } else { $null = $targetMachineOus.add($targetMachine.distinguishedname.Replace("CN=$($targetMachine.name),","")) } } $targetMachineOus | Get-Unique | ForEach-Object {Get-ADOrganizationalUnit -Filter {DistinguishedName -eq $_}} | ForEach-Object {$null = $orgunits.add($_)} if ($Scope -eq "Full") { $null = $orgUnits.add("Computers") } } Write-Output "`tSystem Count - $($targetMachines.Count)" } else { Write-Output "`tGenerating System Data for LocalHost." [array]$orgUnits = "LocalHost" } foreach ($ou in $orgUnits) { if ($LocalHost -or ($scope -eq "Local")) { $targetMachines = $env:ComputerName $ouFolder = "$SystemsPath\$env:computerName" } elseif ($ou -eq "Computers") { $targetMachines = (Get-ADComputer -Properties OperatingSystem -filter {OperatingSystem -like "*Windows 10*"} ).name $ouFolder = "$SystemsPath\Windows 10" } else { $targetMachines = (Get-ADComputer -filter * -SearchBase $ou.DistinguishedName).name $ouFolder = "$SystemsPath\$($ou.name)" } $jobs = New-Object System.Collections.ArrayList $ouMachineCount = $targetMachines.Count $currentMachineCount = 0 if ($targetMachines.Count -gt 0) { if (-not (Test-Path $ouFolder)) { $null = New-Item -Path $ouFolder -ItemType Directory -Force } if ($ou -eq "Computers") { Write-Output "`n`t$ou - $ouMachineCount Node(s) identified" } else { Write-Output "`n`t$($ou.name) - $ouMachineCount Node(s) identified" } foreach ($machine in $TargetMachines) { $currentMachineCount++ try { $null = Test-WsMan -Computername $machine -Authentication Default -ErrorAction Stop Write-Output "`t`tStarting Job ($currentMachineCount/$ouMachineCount) - Generate System Data for $machine" } catch { Write-Output "`t`tError - Unable to connect to $machine via WinRM." continue } $job = Start-Job -Scriptblock { $rootPath = $using:RootPath $machine = $using:machine $LcmSettings = $using:lcmsettings $ouFolder = $using:oufolder $LocalHost = $using:LocalHost $SystemsPath = $using:SystemsPath #region Get Applicable STIGs if ($LocalHost) { $applicableStigs = @(Get-ApplicableStigs -LocalHost) } else { $applicableStigs = @(Get-ApplicableStigs -Computername $machine) } switch -Wildcard ($applicableStigs) { "WindowsServer*" { $filter = "(&(objectCategory=computer)(objectClass=computer)(cn=$machine))" $distinguishedName = ([adsisearcher]$filter).FindOne().Properties.distinguishedname switch -Wildcard ($distinguishedName) { "*Domain Controllers*" {$StigType = "DomainController"; $osRole = "DC"} default {$StigType = "WindowsServer"; $osRole = "MS"} } $osVersion = ($ApplicableStigs | Where-Object {$_ -like "WindowsServer*"}).split("-")[1] $osStigFiles = @{ orgSettings = Get-StigFiles -Rootpath $RootPath -StigType $stigType -Version $osVersion -FileType "OrgSettings" -NodeName $machine xccdfPath = Get-StigFiles -Rootpath $RootPath -StigType $stigType -Version $osVersion -FileType "Xccdf" -NodeName $machine manualChecks = Get-StigFiles -Rootpath $RootPath -StigType $stigType -Version $osVersion -FileType "ManualChecks" -NodeName $machine } } "DotNetFramework" { $dotNetStigFiles = @{ orgsettings = Get-StigFiles -Rootpath $Rootpath -StigType "DotNetFramework" -Version 4 -FileType "OrgSettings" -NodeName $machine xccdfPath = Get-StigFiles -Rootpath $Rootpath -StigType "DotNetFramework" -Version 4 -FileType "Xccdf" -NodeName $machine manualChecks = Get-StigFiles -Rootpath $Rootpath -StigType "DotNetFramework" -Version 4 -FileType "ManualChecks" -NodeName $machine } } "InternetExplorer" { $ieStigFiles = @{ xccdfPath = Get-StigFiles -Rootpath $Rootpath -StigType "InternetExplorer" -Version 11 -FileType "Xccdf" -NodeName $machine orgSettings = Get-StigFiles -Rootpath $Rootpath -StigType "InternetExplorer" -Version 11 -FileType "OrgSettings" -NodeName $machine manualChecks = Get-StigFiles -Rootpath $Rootpath -StigType "InternetExplorer" -Version 11 -FileType "ManualChecks" -NodeName $machine } } "WindowsClient" { $Win10StigFiles = @{ orgSettings = Get-StigFiles -Rootpath $RootPath -StigType "WindowsClient" -Version $osVersion -FileType "OrgSettings" -NodeName $machine xccdfPath = Get-StigFiles -Rootpath $RootPath -StigType "WindowsClient" -Version $osVersion -FileType "Xccdf" -NodeName $machine manualChecks = Get-StigFiles -Rootpath $RootPath -StigType "WindowsClient" -Version $osVersion -FileType "ManualChecks" -NodeName $machine } } "WindowsDefender" { $WinDefenderStigFiles = @{ orgSettings = Get-StigFiles -Rootpath $RootPath -StigType "WindowsDefender" -FileType "OrgSettings" -NodeName $machine xccdfPath = Get-StigFiles -Rootpath $RootPath -StigType "WindowsDefender" -FileType "Xccdf" -NodeName $machine manualChecks = Get-StigFiles -Rootpath $RootPath -StigType "WindowsDefender" -FileType "ManualChecks" -NodeName $machine } } "WindowsFirewall" { $WinFirewallStigFiles = @{ orgSettings = Get-StigFiles -Rootpath $RootPath -StigType "WindowsFirewall" -FileType "OrgSettings" -NodeName $machine xccdfPath = Get-StigFiles -Rootpath $RootPath -StigType "WindowsFirewall" -FileType "Xccdf" -NodeName $machine manualChecks = Get-StigFiles -Rootpath $RootPath -StigType "WindowsFirewall" -FileType "ManualChecks" -NodeName $machine } } "WindowsDnsServer" { $WindowsDnsStigFiles = @{ orgSettings = Get-StigFiles -Rootpath $RootPath -StigType "WindowsDnsServer" -FileType "OrgSettings" -NodeName $machine xccdfPath = Get-StigFiles -Rootpath $RootPath -StigType "WindowsDnsServer" -FileType "Xccdf" -NodeName $machine manualChecks = Get-StigFiles -Rootpath $RootPath -StigType "WindowsDnsServer" -FileType "ManualChecks" -NodeName $machine } } "Office2016" { $word2016xccdfPath = Get-StigFiles -Rootpath $Rootpath -StigType "Office2016_Word" -Version 16 -FileType "Xccdf" -NodeName $machine $word2016orgSettings = Get-StigFiles -Rootpath $Rootpath -StigType "Office2016_Word" -Version 16 -FileType "OrgSettings" -NodeName $machine $word2016manualChecks = Get-StigFiles -Rootpath $Rootpath -StigType "Office2016_Word" -Version 16 -FileType "ManualChecks" -NodeName $machine $powerpoint2016xccdfPath = Get-StigFiles -Rootpath $Rootpath -StigType "Office2016_PowerPoint" -Version 16 -FileType "Xccdf" -NodeName $machine $powerpoint2016orgSettings = Get-StigFiles -Rootpath $Rootpath -StigType "Office2016_PowerPoint" -Version 16 -FileType "OrgSettings" -NodeName $machine $powerpoint2016manualChecks = Get-StigFiles -Rootpath $Rootpath -StigType "Office2016_PowerPoint" -Version 16 -FileType "ManualChecks" -NodeName $machine $outlook2016xccdfPath = Get-StigFiles -Rootpath $Rootpath -StigType "Office2016_Outlook" -Version 16 -FileType "Xccdf" -NodeName $machine $outlook2016orgSettings = Get-StigFiles -Rootpath $Rootpath -StigType "Office2016_Outlook" -Version 16 -FileType "OrgSettings" -NodeName $machine $outlook2016manualChecks = Get-StigFiles -Rootpath $Rootpath -StigType "Office2016_Outlook" -Version 16 -FileType "ManualChecks" -NodeName $machine $excel2016xccdfPath = Get-StigFiles -Rootpath $Rootpath -StigType "Office2016_Excel" -Version 16 -FileType "Xccdf" -NodeName $machine $excel2016orgSettings = Get-StigFiles -Rootpath $Rootpath -StigType "Office2016_Excel" -Version 16 -FileType "OrgSettings" -NodeName $machine $excel2016manualChecks = Get-StigFiles -Rootpath $Rootpath -StigType "Office2016_Excel" -Version 16 -FileType "ManualChecks" -NodeName $machine } "Office2013" { $word2013xccdfPath = Get-StigFiles -Rootpath $Rootpath -StigType "Office2013_word" -Version 15 -FileType "Xccdf" -NodeName $machine $word2013orgSettings = Get-StigFiles -Rootpath $Rootpath -StigType "Office2013_word" -Version 15 -FileType "OrgSettings" -NodeName $machine $word2013manualChecks = Get-StigFiles -Rootpath $Rootpath -StigType "Office2013_word" -Version 15 -FileType "ManualChecks" -NodeName $machine $powerpoint2013xccdfPath = Get-StigFiles -Rootpath $Rootpath -StigType "Office2013_powerpoint" -Version 15 -FileType "Xccdf" -NodeName $machine $powerpoint2013orgSettings = Get-StigFiles -Rootpath $Rootpath -StigType "Office2013_powerpoint" -Version 15 -FileType "OrgSettings" -NodeName $machine $powerpoint2013manualChecks = Get-StigFiles -Rootpath $Rootpath -StigType "Office2013_powerpoint" -Version 15 -FileType "ManualChecks" -NodeName $machine $outlook2013xccdfPath = Get-StigFiles -Rootpath $Rootpath -StigType "Office2013_outlook" -Version 15 -FileType "Xccdf" -NodeName $machine $outlook2013orgSettings = Get-StigFiles -Rootpath $Rootpath -StigType "Office2013_outlook" -Version 15 -FileType "OrgSettings" -NodeName $machine $outlook2013manualChecks = Get-StigFiles -Rootpath $Rootpath -StigType "Office2013_outlook" -Version 15 -FileType "ManualChecks" -NodeName $machine $excel2013xccdfPath = Get-StigFiles -Rootpath $Rootpath -StigType "Office2013_excel" -Version 15 -FileType "Xccdf" -NodeName $machine $excel2013orgSettings = Get-StigFiles -Rootpath $Rootpath -StigType "Office2013_excel" -Version 15 -FileType "OrgSettings" -NodeName $machine $excel2013manualChecks = Get-StigFiles -Rootpath $Rootpath -StigType "Office2013_excel" -Version 15 -FileType "ManualChecks" -NodeName $machine } "SQLServerInstance" { $version = "2016" $sqlInstanceStigFiles = @{ xccdfPath = Get-StigFiles -Rootpath $Rootpath -Version $Version -StigType "SqlServerInstance" -FileType "Xccdf" -NodeName $machine orgSettings = Get-StigFiles -Rootpath $Rootpath -Version $Version -StigType "SqlServerInstance" -FileType "OrgSettings" -NodeName $machine manualChecks = Get-StigFiles -Rootpath $Rootpath -Version $Version -StigType "SqlServerInstance" -FileType "ManualChecks" -NodeName $machine } } "SqlServerDatabase" { $sqlDatabaseStigFiles = @{ xccdfPath = Get-StigFiles -Rootpath $Rootpath -Version $Version -StigType "SqlServerDataBase" -FileType "Xccdf" -NodeName $machine orgSettings = Get-StigFiles -Rootpath $Rootpath -Version $Version -StigType "SqlServerDataBase" -FileType "OrgSettings" -NodeName $machine manualChecks = Get-StigFiles -Rootpath $Rootpath -Version $Version -StigType "SqlServerDataBase" -FileType "ManualChecks" -NodeName $machine } } "WebSite*" { $iisVersion = Invoke-Command -ComputerName $machine -Scriptblock { $iisData = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\InetStp" $localIisVersion = "$($iisData.MajorVersion).$($iisData.MinorVersion)" return $localiisVersion } $WebsiteStigFiles = @{ xccdfPath = Get-StigFiles -Rootpath $Rootpath -StigType "WebSite" -Version $iisVersion -FileType "Xccdf" -NodeName $machine orgSettings = Get-StigFiles -Rootpath $Rootpath -StigType "WebSite" -Version $iisVersion -FileType "OrgSettings" -NodeName $machine manualChecks = Get-StigFiles -Rootpath $Rootpath -StigType "WebSite" -Version $iisVersion -FileType "ManualChecks" -NodeName $machine } } "WebServer*" { [decimal]$iisVersion = Invoke-Command -ComputerName $machine -Scriptblock { $iisData = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\InetStp" $localIisVersion = "$($iisData.MajorVersion).$($iisData.MinorVersion)" return $localiisVersion } $webServerStigFiles = @{ xccdfPath = Get-StigFiles -Rootpath $Rootpath -StigType "WebServer" -Version $iisVersion -FileType "Xccdf" -NodeName $machine orgSettings = Get-StigFiles -Rootpath $Rootpath -StigType "WebServer" -Version $iisVersion -FileType "OrgSettings" -NodeName $machine manualChecks = Get-StigFiles -Rootpath $Rootpath -StigType "WebServer" -Version $iisVersion -FileType "ManualChecks" -NodeName $machine } } "McAfee" { $mcafeeStigFiles = @{ xccdfPath = Get-StigFiles -Rootpath $Rootpath -StigType "McAfee" -FileType "Xccdf" -NodeName $machine orgSettings = Get-StigFiles -Rootpath $Rootpath -StigType "McAfee" -FileType "OrgSettings" -NodeName $machine manualChecks = Get-StigFiles -Rootpath $Rootpath -StigType "McAfee" -FileType "ManualChecks" -NodeName $machine } } "FireFox" { $fireFoxStigFiles = @{ xccdfPath = Get-StigFiles -Rootpath $Rootpath -StigType "FireFox" -FileType "Xccdf" -NodeName $machine orgSettings = Get-StigFiles -Rootpath $Rootpath -StigType "FireFox" -FileType "OrgSettings" -NodeName $machine manualChecks = Get-StigFiles -Rootpath $Rootpath -StigType "FireFox" -FileType "ManualChecks" -NodeName $machine } } "Edge" { $edgeStigFiles = @{ xccdfPath = Get-StigFiles -Rootpath $Rootpath -StigType "Edge" -FileType "Xccdf" -NodeName $machine orgSettings = Get-StigFiles -Rootpath $Rootpath -StigType "Edge" -FileType "OrgSettings" -NodeName $machine manualChecks = Get-StigFiles -Rootpath $Rootpath -StigType "Edge" -FileType "ManualChecks" -NodeName $machine } } "Chrome" { $chromeStigFiles = @{ xccdfPath = Get-StigFiles -Rootpath $Rootpath -StigType "Chrome" -FileType "Xccdf" -NodeName $machine orgSettings = Get-StigFiles -Rootpath $Rootpath -StigType "Chrome" -FileType "OrgSettings" -NodeName $machine manualChecks = Get-StigFiles -Rootpath $Rootpath -StigType "Chrome" -FileType "ManualChecks" -NodeName $machine } } "Adobe" { $adobeStigFiles = @{ orgsettings = Get-StigFiles -Rootpath $Rootpath -StigType "Adobe" -FileType "OrgSettings" -NodeName $machine xccdfPath = Get-StigFiles -Rootpath $Rootpath -StigType "Adobe" -FileType "Xccdf" -NodeName $machine manualChecks = Get-StigFiles -Rootpath $Rootpath -StigType "Adobe" -FileType "ManualChecks" -NodeName $machine } } "OracleJRE" { $oracleStigFiles = @{ xccdfPath = Get-StigFiles -Rootpath $Rootpath -StigType "OracleJRE" -FileType "Xccdf" -NodeName $machine orgSettings = Get-StigFiles -Rootpath $Rootpath -StigType "OracleJRE" -FileType "OrgSettings" -NodeName $machine manualChecks = Get-StigFiles -Rootpath $Rootpath -StigType "OracleJRE" -FileType "ManualChecks" -NodeName $machine } } } #endregion #region Generate Configuration Data try { #region LocalHost Data if ($LocalHost) { $compName = $env:ComputerName $configContent = New-Object System.Collections.ArrayList $null = $configContent.add("@{`n`tNodeName = `"$compName`"`n`n") } else { $configContent = New-Object System.Collections.ArrayList $null = $configContent.add("@{`n`tNodeName = `"$machine`"") } #endregion Localhost Data #region AppliedConfigurations if ($null -ne $applicableSTIGs) { $null = $configContent.add("`n`n`tAppliedConfigurations =") $null = $configContent.add("`n`t@{") switch -Wildcard ($applicableSTIGs) { "WindowsServer*" { $null = $configContent.add("`n`n`t`tPowerSTIG_WindowsServer =") $null = $configContent.add("`n`t`t@{") $null = $configContent.add("`n`t`t`tOSRole = `"$osRole`"") $null = $configContent.add("`n`t`t`tOsVersion = `"$osVersion`"") $null = $configContent.add("`n`t`t`tOrgSettings = `"$($osStigFiles.orgSettings)`"") $null = $configContent.add("`n`t`t`tManualChecks = `"$($osStigFiles.manualChecks)`"") $null = $configContent.add("`n`t`t`txccdfPath = `"$($osStigFiles.xccdfPath)`"") $null = $configContent.add("`n`t`t}") } "InternetExplorer" { $null = $configContent.add("`n`n`t`tPowerSTIG_InternetExplorer =") $null = $configContent.add("`n`t`t@{") $null = $configContent.add("`n`t`t`tBrowserVersion = `"11`"") $null = $configContent.add("`n`t`t`tOrgSettings = `"$($ieStigFiles.orgSettings)`"") $null = $configContent.add("`n`t`t`txccdfPath = `"$($ieStigFiles.xccdfPath)`"") $null = $configContent.add("`n`t`t`tSkipRule = `"V-46477`"") $null = $configContent.add("`n`t`t}") } "DotnetFrameWork" { $null = $configContent.add("`n`n`t`tPowerSTIG_DotNetFrameWork =") $null = $configContent.add("`n`t`t@{") $null = $configContent.add("`n`t`t`tFrameWorkVersion = `"4`"") $null = $configContent.add("`n`t`t`txccdfPath = `"$($dotNetStigFiles.xccdfPath)`"") $null = $configContent.add("`n`t`t`tOrgSettings = `"$($dotNetStigFiles.orgSettings)`"") $null = $configContent.add("`n`t`t`tManualChecks = `"$($dotNetStigFiles.manualChecks)`"") $null = $configContent.add("`n`t`t}") } "WindowsClient" { $null = $configContent.add("`n`n`t`tPowerSTIG_WindowsClient =") $null = $configContent.add("`n`t`t@{") $null = $configContent.add("`n`t`t`tOSVersion = `"10`"") $null = $configContent.add("`n`t`t`tOrgSettings = `"$($win10StigFiles.orgSettings)`"") $null = $configContent.add("`n`t`t`tManualChecks = `"$($win10StigFiles.manualChecks)`"") $null = $configContent.add("`n`t`t`txccdfPath = `"$($win10StigFiles.xccdfPath)`"") $null = $configContent.add("`n`t`t}") } "WindowsDefender" { $null = $configContent.add("`n`n`t`tPowerSTIG_WindowsDefender =") $null = $configContent.add("`n`t`t@{") $null = $configContent.add("`n`t`t`tOrgSettings = `"$($winDefenderStigFiles.orgSettings)`"") $null = $configContent.add("`n`t`t`tManualChecks = `"$($winDefenderStigFiles.manualChecks)`"") $null = $configContent.add("`n`t`t`txccdfPath = `"$($winDefenderStigFiles.xccdfPath)`"") $null = $configContent.add("`n`t`t}") } "WindowsFirewall" { $null = $configContent.add("`n`n`t`tPowerSTIG_WindowsFirewall =") $null = $configContent.add("`n`t`t@{") $null = $configContent.add("`n`t`t`tOrgSettings = `"$($winFirewallStigFiles.orgSettings)`"") $null = $configContent.add("`n`t`t`tManualChecks = `"$($winFirewallStigFiles.manualChecks)`"") $null = $configContent.add("`n`t`t`txccdfPath = `"$($winFirewallStigFiles.xccdfPath)`"") $null = $configContent.add("`n`t`t}") } "WindowsDnsServer" { $null = $configContent.add("`n`n`t`tPowerSTIG_WindowsDNSServer =") $null = $configContent.add("`n`t`t@{") $null = $configContent.add("`n`t`t`tOsVersion = `"$osVersion`"") $null = $configContent.add("`n`t`t`txccdfPath = `"$($WindowsDnsStigFiles.xccdfPath)`"") $null = $configContent.add("`n`t`t`tOrgSettings = `"$($WindowsDnsStigFiles.orgSettings)`"") $null = $configContent.add("`n`t`t`tManualChecks = `"$($WindowsDnsStigFiles.manualChecks)`"") $null = $configContent.add("`n`t`t}") } "Office2016*" { $null = $configContent.add("`n`n`t`tPowerSTIG_Office2016_Excel =") $null = $configContent.add("`n`t`t@{") $null = $configContent.add("`n`t`t`tOrgSettings = `"$Excel2016OrgSettings`"") $null = $configContent.add("`n`t`t`tManualChecks = `"$Excel2016ManualChecks`"") $null = $configContent.add("`n`t`t`txccdfPath = `"$Excel2016xccdfPath`"") $null = $configContent.add("`n`t`t}") $null = $configContent.add("`n`n`t`tPowerSTIG_Office2016_Outlook =") $null = $configContent.add("`n`t`t@{") $null = $configContent.add("`n`t`t`tOrgSettings = `"$Outlook2016OrgSettings`"") $null = $configContent.add("`n`t`t`tManualChecks = `"$Outlook2016ManualChecks`"") $null = $configContent.add("`n`t`t`txccdfPath = `"$Outlook2016xccdfPath`"") $null = $configContent.add("`n`t`t}") $null = $configContent.add("`n`n`t`tPowerSTIG_Office2016_PowerPoint =") $null = $configContent.add("`n`t`t@{") $null = $configContent.add("`n`t`t`tOrgSettings = `"$PowerPoint2016OrgSettings`"") $null = $configContent.add("`n`t`t`tManualChecks = `"$PowerPoint2016ManualChecks`"") $null = $configContent.add("`n`t`t`txccdfPath = `"$PowerPoint2016xccdfPath`"") $null = $configContent.add("`n`t`t}") $null = $configContent.add("`n`n`t`tPowerSTIG_Office2016_Word =") $null = $configContent.add("`n`t`t@{") $null = $configContent.add("`n`t`t`tOrgSettings = `"$Word2016OrgSettings`"") $null = $configContent.add("`n`t`t`tManualChecks = `"$Word2016ManualChecks`"") $null = $configContent.add("`n`t`t`txccdfPath = `"$Word2016xccdfPath`"") $null = $configContent.add("`n`t`t}") } "Office2013*" { $null = $configContent.add("`n`n`t`tPowerSTIG_Office2013_Excel =") $null = $configContent.add("`n`t`t@{") $null = $configContent.add("`n`t`t`tOrgSettings = `"$Excel2013OrgSettings`"") $null = $configContent.add("`n`t`t`tManualChecks = `"$Excel2013ManualChecks`"") $null = $configContent.add("`n`t`t`txccdfPath = `"$Excel2013xccdfPath`"") $null = $configContent.add("`n`t`t}") $null = $configContent.add("`n`n`t`tPowerSTIG_Office2013_Outlook =") $null = $configContent.add("`n`t`t@{") $null = $configContent.add("`n`t`t`tOrgSettings = `"$Outlook2013OrgSettings`"") $null = $configContent.add("`n`t`t`tManualChecks = `"$Outlook2013ManualChecks`"") $null = $configContent.add("`n`t`t`txccdfPath = `"$Outlook2013xccdfPath`"") $null = $configContent.add("`n`t`t}") $null = $configContent.add("`n`n`t`tPowerSTIG_Office2013_PowerPoint =") $null = $configContent.add("`n`t`t@{") $null = $configContent.add("`n`t`t`tOrgSettings = `"$PowerPoint2013OrgSettings`"") $null = $configContent.add("`n`t`t`tManualChecks = `"$PowerPoint2013ManualChecks`"") $null = $configContent.add("`n`t`t`txccdfPath = `"$PowerPoint2013xccdfPath`"") $null = $configContent.add("`n`t`t}") $null = $configContent.add("`n`n`t`tPowerSTIG_Office2013_Word =") $null = $configContent.add("`n`t`t@{") $null = $configContent.add("`n`t`t`tOrgSettings = `"$Word2013OrgSettings`"") $null = $configContent.add("`n`t`t`tManualChecks = `"$Word2013ManualChecks`"") $null = $configContent.add("`n`t`t`txccdfPath = `"$Word2013xccdfPath`"") $null = $configContent.add("`n`t`t}") } "Website*" { $websites = @(Invoke-Command -Computername $Machine -Scriptblock { Import-Module WebAdministration;Return (Get-Childitem "IIS:\Sites").name}) $appPools = @(Invoke-Command -Computername $Machine -Scriptblock { Import-Module WebAdministration;Return (Get-Childitem "IIS:\AppPools").name}) [string]$allWebSites = '' [string]$allAppPools = '' if ($websites.count -gt 1) { foreach ($site in $websites) { $allWebsites += "`"$site`"," } $websiteString = $allWebsites.TrimEnd(",") } else { $websiteString = "`"$websites`"" } if ($appPools.count -gt 1) { foreach ($appPool in $appPools) { $allAppPools += "`"$appPool`"," } $appPoolString = $allAppPools.TrimEnd(",") } else { $appPoolString = "`"$appPools`"" } $null = $configContent.add("`n`n`t`tPowerSTIG_WebSite =") $null = $configContent.add("`n`t`t@{") $null = $configContent.add("`n`t`t`tIISVersion = `"$IISVersion`"") $null = $configContent.add("`n`t`t`tWebsiteName = $websiteString") $null = $configContent.add("`n`t`t`tWebAppPool = $appPoolString") $null = $configContent.add("`n`t`t`tXccdfPath = `"$($webSiteStigFiles.XccdfPath)`"") $null = $configContent.add("`n`t`t`tOrgSettings = `"$($webSiteStigFiles.OrgSettings)`"") $null = $configContent.add("`n`t`t`tManualChecks = `"$($webSiteStigFiles.ManualChecks)`"") $null = $configContent.add("`n`t`t}") } "WebServer*" { $null = $configContent.add("`n`n`t`tPowerSTIG_WebServer =") $null = $configContent.add("`n`t`t@{") $null = $configContent.add("`n`t`t`tSkipRule = `"V-214429`"") $null = $configContent.add("`n`t`t`tIISVersion = `"$IISVersion`"") $null = $configContent.add("`n`t`t`tLogPath = `"C:\InetPub\Logs`"") $null = $configContent.add("`n`t`t`tXccdfPath = `"$($webServerStigFiles.XccdfPath)`"") $null = $configContent.add("`n`t`t`tOrgSettings = `"$($webServerStigFiles.OrgSettings)`"") $null = $configContent.add("`n`t`t`tManualChecks = `"$($webServerStigFiles.ManualChecks)`"") $null = $configContent.add("`n`t`t}") } "FireFox" { $null = $configContent.add("`n`n`t`tPowerSTIG_Firefox =") $null = $configContent.add("`n`t`t@{") $null = $configContent.add("`n`t`t`tInstallDirectory = `"C:\Program Files\Mozilla Firefox`"") $null = $configContent.add("`n`t`t`txccdfPath = `"$($firefoxStigFiles.XccdfPath)`"") $null = $configContent.add("`n`t`t`tOrgSettings = `"$($firefoxStigFiles.OrgSettings)`"") $null = $configContent.add("`n`t`t`tManualChecks = `"$($firefoxStigFiles.ManualChecks)`"") $null = $configContent.add("`n`t`t}") } "Edge" { $null = $configContent.add("`n`n`t`tPowerSTIG_Edge =") $null = $configContent.add("`n`t`t@{") $null = $configContent.add("`n`t`t`tOrgSettings = `"$($edgeStigFiles.orgSettings)`"") $null = $configContent.add("`n`t`t`tManualChecks = `"$($edgeStigFiles.manualChecks)`"") $null = $configContent.add("`n`t`t`txccdfPath = `"$($edgeStigFiles.xccdfPath)`"") $null = $configContent.add("`n`t`t}") } "Chrome" { $null = $configContent.add("`n`n`t`tPowerSTIG_Chrome =") $null = $configContent.add("`n`t`t@{") $null = $configContent.add("`n`t`t`tOrgSettings = `"$($chromeStigFiles.orgSettings)`"") $null = $configContent.add("`n`t`t`tManualChecks = `"$($chromeStigFiles.manualChecks)`"") $null = $configContent.add("`n`t`t`txccdfPath = `"$($chromeStigFiles.xccdfPath)`"") $null = $configContent.add("`n`t`t}") } "Adobe" { $null = $configContent.add("`n`n`t`tPowerSTIG_Adobe =") $null = $configContent.add("`n`t`t@{") $null = $configContent.add("`n`t`t`tAdobeApp = `"AcrobatReader`"") $null = $configContent.add("`n`t`t`txccdfPath = `"$($adobeStigFiles.XccdfPath)`"") $null = $configContent.add("`n`t`t`tOrgSettings = `"$($adobeStigFiles.OrgSettings)`"") $null = $configContent.add("`n`t`t`tManualChecks = `"$($adobeStigFiles.ManualChecks)`"") $null = $configContent.add("`n`t`t}") } "OracleJRE" { $null = $configContent.add("`n`n`t`tPowerSTIG_OracleJRE =") $null = $configContent.add("`n`t`t@{") $null = $configContent.add("`n`t`t`tConfigPath = `"$ConfigPath`"") $null = $configContent.add("`n`t`t`tPropertiesPath = `"$PropertiesPath`"") $null = $configContent.add("`n`t`t`tXccdfPath = `"$($oracleStigFiles.XccdfPath)`"") $null = $configContent.add("`n`t`t`tOrgSettings = `"$($oracleStigFiles.OrgSettings)`"") $null = $configContent.add("`n`t`t`tManualChecks = `"$($oracleStigFiles.ManualChecks)`"") $null = $configContent.add("`n`t`t}") } # "Mcafee" # { # $null = $configContent.add("`n`n`t`tPowerSTIG_McAfee =") # $null = $configContent.add("`n`t`t@{") # $null = $configContent.add("`n`t`t`tTechnology = `"VirusScan`"") # $null = $configContent.add("`n`t`t`tVersion = `"8.8`"") # $null = $configContent.add("`n`t`t`tXccdfPath = `"$($mcafeeStigFiles.XccdfPath)`"") # $null = $configContent.add("`n`t`t`tOrgSettings = `"$($mcafeeStigFiles.OrgSettings)`"") # $null = $configContent.add("`n`t`t`tManualChecks = `"$($mcafeeStigFiles.ManualChecks)`"") # $null = $configContent.add("`n`t`t}") # } # "SqlServerInstance" # { # $null = $configContent.add("`n`n`t`tPowerSTIG_SQLServer_Instance =") # $null = $configContent.add("`n`t`t@{") # $null = $configContent.add("`n`t`t`tSqlRole = `"$sqlRole`"") # $null = $configContent.add("`n`t`t`tSqlVersion = `"$sqlVersion`"") # $null = $configContent.add("`n`t`t`tServerInstance = `"$sqlServerInstance`"") # $null = $configContent.add("`n`t`t`tXccdfPath = `"$($sqlinstanceStigFiles.XccdfPath)`"") # $null = $configContent.add("`n`t`t`tOrgSettings = `"$($sqlinstanceStigFiles.OrgSettings)`"") # $null = $configContent.add("`n`t`t`tManualChecks = `"$($sqlinstanceStigFiles.ManualChecks)`"") # $null = $configContent.add("`n`t`t}") # $null = $configContent.add("`n") # } # "SqlServerDatabase" # { # $null = $configContent.add("`n`n`t`tPowerSTIG_SQLServer_Database =") # $null = $configContent.add("`n`t`t@{") # $null = $configContent.add("`n`t`t`tSqlRole = `"$sqlRole`"") # $null = $configContent.add("`n`t`t`tSqlVersion = `"$sqlVersion`"") # $null = $configContent.add("`n`t`t`tServerInstance = `"$sqlServerInstance`"") # $null = $configContent.add("`n`t`t`tXccdfPath = `"$($sqlDatabseStigFiles.XccdfPath)`"") # $null = $configContent.add("`n`t`t`tOrgSettings = `"$($sqlDatabaseStigFiles.OrgSettings)`"") # $null = $configContent.add("`n`t`t`tManualChecks = `"$($sqlDatabaseStigFiles.ManualChecks)`"") # $null = $configContent.add("`n`t`t}") # $null = $configContent.add("`n") # } } $null = $configContent.add("`n`t}") } #endregion AppliedConfigurations #region LocalConfigurationManager $null = $configContent.add("`n`n`tLocalConfigurationManager =") $null = $configContent.add("`n`t@{") foreach ($setting in $LcmSettings.Keys) { if (($Null -ne $LcmSettings.$setting) -and ("{}" -ne $lcmsettings.$setting) -and ("" -ne $LcmSettings.$setting)) { $null = $null = $configContent.add("`n`t`t$($setting)") if ($setting.Length -lt 8) {$null = $configContent.add("`t`t`t`t`t`t`t= ")} elseif ($setting.Length -lt 12) {$null = $configContent.add("`t`t`t`t`t`t= ")} elseif ($setting.Length -lt 16) {$null = $configContent.add("`t`t`t`t`t= ")} elseif ($setting.Length -lt 20) {$null = $configContent.add("`t`t`t`t= ")} elseif ($setting.Length -lt 24) {$null = $configContent.add("`t`t`t= ")} elseif ($setting.Length -lt 28) {$null = $configContent.add("`t`t= ")} elseif ($setting.Length -lt 32) {$null = $configContent.add("`t= ")} if (($LcmSettings.$setting -eq $true) -or ($LcmSettings.$setting -eq $false)) { $null = $configContent.add("`$$($LcmSettings.$setting)") } else { $null = $configContent.add("`"$($LcmSettings.$setting)`"") } } } $null = $configContent.add("`n`t}") #endregion LocalConfigurationManager #region Hardware Resources # Network Interfaces $nics = Get-CimInstance -ComputerName $machine -ClassName Win32_NetworkAdapterConfiguration -Filter "IPEnabled = 'True'" | select -property * $null = $configContent.add("`n`n`tNetworkInterfaces = `n`t@(") $nicCount = 0 foreach ($nic in $nics) { $nicCount++ $nicName = "$machine-nic-0$nicCount" $nicIP = $nic.ipaddress | Select -first 1 $nicGateway = $nic.DefaultIpGateway | Select -first 1 $nicMacAddress = $nic.MacAddress | Select -first 1 $nicSubnet = $nic.IPSubnet | Select -first 1 if ($nicCount -gt 1) { $null = $configContent.add("`n") } $null = $configContent.add("`n`t`t@{") $null = $configContent.add("`n`t`t`tName = `"$nicName`"") $null = $configContent.add("`n`t`t`tIpAddress = `"$nicIP`"") $null = $configContent.add("`n`t`t`tDefaultGateway = `"$nicGateway`"") $null = $configContent.add("`n`t`t`tMacAddress = `"$nicMacAddress`"") $null = $configContent.add("`n`t`t}") } $null = $configContent.add("`n`t)") # Disks $disks = Get-CimInstance -ComputerName $machine -ClassName Win32_DiskDrive | select -property * $null = $configContent.add("`n`n`tDisks = `n`t@(") $diskcount = 0 foreach ($disk in $disks) { $diskCount++ $diskName = "$machine-disk-0$diskCount" $diskSize = [math]::Round($disk.Size/1GB).tostring() + "GB" if ($diskCount -gt 1) { $null = $configContent.add("`n") } $null = $configContent.add("`n`t`t@{") $null = $configContent.add("`n`t`t`tName = `"$diskName`"") $null = $configContent.add("`n`t`t`tSize = `"$diskSize`"") $null = $configContent.add("`n`t`t}") } $null = $configContent.add("`n`t)") #endregion Hardware Resources $null = $configContent.add("`n}") if ($LocalHost) { $compName = $env:ComputerName $SystemFile = New-Item -Path "$SystemsPath\$CompName\$CompName.psd1" -Force } else { $SystemFile = New-Item -Path "$ouFolder\$machine.psd1" -Force } $null = Set-Content -nonewline -path $SystemFile $configContent Write-Output "`t`t$machine - System Data successfully generated." } catch { Write-Output "`t`t$machine - Error Generating System Data." } } $null = $jobs.add($job.Id) } Write-Output "`t`tJob creation for $($ou.name) System Data is complete. Waiting on $($jobs.count) jobs to finish processing." if ($jobs.count -ge 1) { do { $completedJobs = (Get-Job -ID $jobs | Where-Object {$_.state -ne "Running"}).count $runningjobs = (Get-Job -ID $jobs | Where-Object {$_.state -eq "Running"}).count Write-Output "`t`t$($ou.Name) System Data Status:`t$runningJobs Jobs Currently Processing`t$completedJobs/$($jobs.count) Jobs Completed" Start-Sleep -Seconds 30 } while ((Get-Job -ID $jobs).State -contains "Running") Write-Output "`t`t$($jobs.count) System Data jobs completed. Outputting Results." Get-Job -ID $jobs | Wait-Job | Receive-Job } else { Write-Output "`t`tNo Jobs Generated for $($ou.Name)" } } } } function Get-StigFiles { param( [Parameter()] [string] $FileType, [Parameter()] [string] $StigType, [Parameter()] [string] $RootPath = (Get-Location).Path, [Parameter()] [string] $Version, [Parameter()] [string] $NodeName ) $xccdfArchive = (Resolve-Path -Path "$RootPath\*Resources\Stig Data\XCCDFs").Path $manualCheckFolder = (Resolve-Path -Path "$RootPath\*Resources\Stig Data\Manual Checks").Path $orgSettingsFolder = (Resolve-Path -Path "$RootPath\*Resources\Stig Data\Organizational Settings").Path $stigFilePath = '' switch ($fileType) { "Xccdf" { switch -WildCard ($stigType) { "WindowsServer" { $xccdfContainer = (Resolve-Path -Path "$xccdfArchive\Windows.Server.$version" -ErrorAction SilentlyContinue).Path switch ($version) { "2012R2" {$xccdfs = (Get-ChildItem -Path "$xccdfContainer\*.xml" | Where-Object { $_.name -notlike "*DC*" }).Name} "2016" {$xccdfs = (Get-ChildItem -Path "$xccdfContainer\*$version`_STIG*.xml").Name} "2019" {$xccdfs = (Get-ChildItem -Path "$xccdfContainer\*$version`_STIG*.xml").Name} } } "DomainController" { $xccdfContainer = (Resolve-Path -Path "$xccdfArchive\Windows.Server.$version" -ErrorAction SilentlyContinue).Path switch ($version) { "2012R2" {$xccdfs = (Get-ChildItem -Path "$xccdfContainer\*.xml" | Where-Object { $_.name -like "*DC*" }).Name} "2016" {$xccdfs = (Get-ChildItem -Path "$xccdfContainer\*$version`_STIG*.xml").Name} "2019" {$xccdfs = (Get-ChildItem -Path "$xccdfContainer\*$version`_STIG*.xml").Name} } } "WindowsClient" { $xccdfContainer = (Resolve-Path -Path "$xccdfArchive\Windows.Client" -ErrorAction SilentlyContinue).Path $xccdfs = (Get-ChildItem -Path "$xccdfContainer\*.xml").name } "DotNetFramework" { $xccdfContainer = (Resolve-Path -Path "$xccdfArchive\DotNet" -ErrorAction SilentlyContinue).Path $xccdfs = (Get-ChildItem -Path "$xccdfContainer\*.xml" | Where-Object { $_.name -like "*$Version*STIG*Manual-xccdf.xml"}).name } "InternetExplorer" { $xccdfContainer = (Resolve-Path -Path "$xccdfArchive\$StigType" -ErrorAction SilentlyContinue).Path $xccdfs = (Get-ChildItem -Path "$xccdfContainer\*.xml" | Where-Object { $_.name -like "*xccdf.xml"}).name } "WebServer" { $xccdfContainer = (Resolve-Path -Path "$xccdfArchive\Web Server" -ErrorAction SilentlyContinue).Path $xccdfs = (Get-ChildItem -Path "$xccdfContainer\*.xml" | Where-Object { $_.name -like "*$($Version.replace(".","-"))*Server*xccdf.xml"}).name } "WebSite" { $xccdfContainer = (Resolve-Path -Path "$xccdfArchive\Web Server" -ErrorAction SilentlyContinue).Path $xccdfs = (Get-ChildItem -Path "$xccdfContainer\*.xml" | Where-Object { $_.name -like "*$($Version.replace(".","-"))*Site*xccdf.xml"}).name } "FireFox" { $xccdfContainer = (Resolve-Path -Path "$xccdfArchive\browser" -ErrorAction SilentlyContinue).Path $xccdfs = (Get-ChildItem -Path "$xccdfContainer\*.xml" | Where-Object { $_.name -like "*FireFox*xccdf.xml"}).name } "Edge" { $xccdfContainer = (Resolve-Path -Path "$xccdfArchive\Edge" -ErrorAction SilentlyContinue).Path $xccdfs = (Get-ChildItem -Path "$xccdfContainer\*.xml" | Where-Object { $_.name -like "*edge*xccdf.xml"}).name } "Chrome" { $xccdfContainer = (Resolve-Path -Path "$xccdfArchive\Chrome" -ErrorAction SilentlyContinue).Path $xccdfs = (Get-ChildItem -Path "$xccdfContainer\*.xml" | Where-Object { $_.name -like "*chrome*xccdf.xml"}).name } "Adobe" { $xccdfContainer = (Resolve-Path -Path "$xccdfArchive\adobe" -ErrorAction SilentlyContinue).Path $xccdfs = (Get-ChildItem -Path "$xccdfContainer\*.xml" | Where-Object { $_.name -like "*adobe*xccdf.xml"}).name } "McAfee" { $xccdfContainer = (Resolve-Path -Path "$xccdfArchive\$StigType" -ErrorAction SilentlyContinue).Path $xccdfs = (Get-ChildItem -Path "$xccdfContainer\*.xml" | Where-Object { $_.name -like "*McAfee*xccdf.xml"}).name } "Office*" { $officeApp = $stigType.split('_')[1] $officeVersion = $stigType.split('_')[0].Replace('Office',"") $xccdfContainer = (Resolve-Path -Path "$xccdfArchive\Office" -ErrorAction SilentlyContinue).Path $xccdfs = (Get-ChildItem -Path "$xccdfContainer\*$officeApp*.xml" | Where-Object { $_.name -like "*$officeversion*"}).name } "OracleJRE" { $xccdfContainer = (Resolve-Path -Path "$xccdfArchive\$StigType" -ErrorAction SilentlyContinue).Path $xccdfs = (Get-ChildItem -Path "$xccdfContainer\*.xml" | Where-Object { $_.name -like "*Oracle*JRE*$version*xccdf.xml"}).name } "WindowsDefender" { $xccdfContainer = (Resolve-Path -Path "$xccdfArchive\Windows.Defender" -ErrorAction SilentlyContinue).Path $xccdfs = (Get-ChildItem -Path "$xccdfContainer\*.xml" | Where-Object { $_.name -like "*Windows*Defender*xccdf.xml"}).name } "WindowsFirewall" { $xccdfContainer = (Resolve-Path -Path "$xccdfArchive\Windows.Firewall" -ErrorAction SilentlyContinue).Path $xccdfs = (Get-ChildItem -Path "$xccdfContainer\*.xml" | Where-Object { $_.name -like "*Windows*Firewall*xccdf.xml"}).name } "WindowsDNSServer" { $xccdfContainer = (Resolve-Path -Path "$xccdfArchive\Windows.Dns" -ErrorAction SilentlyContinue).Path $xccdfs = (Get-ChildItem -Path "$xccdfContainer\*.xml" | Where-Object { $_.name -like "*xccdf.xml"}).name } "SqlServerInstance" { $xccdfContainer = (Resolve-Path -Path "$xccdfArchive\SQL Server" -ErrorAction SilentlyContinue).Path $xccdfs = (Get-ChildItem -Path "$xccdfContainer\*.xml" | Where-Object { $_.name -like "*SQL*$Version*Instance*xccdf.xml"}).name } "SqlServerDatabase" { $xccdfContainer = (Resolve-Path -Path "$xccdfArchive\SQL Server" -ErrorAction SilentlyContinue).Path $xccdfs = (Get-ChildItem -Path "$xccdfContainer\*.xml" | Where-Object { $_.name -like "*SQL*$version*Database*xccdf.xml"}).name } } $stigVersions = $xccdfs | Select-String "V(\d+)R(\d+)" -AllMatches | Foreach-Object {$_.Matches.Value} $latestVersion = ($stigversions | Measure-Object -Maximum).Maximum $xccdfFileName = $xccdfs | Where { $_ -like "*$latestVersion*-xccdf.xml"} $stigFilePath = "$xccdfContainer\$xccdfFileName" } "ManualChecks" { switch -wildcard ($stigType) { "WindowsServer" { $osVersion = $version.replace('R2','') $manualCheckContainer = (Resolve-Path -Path "$manualCheckFolder\Windows.Server.$Version" -ErrorAction SilentlyContinue).Path $manualCheckFiles = (Get-ChildItem -Path $manualCheckContainer | Where-Object {$_.name -like "*$osVersion*MS*.psd1"}).basename } "DomainController" { $manualCheckContainer = (Resolve-Path -Path "$manualCheckFolder\Windows`.Server`.$version" -ErrorAction SilentlyContinue).Path $manualCheckFiles = (Get-ChildItem -Path $manualCheckContainer | Where-Object {$_.name -like "*$version*DC*.psd1"}).basename $stigVersions = $manualCheckFiles | Select-String "(\d+)R(\d+)" -AllMatches | Foreach-Object {$_.Matches.Value} $latestVersion = ($stigVersions | Measure-Object -Maximum).Maximum $manualCheckFileName = $manualCheckFiles | Where-Object { $_ -like "*WindowsServer*$latestVersion*" } $stigFilePath = "$manualCheckContainer\$manualCheckFileName.psd1" } "WindowsClient" { $manualCheckContainer = (Resolve-Path -Path "$manualCheckFolder\WindowsClient" -ErrorAction SilentlyContinue).Path $manualCheckFiles = (Get-ChildItem -Path $manualCheckContainer).basename } "DotNetFramework" { "$manualCheckFolder\Dotnet" $manualCheckContainer = (Resolve-Path -Path "$manualCheckFolder\Dotnet" -ErrorAction SilentlyContinue).Path $manualCheckFiles = (Get-ChildItem -Path $manualCheckContainer | Where-Object { $_.name -like "*Dot*Net*ManualChecks.psd1"}).basename } "InternetExplorer" { $manualCheckContainer = (Resolve-Path -Path "$manualCheckFolder\InternetExplorer" -ErrorAction SilentlyContinue).Path $manualCheckFiles = (Get-ChildItem -Path $manualCheckContainer | Where-Object { $_.name -like "*IE*11*ManualChecks.psd1"}).basename } "WebServer" { $iisVersion = $version.replace(".","-") $manualCheckContainer = (Resolve-Path -Path "$manualCheckFolder\WebServer" -ErrorAction SilentlyContinue).Path $manualCheckFiles = (Get-ChildItem -Path $manualCheckContainer | Where-Object { $_.name -like "*$iisVersion*-ManualChecks.psd1"}).basename } "WebSite" { $iisVersion = $version.replace(".","-") $manualCheckContainer = (Resolve-Path -Path "$manualCheckFolder\WebSite" -ErrorAction SilentlyContinue).Path $manualCheckFiles = (Get-ChildItem -Path $manualCheckContainer | Where-Object { $_.name -like "*$iisVersion*ManualChecks.psd1"}).basename } "FireFox" { $manualCheckContainer = (Resolve-Path -Path "$manualCheckFolder\FireFox" -ErrorAction SilentlyContinue).Path $manualCheckFiles = (Get-ChildItem -Path $manualCheckContainer | Where-Object { $_.name -like "*FireFox*ManualChecks.psd1"}).basename } "Edge" { $manualCheckContainer = (Resolve-Path -Path "$manualCheckFolder\Edge" -ErrorAction SilentlyContinue).Path $manualCheckFiles = (Get-ChildItem -Path $manualCheckContainer | Where-Object { $_.name -like "*Edge*ManualChecks.psd1"}).basename } "Chrome" { $manualCheckContainer = (Resolve-Path -Path "$manualCheckFolder\Chrome" -ErrorAction SilentlyContinue).Path $manualCheckFiles = (Get-ChildItem -Path $manualCheckContainer | Where-Object { $_.name -like "*Chrome*ManualChecks.psd1"}).basename } "Adobe" { $manualCheckContainer = (Resolve-Path -Path "$manualCheckFolder\adobe" -ErrorAction SilentlyContinue).Path $manualCheckFiles = (Get-ChildItem -Path $manualCheckContainer | Where-Object { $_.name -like "*adobe*ManualChecks.psd1"}).basename } "McAfee" { $manualCheckContainer = (Resolve-Path -Path "$manualCheckFolder\McAfee" -ErrorAction SilentlyContinue).Path $manualCheckFiles = (Get-ChildItem -Path $manualCheckContainer | Where-Object { $_.name -like "*McAfee*ManualChecks.psd1"}).basename } "Office2016*" { $officeApp = $stigType.split('_')[1] $officeVersion = $stigType.split('_')[0].TrimStart("office") $manualCheckContainer = (Resolve-Path -Path "$manualCheckFolder\Office" -ErrorAction SilentlyContinue).Path $manualCheckFiles = (Get-ChildItem -Path $manualCheckContainer | Where-Object { $_.name -like "*$officeApp*ManualChecks.psd1"}).basename $stigVersions = $manualCheckFiles | Select-String "(\d+)R(\d+)" -AllMatches | Foreach-Object {$_.Matches.Value} $latestVersion = ($stigVersions | Measure-Object -Maximum).Maximum $manualCheckFileName = $manualCheckFiles | Where-Object { $_ -like "*$officeApp*$latestVersion*" } $stigFilePath = "$manualCheckContainer\$manualCheckFileName.psd1" } "Office2013*" { $officeApp = $stigType.split('_')[1] $officeVersion = $stigType.split('_')[0].TrimStart("office") $manualCheckContainer = (Resolve-Path -Path "$manualCheckFolder\Office_2013" -ErrorAction SilentlyContinue).Path $manualCheckFiles = (Get-ChildItem -Path $manualCheckContainer | Where-Object { $_.name -like "*$officeApp*ManualChecks.psd1"}).basename $stigVersions = $manualCheckFiles | Select-String "(\d+)R(\d+)" -AllMatches | Foreach-Object {$_.Matches.Value} $latestVersion = ($stigVersions | Measure-Object -Maximum).Maximum $manualCheckFileName = $manualCheckFiles | Where-Object { $_ -like "*$officeApp*$latestVersion*" } $stigFilePath = "$manualCheckContainer\$manualCheckFileName.psd1" } "OracleJRE" { $manualCheckContainer = (Resolve-Path -Path "$manualCheckFolder\OracleJRE" -ErrorAction SilentlyContinue).Path $manualCheckFiles = (Get-ChildItem -Path $manualCheckContainer | Where-Object { $_.name -like "*OracleJRE*$version*.psd1"}).basename } "WindowsDefender" { $manualCheckContainer = (Resolve-Path -Path "$manualCheckFolder\Windows.Defender" -ErrorAction SilentlyContinue).Path $manualCheckFiles = (Get-ChildItem -Path $manualCheckContainer | Where-Object { $_.name -like "*Windows*Defender*ManualChecks.psd1"}).basename } "WindowsFirewall" { $manualCheckContainer = (Resolve-Path -Path "$manualCheckFolder\Windows.Firewall" -ErrorAction SilentlyContinue).Path $manualCheckFiles = (Get-ChildItem -Path $manualCheckContainer | Where-Object { $_.name -like "*Windows*Firewall*ManualChecks.psd1"}).basename } "WindowsDNSServer" { $manualCheckContainer = (Resolve-Path -Path "$manualCheckFolder\Windows.Dns" -ErrorAction SilentlyContinue).Path $manualCheckFiles = (Get-ChildItem -Path $manualCheckContainer | Where-Object { $_.name -like "*Domain*Naming*Sytem*ManualChecks.psd1"}).basename } "SqlServerInstance" { $manualCheckContainer = (Resolve-Path -Path "$manualCheckFolder\SqlServer" -ErrorAction SilentlyContinue).Path $manualCheckFiles = (Get-ChildItem -Path $manualCheckContainer | Where-Object { $_.name -like "*SQL*$version*Database*ManualChecks.psd1"}).basename } "SqlServerDatabase" { $manualCheckContainer = (Resolve-Path -Path "$manualCheckFolder\SqlServer" -ErrorAction SilentlyContinue).Path $manualCheckFiles = (Get-ChildItem -Path $manualCheckContainer | Where-Object { $_.name -like "*SQL*$version*Database*ManualChecks.psd1"}).basename } } if ("" -eq $stigFilePath) { $stigVersions = $manualCheckFiles | Select-String "(\d+)\.(\d+)" -AllMatches | Foreach-Object {$_.Matches.Value} $latestVersion = ($stigVersions | Measure-Object -Maximum).Maximum $manualCheckFileName = $manualCheckFiles | Where-Object { $_ -like "*$latestVersion*" } $stigFilePath = "$manualCheckContainer\$manualCheckFileName.psd1" } } "OrgSettings" { switch -wildcard ($stigType) { "WindowsServer" { $orgSettingsFiles = (Get-ChildItem $orgSettingsFolder | Where-Object {$_.name -like "$stigType-$version-MS*"}).name } "DomainController" { $orgSettingsFiles = (Get-ChildItem $orgSettingsFolder | Where-Object {$_.name -like "WindowsServer-$version-DC*"}).name $stigVersions = $orgSettingsFiles | Select-String "(\d+)\.(\d+)" -AllMatches | Foreach-Object {$_.Matches.Value} $latestVersion = ($stigVersions | Measure-Object -Maximum).Maximum $orgSettingsFileName = $orgSettingsFiles | Where-Object {$_ -like "*WindowsServer*$latestVersion*.xml"} $stigFilePath = "$orgSettingsFolder\$orgSettingsFileName" } "WindowsClient" { $orgSettingsFiles = (Get-ChildItem $orgSettingsFolder | Where-Object { $_.name -Like "*$StigType*" }).name } "DotNetFramework" { $orgSettingsFiles = (Get-ChildItem $orgSettingsFolder | Where-Object { $_.name -like "$stigType-$version*"}).name } "InternetExplorer" { $orgSettingsFiles = (Get-ChildItem $orgSettingsFolder | Where-Object { $_.name -like "$stigType-$version*"}).name } "WebServer" { $orgSettingsFiles = (Get-ChildItem $orgSettingsFolder | Where-Object { $_.name -like "IISServer*$version*"}).name } "WebSite" { $orgSettingsFiles = (Get-ChildItem $orgSettingsFolder | Where-Object { $_.name -like "IISSite*$version*"}).name } "FireFox" { $StigType = "FireFox" $orgSettingsFiles = (Get-ChildItem $orgSettingsFolder | Where-Object { $_.name -like "$stigType-All-*"}).name } "Edge" { $orgSettingsFiles = (Get-ChildItem $orgSettingsFolder | Where-Object { $_.name -like "*$stigType*"}).name } "Chrome" { $orgSettingsFiles = (Get-ChildItem $orgSettingsFolder | Where-Object { $_.name -like "*$stigType*"}).name } "Adobe" { $StigType = "Adobe" $orgSettingsFiles = (Get-ChildItem $orgSettingsFolder | Where-Object { $_.name -like "$stigType-*.xml"}).name } "McAfee" { $orgSettingsFiles = (Get-ChildItem $orgSettingsFolder | Where-Object { $_.name -like "$stigType-$version*"}).name } "Office*" { $officeApp = $stigType.split('_')[1] $officeVersion = $stigType.split('_')[0].replace('Office','') $orgSettingsFiles = (Get-ChildItem "$orgSettingsFolder" | Where-Object { $_.name -like "*$officeApp$officeVersion*"}).name $stigVersions = $orgSettingsFiles | Select-String "(\d+)\.(\d+)" -AllMatches | Foreach-Object {$_.Matches.Value} $latestVersion = ($stigVersions | Measure-Object -Maximum).Maximum $orgSettingsFileName = $orgSettingsFiles | Where-Object { $_ -like "*$officeApp*$officeVersion*$latestVersion*.xml"} $stigFilePath = "$orgSettingsFolder\$orgSettingsFileName" } "OracleJRE" { $orgSettingsFiles = (Get-ChildItem $orgSettingsFolder | Where-Object { $_.name -like "$stigType-$version*"}).name } "WindowsDefender" { $orgSettingsFiles = (Get-ChildItem $orgSettingsFolder | Where-Object { $_.name -like "$stigType-$version*"}).name } "WindowsFirewall" { $orgSettingsFiles = (Get-ChildItem $orgSettingsFolder | Where-Object { $_.name -like "*$stigType*"}).name } "WindowsDNSServer" { $orgSettingsFiles = (Get-ChildItem $orgSettingsFolder | Where-Object { $_.name -like "$stigType*"}).name } "OracleJRE" { $orgSettingsFiles = (Get-ChildItem $orgSettingsFolder | Where-Object { $_.name -like "$stigType-$version"}).name } } if ($stigtype -like "WebSite*" -or $stigType -like "WebServer*") { $stigVersions = $orgSettingsFiles | ForEach-Object { $_.split("-")[2] | Select-String "(\d+)\.(\d+)" -AllMatches | Foreach-Object {$_.Matches.Value} } $latestVersion = ($stigVersions | Measure-Object -Maximum).Maximum $orgSettingsFileName = $orgSettingsFiles | Where-Object { $_ -like "*$($stigType.replace("Web","IIS"))*$latestVersion*.xml"} $stigFilePath = "$orgSettingsFolder\$orgSettingsFileName" } elseif ('' -eq $stigFilePath) { $stigVersions = $orgSettingsFiles | Select-String "(\d+)\.(\d+)" -AllMatches | Foreach-Object {$_.Matches.Value} $latestVersion = ($stigVersions | Measure-Object -Maximum).Maximum $orgSettingsFileName = $orgSettingsFiles | Where-Object { $_ -like "*$stigType*$latestVersion*.xml"} $stigFilePath = "$orgSettingsFolder\$orgSettingsFileName" } } } if ((Test-Path $stigFilePath) -and ( $stigFilePath -like "*.xml" -Or $stigFilePath -like "*.psd1") ) { return $stigFilePath } elseif ($stigtype -notlike "*SQL*") { Write-Warning "$NodeName - Unable to find $fileType file for $stigType STIG." return $null } } function Get-ApplicableStigs { [cmdletbinding()] param( [Parameter()] [string] $RootPath = (Get-Location).Path, [Parameter()] [string] $Computername = $env:COMPUTERNAME, [Parameter()] [switch] $LocalHost ) Write-Output "`t`tGathering STIG Applicability for $ComputerName" # Get Windows Version from Active Directory try { if ($LocalHost) { $WindowsVersion = "Windows 10" $ComputerName = 'LocalHost' } else { $windowsVersion = (Get-WmiObject -class win32_OperatingSystem -ComputerName $ComputerName -erroraction Stop).caption } # Get Installed Software from Target System $session = New-PsSession -ComputerName $Computername -ErrorAction Stop $installedSoftware = Invoke-Command -Session $session -ErrorAction Stop -Scriptblock { $localSoftwareList = New-Object System.Collections.ArrayList $null = (Get-ItemProperty "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" | Select-Object DisplayName, DisplayVersion, Publisher, InstallDate) | ForEach-Object {$null = $localSoftwareList.add($_)} $null = (Get-ItemProperty "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*" | Select-Object DisplayName, DisplayVersion, Publisher, InstallDate) | ForEach-Object {$null = $localSoftwareList.add($_)} return $localSoftwareList } # Get Installed Roles on Target System if ($windowsVersion -notlike "*Windows 10*") { $installedRoles = Invoke-Command -Session $session -Erroraction Stop -Scriptblock { $localRoleList = @(Get-WindowsFeature | Where-Object { $_.Installed -eq $True }) return $localRoleList } } # Add Applicable STIGs to Array $applicableSTIGs = New-Object System.Collections.ArrayList # Windows Operating System STIGs switch -WildCard ($windowsVersion) { "*2012*" {$null = $applicableStigs.add("WindowsServer-2012R2-MemberServer")} "*2016*" {$null = $applicableStigs.add("WindowsServer-2016-MemberServer")} "*2019*" {$null = $applicableStigs.add("WindowsServer-2019-MemberServer")} "*10*" {$null = $applicableStigs.add("WindowsClient")} } # Software STIGs switch -Wildcard ($installedSoftware.DisplayName) { "*Adobe Acrobat*" {$null = $applicableStigs.add("AdobeReader")} "*McAfee*" {$null = $applicableStigs.add("McAfee")} "*Office*16*" {$null = $applicableStigs.add("Office2016")} "*Office*15*" {$null = $applicableStigs.add("Office2013")} "*FireFox*" {$null = $applicableStigs.add("FireFox")} "*Chrome*" {$null = $applicableStigs.add("Chrome")} "*Edge*" {$null = $applicableStigs.add("Edge")} "*OracleJRE*" {$null = $applicableStigs.add("OracleJRE")} "Microsoft SQL Server*" { $null = $applicableStigs.add("SqlServerInstance") $null = $applicableStigs.add("SqlServerDatabase") } } # Server Role-Based STIGs switch -WildCard ($installedRoles.Name) { "Web-Server" { $iisVersion = Invoke-Command -Session $Session -ErrorAction Stop -Scriptblock { $iisData = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\InetStp" $localIisVersion = "$($iisData.MajorVersion).$($iisData.MinorVersion)" return $localiisVersion } $null = $applicableStigs.add("WebServer-$IISVersion") $null = $applicableStigs.add("Website-$IISVersion") } "Windows-Defender" { $null = $applicableStigs.add("WindowsDefender") $null = $applicableStigs.add("WindowsFirewall") } "DNS" {$null = $applicableStigs.add("WindowsDnsServer")} "AD-Domain-Services" {$null = $applicableStigs.add("ActiveDirectory")} } # Always Applicable $null = $applicableSTIGs.add("InternetExplorer") $null = $applicableSTIGs.add("DotnetFramework") $null = $applicableStigs.add("WindowsDefender") $null = $applicableStigs.add("WindowsFirewall") Remove-PsSession $Session $applicableStigs = $applicableStigs | Select-Object -Unique return $applicableStigs } catch { Write-Output "`t`t`tUnable to determine STIG Applicability for $ComputerName. Please verify WinRM connectivity." return $null Remove-PsSession $Session } } function Get-DscComplianceReports { [cmdletbinding()] param( [Parameter()] [string] $RootPath = (Get-Location).Path, [Parameter()] [string] $MofPath = (Resolve-Path -Path "$RootPath\*Artifacts\Mofs").Path, [Parameter()] [string] $LogsPath = (Resolve-Path -Path "$Rootpath\*Artifacts\Logs").Path, [Parameter()] [string] $OutputPath = (Resolve-Path -Path "$Rootpath\*Artifacts\Reports").Path, [Parameter()] [array] $DscResults ) if ($DSCResults.count -lt 1) { $DscResults = Test-DSCConfiguration -Path $MofPath } $DscResults | Export-Clixml -Path "$OutputPath\DscResults.xml" -Force $results = Import-CliXml "$OutputPath\DscResults.xml" $newdata = $results | ForEach-Object { if ($_.ResourcesInDesiredState) { $_.ResourcesInDesiredState | ForEach-Object { $_ } } if ($_.ResourcesNotInDesiredState) { $_.ResourcesNotInDesiredState | ForEach-Object { $_ } } } $parsedData = $newdata | Select-Object PSComputerName, ResourceName, InstanceName, InDesiredState, ConfigurationName, StartDate $parsedData | Export-Csv -Path $OutputPath\DscResults.csv -NoTypeInformation } function Get-OuDN { [CmdletBinding()] param ( [Parameter()] [string] $ComputerName = "$env:computername" ) $dn = (Get-AdComputer -Identity $ComputerName).DistinguishedName return $dn.replace("CN=$Env:ComputerName,","") } function Clear-SystemData { [CmdletBinding()] param ( [Parameter()] [String] $Rootpath = (Get-Location).Path ) $SystemsPath = (Resolve-Path -Path "$RootPath\*Systems").Path $ConfigDataFiles = Get-Childitem $SystemsPath -Recurse | Where-Object { $_.FullName -Notlike "*Staging*" } Write-Output "`tRemoving $($configDataFiles.count) DSC COnfigData Files" Remove-Item $configDataFiles.FullName -Force -Confirm:$False -Recurse } function Get-ManualCheckFileFromXccdf { [cmdletBinding()] param ( [Parameter()] [string] $XccdfPath, [Parameter()] [string] $ManualCheckPath = ".\Resources\ManualChecks\New" ) foreach ($path in $XccdfPath) { $file = Get-Item $path [xml]$content = Get-Content -path $file -Encoding UTF8 $split = $file.basename.split("_") $StigType = $split[1] $subType = $split[2] + $split[3] + $split[4] + $split[5] $Vuls = $content.benchmark.group.id $outfileName = "$subType-manualchecks.psd1" $manualCheckContent = New-Object System.Collections.ArrayList foreach ($vul in $vuls) { $null = $manualCheckContent.add("@{") $null = $manualCheckContent.add(" VulID = `"$vul`"") $null = $manualCheckContent.add(" Status = `"NotReviewed`"") $null = $manualCheckContent.add(" Comments = `"Input Finding Comments`"") $null = $manualCheckContent.add("}`n") } $manualCheckContent | Out-File "$manualCheckPath\$outFileName" -force } } function Publish-SCARArtifacts { Param ( [string]$repoUrl, [string]$repoName, [string]$repoFolderLocation, [string]$pathOfFolderToCopy, [string]$accessToken, [string]$targetPath ) $env:GIT_REDIRECT_STDERR = '2>&1' $startingPath = (Get-Location).Path Write-Host "Checking out $repoUrl." if($accessToken.Length -gt 0) {git clone $repoUrl -c http.extraheader="AUTHORIZATION: bearer $accessToken" -v} else {git clone $repoUrl -v} if(Test-Path $pathOfFolderToCopy){$publishArtifacts = Get-Item $pathOfFolderToCopy} else {Write-Host "Invalid Path Of Folder Copy Location: $pathOfFolderToCopy";exit} if(Test-Path $repoFolderLocation){Set-Location $repoFolderLocation} else {Write-Host "Invalid Folder Repo Location: $repoFolderLocation";exit} $sourcePath = $publishArtifacts.FullName+"\*" if (Test-Path $targetPath) {Remove-Item $targetPath -Recurse -Force} if(!(Test-Path $targetPath)) {New-Item -Path $targetPath -ItemType Directory} Copy-Item $sourcePath $targetPath -Recurse -Force git config --global user.email "SYSTEM@CONTOSO.COM" git config --global user.name "SYSTEM" git add --all git commit -m "Automated Commit" git push cd $startingPath if(Test-Path $repoName){ Remove-Item $repoName -Recurse -Force } } #region Stig Checklist Functions function Get-StigChecklists { <# .SYNOPSIS This function will generate the STIG Checklists and output them to the Reports directory under SCAR. .PARAMETER Rootpath Path to the root of the SCAR repository/codebase. C:\Your Repo\SCAR\ .PARAMETER OutputPath Path of where the checklists will be generated. Defaults to: Artifacts\Stig Checklist .PARAMETER TargetMachines List of target machines. If not specificied, a list will be generated from configurations present in "C:\Your Repo\SCAR\Systems" .PARAMETER TestConfig Switch parameter that allows testing against the configuration and the target machine. If switch is used, it will run test-dscconfiguration for the mof against the target machines to verify compliance. .EXAMPLE Example Get-StigChecklists -RootPath "C:\Your Repo\SCAR\" .EXAMPLE Example Get-StigChecklists -RootPath "C:\Your Repo\SCAR\" -TestConfig #> [cmdletbinding()] param( [Parameter()] [string] $RootPath = (Get-Location).Path, [Parameter()] [string] $OutputPath, [Parameter()] [array] $TargetMachines, [Parameter()] [string] $TargetFolder, [Parameter()] [string] $checklistDataPath, [Parameter()] [switch] $MofSettings, [Parameter()] [switch] $GenerateReports, [Parameter()] [switch] $LocalHost, [Parameter()] [string] $Enclave = "Unclassified" ) # Initialize File Paths $SystemsPath = (Resolve-Path -Path "$RootPath\*Systems").path $mofPath = (Resolve-Path -Path "$RootPath\*Artifacts\Mofs").path $resourcePath = (Resolve-Path -Path "$RootPath\*Resources").path $artifactsPath = (Resolve-Path -Path "$RootPath\*Artifacts").path $cklContainer = (Resolve-Path -Path "$artifactsPath\STIG Checklists").Path $allCkls = @() if (-not ($LocalHost)) { if ($null -eq $TargetMachines) { if ('' -eq $TargetFolder) { $targetMachines = (Get-Childitem -Path $SystemsPath -recurse | Where-object {$_.FullName -like "*.psd1" -and $_.fullname -notlike "*staging*"}).basename } else { if (Test-Path "$SystemsPath\$TargetFolder") { $targetMachines = (Get-Childitem -Path "$SystemsPath\$TargetFolder\*.psd1" -recurse).basename } else { Write-Output "$TargetFolder is not a valid SystemData subfolder. Please verify the folder name." exit } } } } else { $targetMachines = @("$env:ComputerName") } $jobs = New-Object System.Collections.ArrayList Write-Output "`tStarting STIG Checklist generation jobs for $($targetMachines.count) targetted machines.`n" foreach ($machine in $targetMachines) { $SystemFile = (Resolve-Path -Path "$SystemsPath\*\$machine.psd1").path $data = Invoke-Expression (Get-Content $SystemFile | Out-String) try { $machineFolder = (New-Item -Path $CklContainer -Name "$($data.nodeName)" -ItemType Directory -Force).FullName } catch { $machineFolder = (New-Item -Path $CklContainer -Name "$machine" -ItemType Directory -Force).FullName } Write-Output "`t`tStarting Job - Generate STIG Checklists for $machine" $job = Start-Job -InitializationScript {Import-Module -Name "C:\Program Files\WindowsPowershell\Modules\PowerSTIG\*\powerstig.psm1","C:\Program Files\WindowsPowershell\Modules\StigRepo\*\module\StigRepo.psm1"} -Scriptblock { $machine = $using:machine $RootPath = $using:RootPath $machineFolder = $using:machinefolder $SystemsPath = $using:SystemsPath $mofPath = $using:mofPath $resourcePath = $using:resourcePath $artifactsPath = $using:artifactsPath $cklContainer = $using:cklContainer $SystemFile = $using:SystemFile $data = $using:data $dscResult = $null $remoteCklJobs = New-Object System.Collections.ArrayList Write-Output "`n`n`t`t$Machine - Begin STIG Checklist Generation`n" if ($null -ne $data.appliedConfigurations) {$appliedStigs = $data.appliedConfigurations.getenumerator() | Where-Object {$_.name -like "POWERSTIG*"}} if ($null -ne $data.manualStigs) {$manualStigs = $data.manualStigs.getenumerator()} if ($null -ne $appliedStigs) { $winRmTest = Test-WSMan -Computername $machine -Authentication Default -Erroraction silentlycontinue $ps5check = Invoke-Command -ComputerName $machine -ErrorAction SilentlyContinue -Scriptblock {return $psversiontable.psversion.major} $osVersion = (Get-WmiObject Win32_OperatingSystem).caption | Select-String "(\d+)([^\s]+)" -AllMatches | Foreach-Object {$_.Matches.Value} if ($null -eq $winRmTest) { Write-Warning "`t`t`tUnable to connect to $machine to Test DSC Compliance. Verify WinRM connectivity." Continue } if ($ps5Check -lt 5) { Write-Warning "The Powershell version on $machine does not support Desired State Configuration. Minimum Powershell version is 5.0" Continue } try { $referenceConfiguration = (Resolve-Path "$mofPath\*$machine.mof").Path if ($machine -eq $env:computername) { $null = New-Item "C:\ScarData\STIG Data\ManualChecks" -ItemType Directory -Force -Confirm:$False $null = New-Item "C:\ScarData\STIG Data\Xccdfs" -ItemType Directory -Force -Confirm:$False $null = New-Item "C:\ScarData\STIG Checklists" -ItemType Directory -Force -Confirm:$False $null = New-Item "C:\ScarData\MOF" -ItemType Directory -Force -Confirm:$False $null = Copy-Item -Path $referenceConfiguration -Destination "C:\SCARData\MOF\" -Force -Confirm:$False } else { $null = New-Item "\\$machine\c$\SCAR\STIG Data\ManualChecks" -ItemType Directory -Force -Confirm:$False $null = New-Item "\\$machine\c$\SCAR\STIG Data\Xccdfs" -ItemType Directory -Force -Confirm:$False $null = New-Item "\\$machine\c$\SCAR\STIG Checklists" -ItemType Directory -Force -Confirm:$False $null = New-Item "\\$machine\c$\SCAR\MOF" -ItemType Directory -Force -Confirm:$False $null = Copy-Item -Path $referenceConfiguration -Destination "\\$machine\c$\SCAR\MOF\" -Force -Confirm:$False } $directoryCopy = $true } catch { Write-Output "`t`t`t`tUnable to Copy SCAR directory to $Machine." $directoryCopy = $false } if ($directoryCopy) { $attemptCount = 0 do { try { $attemptCount++ if ($machine -eq $env:computername) { Write-Output "`t`tExecuting local DSC Compliance Scan (Attempt $attemptCount/3)" $dscResult = Test-DscConfiguration -ReferenceConfiguration $ReferenceConfiguration -ErrorAction Stop $remoteExecution = $false } else { Write-Output "`t`tExecuting remote DSC Compliance Scan (Attempt $attemptCount/3)" $dscResult = Invoke-Command -Computername $machine -ErrorAction Stop -Scriptblock { Test-DscConfiguration -ReferenceConfiguration "C:\SCAR\MOF\$env:Computername.mof" } $remoteExecution = $true } } catch { if ($machine -eq $env:computername) { Stop-DscConfiguration -force -erroraction SilentlyContinue -WarningAction SilentlyContinue } else { Invoke-Command -ComputerName $machine -erroraction SilentlyContinue -WarningAction SilentlyContinue -Scriptblock { Stop-DscConfiguration -force -erroraction SilentlyContinue -WarningAction SilentlyContinue } } Start-Sleep -Seconds 5 $remoteExecution = $False } } until ($null -ne $dscResult -or $attemptCount -ge 3) } else { Write-Warning "`t`tRemote Execution failed - Attempting compliance scan locally (Attempt $attemptCount/5)" $attemptCount = 0 do { try { $attemptCount++ $referenceConfiguration = (Resolve-Path "$mofPath\*$machine.mof").Path Write-Output "`t`t`tExecuting local DSC Compliance Scan (Attempt $attemptCount/3)" if (Test-Path -Path $referenceConfiguration) { $dscResult = Test-DscConfiguration -Computername $machine -ReferenceConfiguration $referenceConfiguration -ErrorAction Stop } else { Write-Output "`t`t`t`tNo MOF exists for $machine." Continue } } catch { Write-Output "`t`t`t`tError gathering DSC Status. Restarting DSC Engine and trying again in 5 Seconds." if ($machine -eq $env:computername) { Stop-DscConfiguration -force -erroraction SilentlyContinue -WarningAction SilentlyContinue } else { Invoke-Command -ComputerName $machine -erroraction SilentlyContinue -WarningAction SilentlyContinue -Scriptblock { Stop-DscConfiguration -force -erroraction SilentlyContinue -WarningAction SilentlyContinue } } Start-Sleep -Seconds 5 } } until ($null -ne $dscResult -or $attemptCount -ge 3) if ($null -eq $dscResult) { Write-Output "Unable to execute compliance scan on $machine. Please verify winrm connectivity." exit } } if ($null -eq $dscResult) { Write-Output "Unable to execute DSC compliance scan on $machine." exit } else { foreach ($stig in $appliedStigs) { $stigType = $stig.name.tostring().replace("PowerSTIG_", "") $cklPath = "$machineFolder\$machine-$stigType.ckl" if (($null -ne $stig.Value.XccdfPath) -and (Test-Path $stig.Value.XccdfPath)) { $xccdfPath = $stig.Value.XccdfPath } else { Write-Warning "$machine - No xccdf file provided for $Stigtype" continue } if (($null -ne $stig.value.ManualChecks) -and (Test-Path $stig.Value.ManualChecks)) { $manualCheckFile = $stig.Value.ManualChecks } else { Write-Verbose "$machine - No Manual Check file provided for $Stigtype" } if ($remoteExecution) { Write-Output "`t`t`tSTIG Checklist - $stigType" try { if (Test-Path $xccdfPath) { $remoteXccdfPath = (Copy-Item -Path $xccdfPath -Passthru -Destination "\\$machine\C$\Scar\STIG Data\Xccdfs" -Container -Force -Confirm:$False -erroraction Stop).fullName.Replace("\\$machine\C$\","C:\") } $remoteCklPath = "C:\SCAR\STIG Checklists" if ($null -ne $manualCheckFile) { $remoteManualCheckFile = (Copy-Item -Path $ManualCheckFile -Passthru -Destination "\\$machine\C$\Scar\STIG Data\ManualChecks" -Container -Force -Confirm:$False).FullName.Replace("\\$machine\C$\","C:\") } $remoteCklJob = Invoke-Command -ComputerName $machine -AsJob -ArgumentList $remoteXccdfPath,$remoteManualCheckFile,$remoteCklPath,$dscResult,$machineFolder,$stigType -ScriptBlock { param( [Parameter(Position=0)]$remoteXccdfPath, [Parameter(Position=1)]$remoteManualCheckFile, [Parameter(Position=2)]$remoteCklPath, [Parameter(Position=3)]$dscResult, [Parameter(Position=4)]$machineFolder, [Parameter(Position=5)]$stigType ) Import-Module -Name "C:\Program Files\WindowsPowershell\Modules\PowerSTIG\*\powerstig.psm1" Import-Module -Name "C:\Program Files\WindowsPowershell\Modules\StigRepo\*\module\StigRepo.psm1" $params = @{ xccdfPath = $remotexccdfPath OutputPath = "$remoteCklPath\$env:computername-$stigType.ckl" DscResult = $dscResult Enclave = $Enclave } if ($null -ne $remoteManualCheckFile) { $params += @{ManualCheckFile = $remoteManualCheckFile} } Get-StigChecklist @params -ErrorAction SilentlyContinue } $null = $remoteCklJobs.Add($remoteCklJob) } catch { Write-Output "Unable to generate STIG Checklists for $machine." } } else { Write-Output "`t`t`tSTIG Checklist - $stigType" try { $xccdfPath = (Copy-Item -Path $xccdfPath -Passthru -Destination "C:\ScarData\STIG Data\Xccdfs" -Container -Force -Confirm:$False).FullName $cklPath = "C:\SCARData\STIG Checklists\$machine-$stigType.ckl" if ($null -ne $manualCheckFile) { $remoteManualCheckFile = (Copy-Item -Path $ManualCheckFile -Destination "C:\ScarData\STIG Data\ManualChecks" -Container -Force -Confirm:$False).FullName } $params = @{ XccdfPath = $xccdfPath OutputPath = $cklPath DSCResult = $dscResult Enclave = $Enclave } if ($null -ne $ManualCheckFile) { $params += @{ManualCheckFile = $ManualCheckFile} } Get-StigChecklist @params -ErrorAction SilentlyContinue } catch { Write-Output "`t`t`tUnable to generate $stigType Checklist for $machine." } } } if ($remoteCklJobs.count -gt 0) { Get-Job -ID $remoteCklJobs.ID | Wait-Job | Receive-Job Get-Job -ID $remoteCklJobs.ID | Remove-Job } try { if ($machine -eq $env:computername) { $stigChecklists = Get-ChildItem -Path "C:\ScarData\STIG Checklists\*.ckl" -Recurse } else { $stigChecklists = Get-Childitem -Path "\\$machine\C$\SCAR\STIG Checklists\*.ckl" -Recurse } if ($stigChecklists.count -gt 0) { Copy-Item -Path $stigChecklists.FullName -Destination $machineFolder } else { Write-Output "`t`t$machine - No STIG Checklists generated." } } catch { Write-Output "`t`t$machine - Unable to copy STIG Checklists to artifacts location." } } } if ($null -ne $manualStigs) { foreach ($manStig in $manualStigs) { if ($null -ne $manStig.Value.Subtypes) { $stigType = $manStig.name.tostring().replace("StigChecklist_", "") $subTypes = $manStig.value.subTypes foreach ($subType in $subTypes) { Write-Output "`t`tGenerating Checklist - $StigType-$subtype" $manCheckFileHint = $subtype.replace("_","") $xccdfHint = $subtype $manualCheckFile = (Get-Childitem "$rootpath\Resources\Stig Data\Manual Checks\$stigType\*.psd1" | Where {$_.name -like "*$manCheckFileHint*"}).FullName $xccdfPath = (Get-Childitem "$rootpath\Resources\Stig Data\XCCDFs\$stigType\*Manual-xccdf.xml" | Where {$_.name -like "*$xccdfHint*"}).FullName $cklPath = "$machineFolder\$($data.nodename)-$stigType_$manCheckFileHint.ckl" $params = @{ xccdfPath = $xccdfPath OutputPath = $cklPath ManualCheckFile = $manualCheckFile NoMof = $true NodeName = $data.nodename Enclave = $Enclave } Get-StigChecklist @params -ErrorAction SilentlyContinue } } elseif ($null -ne $manstig.name) { $stigType = $manStig.name.tostring().replace("StigChecklist_", "") Write-Output "`t`tGenerating Checklist - $stigType" $manualCheckFile = (Get-Childitem "$rootpath\Resources\Stig Data\Manual Checks\$stigType\*.psd1" | Select -first 1).FullName $xccdfPath = (Get-Childitem "$rootpath\Resources\Stig Data\XCCDFs\$stigType\*Manual-xccdf.xml" | Select -first 1).FullName $cklPath = "$machineFolder\$($data.nodename)-$stigType.ckl" $params = @{ xccdfPath = $xccdfPath OutputPath = $cklPath ManualCheckFile = $manualCheckFile NoMof = $true NodeName = $data.nodename Enclave = $Enclave } Get-StigChecklist @params -ErrorAction SilentlyContinue } else { Write-Output "`t`tUnable to generate $stigtype STIG Checklist for $machine. Please verify that STIG Data files." Continue } } } $machineCkls = (Get-ChildItem "$machineFolder\*.ckl" -recurse).count if ($machineCkls -lt 1) { Write-Output "`t`tNo STIG Checklists exist for $machine - Removing folder." Remove-Item $machineFolder -Force -Recurse -Confirm:$False } Write-Output "`t`t$machine - STIG Checklist job complete" } $null = $jobs.add($job.Id) } Write-Output "`n`tJob creation for STIG Checklists Generation is Complete. Waiting for $($jobs.count) jobs to finish processing" do { Start-Sleep -Seconds 60 $completedJobs = (Get-Job -id $jobs | where {$_.state -ne "Running"}).count $runningjobs = (Get-Job -id $jobs | where {$_.state -eq "Running"}).count Write-Output "`t`tChecklist Job Status:`t$runningJobs Jobs Currently Processing`t$completedJobs/$($jobs.count) Jobs Completed" } while ((Get-Job -ID $jobs).State -contains "Running") Write-Output "`n`t$($jobs.count) STIG Checklist jobs completed. Receiving job output" Get-Job -ID $jobs | Wait-Job | Receive-Job $cklCount = (Get-ChildItem "$cklContainer\*.ckl" -Recurse).count Write-Output "`tSTIG Checklist generation complete. Total STIG Checklists generated - $cklCount`n" } function Get-StigCheckList { <# .SYNOPSIS Automatically creates a Stig Viewer checklist from the DSC results or compiled MOF .PARAMETER ReferenceConfiguration The MOF that was compiled with a PowerStig composite .PARAMETER DscResult The results of Test-DscConfiguration .PARAMETER XccdfPath The path to the matching xccdf file. This is currently needed since we do not pull add xccdf data into PowerStig .PARAMETER OutputPath The location you want the checklist saved to .PARAMETER ManualCheckFile Location of a psd1 file containing the input for Vulnerabilities unmanaged via DSC/PowerSTIG. .EXAMPLE Get-StigChecklist -ReferenceConfiguration $referenceConfiguration -XccdfPath $xccdfPath -OutputPath $outputPath .EXAMPLE Get-StigChecklist -ReferenceConfiguration $referenceConfiguration -ManualCheckFile "C:\Stig\ManualChecks\2012R2-MS-1.7.psd1" -XccdfPath $xccdfPath -OutputPath $outputPath Get-StigChecklist -ReferenceConfiguration $referenceConfiguration -ManualCheckFile $manualCheckFilePath -XccdfPath $xccdfPath -OutputPath $outputPath #> [CmdletBinding()] [OutputType([xml])] param ( [Parameter(Mandatory = $true, ParameterSetName = 'mof')] [string] $ReferenceConfiguration, [Parameter(Mandatory = $true, ParameterSetName = 'result')] [psobject] $DscResult, [Parameter(Mandatory = $true, ParameterSetName = 'noMof')] [switch] $NoMof, [Parameter(Mandatory = $true, ParameterSetName = 'noMof')] [string] $NodeName, [Parameter(Mandatory = $true)] [string] $XccdfPath, [Parameter(Mandatory = $true)] [string] $OutputPath, [Parameter()] [string] $ManualCheckFile, [Parameter()] [string] $Enclave = "Unclassified" ) # Validate parameters before continuing if ($ManualCheckFile) { if (-not (Test-Path -Path $ManualCheckFile)) { throw "$($ManualCheckFile) is not a valid path to a ManualCheckFile. Provide a full valid path" } $parent = Split-Path $ManualCheckFile -Parent $filename = Split-Path $ManualCheckFile -Leaf $manualCheckData = Import-LocalizedData -BaseDirectory $parent -Filename $fileName } # Values for some of these fields can be read from the .mof file or the DSC results file if ($PSCmdlet.ParameterSetName -eq 'mof') { if (-not (Test-Path -Path $ReferenceConfiguration)) { throw "$($ReferenceConfiguration) is not a valid path to a configuration (.mof) file. Please provide a valid entry." } $MofString = Get-Content -Path $ReferenceConfiguration -Raw $TargetNode = Get-TargetNodeFromMof($MofString) } elseif ($PSCmdlet.ParameterSetName -eq 'result') { # Check the returned object if ($null -eq $DscResult) { throw 'Passed in $DscResult parameter is null. Please provide a valid result using Test-DscConfiguration.' } $TargetNode = $DscResult.PSComputerName } elseif ($PSCmdlet.ParameterSetName -eq 'NoMof') { $SystemFile = (Resolve-Path "$RootPath\Systems\*\$machine*").path $systemData = Invoke-Expression (Get-Content $SystemFile | Out-String) $targetNode = $NodeName } $TargetNodeType = Get-TargetNodeType($TargetNode) switch ($TargetNodeType) { "MACAddress" { $HostnameMACAddress = $TargetNode Break } "IPv4Address" { $HostnameIPAddress = $TargetNode Break } "IPv6Address" { $HostnameIPAddress = $TargetNode Break } "FQDN" { $HostnameFQDN = $TargetNode Break } default { $Hostname = $TargetNode } } $xmlWriterSettings = [System.Xml.XmlWriterSettings]::new() $xmlWriterSettings.Indent = $true $xmlWriterSettings.IndentChars = "`t" $xmlWriterSettings.NewLineChars = "`n" $writer = [System.Xml.XmlWriter]::Create($OutputPath, $xmlWriterSettings) $writer.WriteStartElement('CHECKLIST') #region ASSET $writer.WriteStartElement("ASSET") try { $IPAddress = (Get-NetIPAddress -AddressFamily IPV4 | Where-Object { $_.IpAddress -notlike "127.*" } | Select-Object -First 1).IPAddress $MACAddress = (Get-NetAdapter | Where-Object {$_.Status -eq "Up"} | Select-Object MacAddress | Select-Object -First 1).MacAddress $filter = "(&(objectCategory=computer)(objectClass=computer)(cn=$env:computername))" $FQDN = ([adsisearcher]$filter).FindOne().Properties.dnshostname } catch { if (-not $PSCmdlet.ParameterSetName -eq 'NoMof') { Write-Warning -Message "Error obtaining host data for $hostname." } } $osVersion = (Get-WmiObject Win32_OperatingSystem -ComputerName $hostName -erroraction silentlycontinue).caption switch -wildcard ($osVersion) { "*Server*" { $filter = "(&(objectCategory=computer)(objectClass=computer)(cn=$hostName))" $distinguishedName = ([adsisearcher]$filter).FindOne().Properties.distinguishedname if ($distinguishedName -notlike "*Domain Controllers*") { $osRole = "Member Server" } else { $osRole = "Domain Controller" } break } "*Windows 10*" { $osRole = "Workstation";break} $null { $osRole = "None"} } $assetElements = [ordered] @{ 'ROLE' = "$osRole" 'ASSET_TYPE' = 'Computing' 'HOST_NAME' = "$Hostname" 'HOST_IP' = "$IPAddress" 'HOST_MAC' = "$MACAddress" 'HOST_FQDN' = "$FQDN" 'TECH_AREA' = '' 'TARGET_KEY' = '2350' 'WEB_OR_DATABASE' = 'false' 'WEB_DB_SITE' = '' 'WEB_DB_INSTANCE' = '' } foreach ($assetElement in $assetElements.GetEnumerator()) { $writer.WriteStartElement($assetElement.name) $writer.WriteString($assetElement.value) $writer.WriteEndElement() } $writer.WriteEndElement(<#ASSET#>) #endregion ASSET $writer.WriteStartElement("STIGS") $writer.WriteStartElement("iSTIG") #region STIGS/iSTIG/STIG_INFO $writer.WriteStartElement("STIG_INFO") $xccdfBenchmarkContent = Get-StigXccdfBenchmarkContent -Path $xccdfPath $stigInfoElements = [ordered] @{ 'version' = $xccdfBenchmarkContent.version 'classification' = "$Enclave" 'customname' = '' 'stigid' = $xccdfBenchmarkContent.id 'description' = $xccdfBenchmarkContent.description 'filename' = Split-Path -Path $xccdfPath -Leaf 'releaseinfo' = $xccdfBenchmarkContent.'plain-text'.InnerText 'title' = $xccdfBenchmarkContent.title 'uuid' = (New-Guid).Guid 'notice' = $xccdfBenchmarkContent.notice.InnerText 'source' = $xccdfBenchmarkContent.reference.source } foreach ($StigInfoElement in $stigInfoElements.GetEnumerator()) { $writer.WriteStartElement("SI_DATA") $writer.WriteStartElement('SID_NAME') $writer.WriteString($StigInfoElement.name) $writer.WriteEndElement(<#SID_NAME#>) $writer.WriteStartElement('SID_DATA') $writer.WriteString($StigInfoElement.value) $writer.WriteEndElement(<#SID_DATA#>) $writer.WriteEndElement(<#SI_DATA#>) } $writer.WriteEndElement(<#STIG_INFO#>) #endregion STIGS/iSTIG/STIG_INFO #region STIGS/iSTIG/VULN[] # Pull in the processed XML file to check for duplicate rules for each vulnerability [xml]$xccdfBenchmark = Get-Content -Path $xccdfPath -Encoding UTF8 $fileList = Get-PowerStigFileList -StigDetails $xccdfBenchmark if ($XccfdPath -like "*2016*") { $processedFolder = "C:\Program Files\WindowsPowerShell\Modules\PowerSTIG\4.5.1\StigData\Processed" $processedXccdfs = (Get-ChildItem $processedFolder | Where { $_.name -like "*WindowsServer*2016*MS*xml"}).name $latestVersion = ($Versions | Measure-Object -Maximum ).maximum $processedFile = (Resolve-Path "$processedFolder\$($processedXccdfs | Where { $_ -like "*$latestVersion*" })").path } else { $processedFileName = $fileList.Settings.FullName } #[xml]$processed = Get-Content -Path $processedFileName $vulnerabilities = Get-VulnerabilityList -XccdfBenchmark $xccdfBenchmarkContent foreach ($vulnerability in $vulnerabilities) { $writer.WriteStartElement("VULN") foreach ($attribute in $vulnerability.GetEnumerator()) { $status = $null $findingDetails = $null $comments = $null $manualCheck = $null if ($attribute.Name -eq 'Vuln_Num') { $vid = $attribute.Value } $writer.WriteStartElement("STIG_DATA") $writer.WriteStartElement("VULN_ATTRIBUTE") $writer.WriteString($attribute.Name) $writer.WriteEndElement(<#VULN_ATTRIBUTE#>) $writer.WriteStartElement("ATTRIBUTE_DATA") $writer.WriteString($attribute.Value) $writer.WriteEndElement(<#ATTRIBUTE_DATA#>) $writer.WriteEndElement(<#STIG_DATA#>) } $statusMap = @{ NotReviewed = 'Not_Reviewed' Open = 'Open' NotAFinding = 'NotAFinding' NotApplicable = 'Not_Applicable' } $manualCheck = $manualCheckData | Where-Object -FilterScript {$_.VulID -eq $VID} if ($PSCmdlet.ParameterSetName -eq 'nomof') { $status = $statusMap["$($manualCheck.Status)"] $findingDetails = $manualCheck.Details $comments = $manualCheck.Comments } else { if ($PSCmdlet.ParameterSetName -eq 'result') { $manualCheck = $manualCheckData | Where-Object -FilterScript {$_.VulID -eq $VID} if ($manualCheck) { $status = $statusMap["$($manualCheck.Status)"] $findingDetails = $manualCheck.Details $comments = $manualCheck.Comments } else { $setting = Get-SettingsFromResult -DscResult $dscResult -Id $vid if ($setting) { if ($setting.InDesiredState -eq $true) { $status = $statusMap['NotAFinding'] $comments = "Addressed by PowerStig MOF via $setting" $findingDetails = Get-FindingDetails -Setting $setting } elseif ($setting.InDesiredState -eq $false) { $status = $statusMap['Open'] $comments = "Configuration attempted by PowerStig MOF via $setting, but not currently set." $findingDetails = Get-FindingDetails -Setting $setting } else { $status = $statusMap['Open'] } } else { $status = $statusMap['NotReviewed'] } } } else { if ($PSCmdlet.ParameterSetName -eq 'mof') { $setting = Get-SettingsFromMof -ReferenceConfiguration $referenceConfiguration -Id $vid } $manualCheck = $manualCheckData | Where-Object {$_.VulID -eq $VID} if ($setting) { $status = $statusMap['NotAFinding'] $comments = "To be addressed by PowerStig MOF via $setting" $findingDetails = Get-FindingDetails -Setting $setting } elseif ($manualCheck) { $status = $statusMap["$($manualCheck.Status)"] $findingDetails = $manualCheck.Details $comments = $manualCheck.Comments } else { $status = $statusMap['NotReviewed'] } } # Test to see if this rule is managed as a duplicate try {$convertedRule = $processed.SelectSingleNode("//Rule[@id='$vid']")} catch { } if ($convertedRule.DuplicateOf) { # How is the duplicate rule handled? If it is handled, then this duplicate is also covered if ($PSCmdlet.ParameterSetName -eq 'mof') { $originalSetting = Get-SettingsFromMof -ReferenceConfiguration $referenceConfiguration -Id $convertedRule.DuplicateOf if ($originalSetting) { $status = $statusMap['NotAFinding'] $findingDetails = 'See ' + $convertedRule.DuplicateOf + ' for Finding Details.' $comments = 'Managed via PowerStigDsc - this rule is a duplicate of ' + $convertedRule.DuplicateOf } } elseif ($PSCmdlet.ParameterSetName -eq 'result') { $originalSetting = Get-SettingsFromResult -DscResult $dscResult -id $convertedRule.DuplicateOf if ($originalSetting.InDesiredState -eq 'True') { $status = $statusMap['NotAFinding'] $findingDetails = 'See ' + $convertedRule.DuplicateOf + ' for Finding Details.' $comments = 'Managed via PowerStigDsc - this rule is a duplicate of ' + $convertedRule.DuplicateOf } else { $status = $statusMap['Open'] $findingDetails = 'See ' + $convertedRule.DuplicateOf + ' for Finding Details.' $comments = 'Managed via PowerStigDsc - this rule is a duplicate of ' + $convertedRule.DuplicateOf } } } } if ($null -eq $status) { $status = 'Not_Reviewed' $Comments = "Error gathering comments" } $writer.WriteStartElement("STATUS") $writer.WriteString($status) $writer.WriteEndElement(<#STATUS#>) $writer.WriteStartElement("FINDING_DETAILS") $writer.WriteString($findingDetails) $writer.WriteEndElement(<#FINDING_DETAILS#>) $writer.WriteStartElement("COMMENTS") $writer.WriteString($comments) $writer.WriteEndElement(<#COMMENTS#>) $writer.WriteStartElement("SEVERITY_OVERRIDE") $writer.WriteString('') $writer.WriteEndElement(<#SEVERITY_OVERRIDE#>) $writer.WriteStartElement("SEVERITY_JUSTIFICATION") $writer.WriteString('') $writer.WriteEndElement(<#SEVERITY_JUSTIFICATION#>) $writer.WriteEndElement(<#VULN#>) } #endregion STIGS/iSTIG/VULN[] $writer.WriteEndElement(<#iSTIG#>) $writer.WriteEndElement(<#STIGS#>) $writer.WriteEndElement(<#CHECKLIST#>) $writer.Flush() $writer.Close() } function Get-VulnerabilityList { <# .SYNOPSIS Gets the vulnerability details from the rule description #> [CmdletBinding()] [OutputType([xml])] param ( [Parameter()] [psobject] $XccdfBenchmark ) [System.Collections.ArrayList] $vulnerabilityList = @() foreach ($vulnerability in $XccdfBenchmark.Group) { [xml]$vulnerabiltyDiscussionElement = "<discussionroot>$($vulnerability.Rule.description)</discussionroot>" [void] $vulnerabilityList.Add( @( [PSCustomObject]@{Name = 'Vuln_Num'; Value = $vulnerability.id}, [PSCustomObject]@{Name = 'Severity'; Value = $vulnerability.Rule.severity}, [PSCustomObject]@{Name = 'Group_Title'; Value = $vulnerability.title}, [PSCustomObject]@{Name = 'Rule_ID'; Value = $vulnerability.Rule.id}, [PSCustomObject]@{Name = 'Rule_Ver'; Value = $vulnerability.Rule.version}, [PSCustomObject]@{Name = 'Rule_Title'; Value = $vulnerability.Rule.title}, [PSCustomObject]@{Name = 'Vuln_Discuss'; Value = $vulnerabiltyDiscussionElement.discussionroot.VulnDiscussion}, [PSCustomObject]@{Name = 'IA_Controls'; Value = $vulnerabiltyDiscussionElement.discussionroot.IAControls}, [PSCustomObject]@{Name = 'Check_Content'; Value = $vulnerability.Rule.check.'check-content'}, [PSCustomObject]@{Name = 'Fix_Text'; Value = $vulnerability.Rule.fixtext.InnerText}, [PSCustomObject]@{Name = 'False_Positives'; Value = $vulnerabiltyDiscussionElement.discussionroot.FalsePositives}, [PSCustomObject]@{Name = 'False_Negatives'; Value = $vulnerabiltyDiscussionElement.discussionroot.FalseNegatives}, [PSCustomObject]@{Name = 'Documentable'; Value = $vulnerabiltyDiscussionElement.discussionroot.Documentable}, [PSCustomObject]@{Name = 'Mitigations'; Value = $vulnerabiltyDiscussionElement.discussionroot.Mitigations}, [PSCustomObject]@{Name = 'Potential_Impact'; Value = $vulnerabiltyDiscussionElement.discussionroot.PotentialImpacts}, [PSCustomObject]@{Name = 'Third_Party_Tools'; Value = $vulnerabiltyDiscussionElement.discussionroot.ThirdPartyTools}, [PSCustomObject]@{Name = 'Mitigation_Control'; Value = $vulnerabiltyDiscussionElement.discussionroot.MitigationControl}, [PSCustomObject]@{Name = 'Responsibility'; Value = $vulnerabiltyDiscussionElement.discussionroot.Responsibility}, [PSCustomObject]@{Name = 'Security_Override_Guidance'; Value = $vulnerabiltyDiscussionElement.discussionroot.SeverityOverrideGuidance}, [PSCustomObject]@{Name = 'Check_Content_Ref'; Value = $vulnerability.Rule.check.'check-content-ref'.href}, [PSCustomObject]@{Name = 'Weight'; Value = $vulnerability.Rule.Weight}, [PSCustomObject]@{Name = 'Class'; Value = 'Unclass'}, [PSCustomObject]@{Name = 'STIGRef'; Value = "$($XccdfBenchmark.title) :: $($XccdfBenchmark.'plain-text'.InnerText)"}, [PSCustomObject]@{Name = 'TargetKey'; Value = $vulnerability.Rule.reference.identifier} # Some Stigs have multiple Control Correlation Identifiers (CCI) $( # Extract only the cci entries $CCIREFList = $vulnerability.Rule.ident | Where-Object {$PSItem.system -eq 'http://iase.disa.mil/cci'} | Select-Object 'InnerText' -ExpandProperty 'InnerText' foreach ($CCIREF in $CCIREFList) { [PSCustomObject]@{Name = 'CCI_REF'; Value = $CCIREF} } ) ) ) } return $vulnerabilityList } function Get-MofContent { <# .SYNOPSIS Converts the mof into an array of objects #> [CmdletBinding()] [OutputType([psobject])] param ( [Parameter(Mandatory = $true)] [string] $ReferenceConfiguration ) if (-not $script:mofContent) { $script:mofContent = [Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache]::ImportInstances($referenceConfiguration, 4) } return $script:mofContent } function Get-SettingsFromMof { <# .SYNOPSIS Gets the stig details from the mof #> [CmdletBinding()] [OutputType([psobject])] param ( [Parameter(Mandatory = $true)] [string] $ReferenceConfiguration, [Parameter(Mandatory = $true)] [string] $Id ) $mofContent = Get-MofContent -ReferenceConfiguration $referenceConfiguration $mofContentFound = $mofContent.Where({$PSItem.ResourceID -match $Id}) return $mofContentFound } function Get-SettingsFromResult { <# .SYNOPSIS Gets the stig details from the Test\Get-DscConfiguration output #> [CmdletBinding()] [OutputType([psobject])] param ( [Parameter(Mandatory = $true)] [psobject] $DscResult, [Parameter(Mandatory = $true)] [string] $Id ) $allResources = $dscResult.ResourcesNotInDesiredState + $dscResult.ResourcesInDesiredState return $allResources.Where({$PSItem.ResourceID -match $id}) } function Get-FindingDetails { <# .SYNOPSIS Gets the value from a STIG setting #> [OutputType([string])] [CmdletBinding()] param ( [Parameter(Mandatory)] [AllowNull()] [psobject] $Setting ) switch ($setting.ResourceID) { # Only add custom entries if specific output is more valuable than dumping all properties {$PSItem -match "^\[None\]"} { return "No DSC resource was leveraged for this rule (Resource=None)" } {$PSItem -match "^\[(x)?Registry\]"} { return "Registry Value = $($setting.ValueData)" } {$PSItem -match "^\[UserRightsAssignment\]"} { return "UserRightsAssignment Identity = $($setting.Identity)" } default { return Get-FindingDetailsString -Setting $setting } } } function Get-FindingDetailsString { <# .SYNOPSIS Formats properties and values with standard string format. #> [OutputType([string])] [CmdletBinding()] param ( [Parameter(Mandatory)] [AllowNull()] [psobject] $Setting ) foreach ($property in $setting.PSobject.properties) { if ($property.TypeNameOfValue -Match 'String') { $returnString += $($property.Name) + ' = ' $returnString += $($setting.PSobject.properties[$property.Name].Value) + "`n" } } return $returnString } function Get-TargetNodeFromMof { [OutputType([string])] [CmdletBinding()] param ( [Parameter(Mandatory)] [string] $MofString ) $pattern = "((?<=@TargetNode=')(.*)(?='))" $TargetNodeSearch = $mofstring | Select-String -Pattern $pattern $TargetNode = $TargetNodeSearch.matches.value return $TargetNode } function Get-TargetNodeType { [OutputType([string])] [CmdletBinding()] param ( [Parameter(Mandatory)] [string] $TargetNode ) switch ($TargetNode) { # Do we have a MAC address? { $_ -match '(([0-9a-f]{2}:){5}[0-9a-f]{2})' } { return 'MACAddress' } # Do we have an IPv6 address? { $_ -match '(([0-9a-f]{0,4}:){7}[0-9a-f]{0,4})' } { return 'IPv4Address' } # Do we have an IPv4 address? { $_ -match '(([0-9]{1,3}\.){3}[0-9]{1,3})' } { return 'IPv6Address' } # Do we have a Fully-qualified Domain Name? { $_ -match '([a-zA-Z0-9-.\+]{2,256}\.[a-z]{2,256}\b)' } { return 'FQDN' } } return '' } function Get-StigXccdfBenchmarkContent { [CmdletBinding()] [OutputType([xml])] param ( [Parameter(Mandatory = $true)] [string] $Path ) if (-not (Test-Path -Path $path)) { Throw "The file $path was not found" } if ($path -like "*.zip") { [xml] $xccdfXmlContent = Get-StigContentFromZip -Path $path } else { [xml] $xccdfXmlContent = Get-Content -Path $path -Encoding UTF8 } $xccdfXmlContent.Benchmark } |