diff --git a/CHANGELOG.md b/CHANGELOG.md index 788674c9b..7117d42c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,21 @@ ## [Unreleased] +* Update PowerSTIG to create Checklist V3 file format + +New Feature Request: +**Is your feature request related to a problem? Please describe.** +The checklist files generated are in the V2 format, but I need the files generated in the V3 format. + +**Describe the solution you'd like** +I want a new function, e.g., New-STIGChecklistV3, that generates a checklist file in the V3 format. + +**Describe alternatives you've considered** +An alternate option would be a function that converts a V2 Checklist file to the V3 format, instead of generating the V3 file directly. + +**Additional context** +The V3 format schema can be found in the Cyber.mil document library. + ## [4.28.0] - 2025-12-5 @@ -87,7 +102,7 @@ * Update Powerstig to parse/apply Microsoft Office System 2016 STIG - Ver 2, Rel 3 [#1352](https://github.com/microsoft/PowerStig/issues/1352) * Update Powerstig to parse/apply Microsoft Office 365 ProPlus STIG - Ver 2, Rel 12 [#1351](https://github.com/microsoft/PowerStig/issues/1351) * Update Powerstig to parse/apply Microsoft .Net Framework 4.0 STIG - Ver 2, Rel 4 [#1349](https://github.com/microsoft/PowerStig/issues/1349) -* Update Powerstig to parse/apply U_MS_SQL_Server_2016_Instance_V2R12 [#1348](https://github.com/microsoft/PowerStig/issues/1348) +* Update Powerstig to parse/apply U_MS_SQL_Server_2016_Instance_V2R12 [#1348](https://github.com/microsoft/PowerStig/issues/1348) * Update Powerstig to parse/apply Canonical Ubuntu 18.04 LTS STIG - Ver 2, Rel 14 [#1347](https://github.com/microsoft/PowerStig/issues/1347) ## [4.21.0] - 2024-03-01 diff --git a/Tests/Unit/Module/STIG.Checklist.tests.ps1 b/Tests/Unit/Module/STIG.Checklist.tests.ps1 index aad962576..5bc433d96 100644 --- a/Tests/Unit/Module/STIG.Checklist.tests.ps1 +++ b/Tests/Unit/Module/STIG.Checklist.tests.ps1 @@ -130,3 +130,67 @@ Describe 'Get-StigXccdfFileName' { $getStigXccdfFileNameResult | Should -Be 'U_Windows_Firewall_STIG_V1R7_Manual-xccdf.xml' } } + +Describe 'New-StigCheckListV3' { + + configuration ExampleV3 + { + param + ( + [parameter()] + [string] + $NodeName = "localhost" + ) + + Import-DscResource -ModuleName PowerStig + + Node $NodeName + { + WindowsServer BaseLine + { + OsVersion = "2019" + OsRole = "MS" + SkipRuleType = "AccountPolicyRule","AuditPolicyRule","AuditSettingRule","DocumentRule","ManualRule","PermissionRule","SecurityOptionRule","UserRightRule","WindowsFeatureRule","ProcessMitigationRule","RegistryRule" + } + } + } + ExampleV3 -OutputPath $TestDrive + + $mofTestV3 = '{0}{1}' -f $TestDrive.fullname,"\localhost.mof" + + # Test parameter validity -OutputPath + It 'Should throw if an invalid path is provided' { + {New-StigCheckListV3 -MofFile 'test' -XccdfPath 'test' -OutputPath 'c:\asdf'} | Should -Throw + } + + It 'Should throw if the full path to a .cklb file is not provided' { + {New-StigCheckListV3 -MofFile 'test' -XccdfPath 'test' -OutputPath 'c:\test\test.ck'} | Should -Throw + } + + # Test parameter -ManualCheckFile + It 'Should throw if the full path to a ManualChecklistEntriesFile is not valid' { + {New-StigCheckListV3 -MofFile 'test' -XccdfPath 'test' -ManualChecklistEntriesFile 'broken' -OutputPath 'c:\test\test.cklb'} | Should -Throw + } + + # Test invalid parameter combinations + It 'Should throw if an invalid combination of parameters for assessment is provided' { + {New-StigCheckListV3 -MofFile 'test' -DscResults 'test' -XccdfPath 'test' -OutputPath 'C:\test'} | Should -Throw + } + + It 'Should throw if an invalid combination of parameters for Xccdf validation is provided' { + {New-StigCheckListV3 -DscResult 'foo' -MofFile 'bar' -OutputPath 'C:\Test'} | Should -Throw + } + + It 'Should throw if input for Verifier is not string' { + {New-StigCheckListV3 -MofFile 'test' -XccdfPath 'test' -OutputPath 'c:\test\test.cklb' -Verifier 1234} | Should -Throw + } + + It 'Generate a V3 checklist given correct parameters' { + + { + $outputPath = Join-Path $TestDrive -ChildPath ChecklistV3.cklb + $xccdfPath = ((Get-ChildItem -Path $script:moduleRoot\StigData\Archive -Include *xccdf.xml -Recurse | Where-Object -Property Name -Match "Server_2019_MS")[1]).FullName + New-StigCheckListV3 -ReferenceConfiguration $mofTestV3 -XccdfPath $xccdfPath -OutputPath $outputPath -Verifier "PowerSTIG V3 Test" + } | Should -Not -Throw + } +} diff --git a/source/Module/STIG/Functions.Checklist.ps1 b/source/Module/STIG/Functions.Checklist.ps1 index 5f0a33241..034276365 100644 --- a/source/Module/STIG/Functions.Checklist.ps1 +++ b/source/Module/STIG/Functions.Checklist.ps1 @@ -504,6 +504,499 @@ function New-StigCheckList } +<# + .SYNOPSIS + Automatically creates a STIG Viewer 3 checklist (.cklb) from DSC results or a compiled MOF for a single endpoint. + The function will test based upon the passed in STIG file or files (XccdfPath) parameter. + Manual entries in the checklist can be injected from a ManualChecklistEntriesFile file. + + .DESCRIPTION + Creates a V3 format STIG checklist in JSON format (.cklb) for use with STIG Viewer 3. + This is the next generation format that replaces the V2 XML (.ckl) format. + + .PARAMETER ReferenceConfiguration + A MOF that was compiled with a PowerStig composite. + This parameter supports an alias of 'MofFile' + + .PARAMETER DscResults + The results of Test-DscConfiguration or DSC report server output for a node. + + .PARAMETER XccdfPath + The path to a DISA STIG .xccdf file. PowerSTIG includes the supported files in the /PowerShell/StigData/Archive folder. + + .PARAMETER OutputPath + The location where the checklist .cklb file will be created. Must include the filename with .cklb on the end. + + .PARAMETER ManualChecklistEntriesFile + Location of a .xml file containing the input for Vulnerabilities unmanaged via DSC/PowerSTIG. + + .PARAMETER Verifier + Name/identifier of the person or process that verified the checklist results. + + .EXAMPLE + Generate a V3 checklist for single STIG using a .MOF file: + + $ReferenceConfiguration = 'C:\contoso.local.mof' + $xccdfPath = 'C:\SQL Server\U_MS_SQL_Server_2016_Instance_STIG_V1R7_Manual-xccdf.xml' + $outputPath = 'C:\SqlServerInstance_2016_V1R7_STIG_config_mof.cklb' + New-StigCheckListV3 -ReferenceConfiguration $ReferenceConfiguration -XccdfPath $XccdfPath -OutputPath $outputPath + + .EXAMPLE + Generate a V3 checklist using DSC results: + + $audit = Test-DscConfiguration -ComputerName localhost -ReferenceConfiguration 'C:\localhost.mof' + $xccdfPath = 'C:\U_MS_SQL_Server_2016_Instance_STIG_V1R7_Manual-xccdf.xml' + $outputPath = 'C:\SqlServerInstance_2016_V1R7_STIG_config_dscresults.cklb' + New-StigCheckListV3 -DscResult $audit -XccdfPath $xccdfPath -OutputPath $outputPath -Verifier "PowerSTIG Automated Check" +#> +function New-StigCheckListV3 +{ + [CmdletBinding()] + [OutputType([System.IO.FileInfo])] + param + ( + [Parameter(Mandatory = $true, ParameterSetName = 'mof')] + [Alias('MofFile')] + [ValidateNotNullOrEmpty()] + [ValidateScript( + { + if (Test-Path -Path $_ -PathType Leaf) + { + return $true + } + else + { + throw "$($_) is not a valid path to a reference configuration (.mof) file. Provide a full valid path and filename." + } + } + )] + [String] + $ReferenceConfiguration, + + [Parameter(Mandatory = $true, ParameterSetName = 'dsc')] + [PSObject] + $DscResults, + + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [ValidateScript( + { + foreach ($filename in $_) + { + if (Test-Path -Path $filename -PathType Leaf) + { + return $true + } + else + { + throw "$($filename) is not a valid path to a DISA STIG .xccdf file. Provide a full valid path and filename." + } + } + } + )] + [String[]] + $XccdfPath, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [ValidateScript( + { + if (Test-Path -Path $_ -PathType Leaf) + { + return $true + } + else + { + throw "$($_) is not a valid path to a Manual Checklist Entries File. Provide a full valid path and filename." + } + } + )] + [String] + $ManualChecklistEntriesFile, + + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [ValidateScript( + { + if (Test-Path -Path $_.DirectoryName -PathType Container) + { + return $true + } + else + { + throw "$($_) is not a valid directory. Please provide a valid directory." + } + if ($_.Extension -ne '.cklb') + { + throw "$($_.FullName) is not a valid V3 checklist extension. Please provide a full valid path ending in .cklb" + } + else + { + return $true + } + } + )] + [System.IO.FileInfo] + $OutputPath, + + [Parameter()] + [String] + $Verifier + ) + + # Process manual check data if provided + if ($PSBoundParameters.ContainsKey('ManualChecklistEntriesFile')) + { + $manualCheckData = ConvertTo-ManualCheckListHashTable -Path $ManualChecklistEntriesFile -XccdfPath $XccdfPath + } + + # Get target node information from MOF or DSC results + if ($PSCmdlet.ParameterSetName -eq 'mof') + { + $mofString = Get-Content -Path $ReferenceConfiguration -Raw + $targetNode = Get-TargetNodeFromMof -MofString $mofString + } + elseif ($PSCmdlet.ParameterSetName -eq 'dsc') + { + if ($null -eq $DscResults) + { + throw 'Passed in $DscResults parameter is null. Please provide a valid result using Test-DscConfiguration.' + } + $targetNode = $DscResults.PSComputerName + } + + # V3 status mapping - uses lowercase with underscores + $statusMapV3 = @{ + NotReviewed = 'not_reviewed' + Open = 'open' + NotAFinding = 'not_a_finding' + NotApplicable = 'not_applicable' + } + + # Determine target node type and populate appropriate fields + $targetNodeType = Get-TargetNodeType -TargetNode $targetNode + $Hostname = '' + $HostnameIPAddress = '' + $HostnameMACAddress = '' + $HostnameFQDN = '' + + switch ($targetNodeType) + { + "MACAddress" + { + $HostnameMACAddress = $targetNode + break + } + "IPv4Address" + { + $HostnameIPAddress = $targetNode + break + } + "IPv6Address" + { + $HostnameIPAddress = $targetNode + break + } + "FQDN" + { + $HostnameFQDN = $targetNode + break + } + default + { + $Hostname = $targetNode + } + } + + # Build the V3 checklist structure + $checklistV3 = [PSCustomObject]@{ + title = Split-Path -Path $OutputPath -Leaf + cklb_version = '1.0' + id = (New-Guid).Guid + target_data = [PSCustomObject]@{ + target_type = 'Computing' + host_name = $Hostname + ip_address = $HostnameIPAddress + mac_address = $HostnameMACAddress + fqdn = $HostnameFQDN + comments = '' + role = 'None' + is_web_database = $false + technology_area = '' + web_db_site = '' + web_db_instance = '' + } + stigs = @() + } + + # Process each STIG file + foreach ($xccdfPathItem in $XccdfPath) + { + # Get STIG benchmark content + $xccdfBenchmarkContent = Get-StigXccdfBenchmarkContent -Path $xccdfPathItem + + # Parse STIG filename for lookups + $stigPathFileName = $XccdfPathItem.Split('\') + $stigFileName = $stigPathFileName[$stigPathFileName.Length - 1] + + # Get processed XML for duplicate rule detection + [XML] $xccdfBenchmark = Get-Content -Path $xccdfPathItem -Encoding UTF8 + $fileList = Get-PowerStigFileList -StigDetails $xccdfBenchmark -Path $xccdfPathItem + $processedFileName = $fileList.Settings.FullName + [XML] $processed = Get-Content -Path $processedFileName + + # Get all vulnerabilities from the STIG + $vulnerabilities = Get-VulnerabilityList -XccdfBenchmark $xccdfBenchmarkContent + + # Create display name by abbreviating common terms + $displayName = $xccdfBenchmarkContent.title -replace 'Security Technical Implementation Guide', 'STIG' + + # Generate STIG UUID + $stigUuid = (New-Guid).Guid + + # Build STIG object for V3 + $stigV3 = [PSCustomObject]@{ + stig_name = $xccdfBenchmarkContent.title + display_name = $displayName + stig_id = $xccdfBenchmarkContent.id + release_info = $xccdfBenchmarkContent.'plain-text'.InnerText + uuid = $stigUuid + reference_identifier = $null + size = $vulnerabilities.Count + rules = @() + } + + # Process each vulnerability as a rule + foreach ($vulnerability in $vulnerabilities) + { + # Initialize rule variables + $vid = $null + $ruleId = $null + $groupId = $null + $severity = 'unknown' + $status = $statusMapV3['NotReviewed'] + $findingDetails = $null + $comments = $null + + # Extract rule properties from vulnerability data + $ruleProperties = @{ + uuid = (New-Guid).Guid + stig_uuid = $stigUuid + group_id = '' + group_id_src = '' + rule_id = '' + rule_id_src = '' + target_key = $null + stig_ref = $null + weight = '' + classification = 'Unclass' + severity = 'unknown' + rule_version = '' + rule_title = '' + fix_text = '' + reference_identifier = $null + group_title = '' + false_positives = '' + false_negatives = '' + discussion = '' + check_content = '' + documentable = '' + mitigations = '' + potential_impacts = '' + third_party_tools = '' + mitigation_control = '' + responsibility = '' + security_override_guidance = '' + ia_controls = '' + check_content_ref = $null + legacy_ids = @() + ccis = @() + status = 'not_reviewed' + comments = '' + finding_details = '' + } + + # Map vulnerability attributes to V3 rule properties + foreach ($attribute in $vulnerability) + { + switch ($attribute.Name) + { + 'Vuln_Num' + { + $vid = $attribute.Value + $ruleProperties.group_id = $attribute.Value + $ruleProperties.group_id_src = $attribute.Value + } + 'Rule_ID' + { + $ruleId = $attribute.Value + $ruleProperties.rule_id = $attribute.Value + $ruleProperties.rule_id_src = $attribute.Value + } + 'Severity' + { + # V3 requires lowercase severity + $ruleProperties.severity = $attribute.Value.ToLower() + } + 'Group_Title' { $ruleProperties.group_title = $attribute.Value } + 'Rule_Ver' { $ruleProperties.rule_version = $attribute.Value } + 'Rule_Title' { $ruleProperties.rule_title = $attribute.Value } + 'Vuln_Discuss' { $ruleProperties.discussion = $attribute.Value } + 'IA_Controls' { $ruleProperties.ia_controls = $attribute.Value } + 'Check_Content' { $ruleProperties.check_content = $attribute.Value } + 'Fix_Text' { $ruleProperties.fix_text = $attribute.Value } + 'False_Positives' { $ruleProperties.false_positives = $attribute.Value } + 'False_Negatives' { $ruleProperties.false_negatives = $attribute.Value } + 'Documentable' { $ruleProperties.documentable = $attribute.Value } + 'Mitigations' { $ruleProperties.mitigations = $attribute.Value } + 'Potential_Impact' { $ruleProperties.potential_impacts = $attribute.Value } + 'Third_Party_Tools' { $ruleProperties.third_party_tools = $attribute.Value } + 'Mitigation_Control' { $ruleProperties.mitigation_control = $attribute.Value } + 'Responsibility' { $ruleProperties.responsibility = $attribute.Value } + 'Security_Override_Guidance' { $ruleProperties.security_override_guidance = $attribute.Value } + 'Weight' { $ruleProperties.weight = $attribute.Value } + 'Class' { $ruleProperties.classification = $attribute.Value } + 'STIGRef' { $ruleProperties.stig_ref = $attribute.Value } + 'TargetKey' { $ruleProperties.target_key = $attribute.Value } + 'CCI_REF' + { + # CCIs are an array in V3 + if ($null -eq $ruleProperties.ccis) + { + $ruleProperties.ccis = @() + } + $ruleProperties.ccis += $attribute.Value + } + } + } + + # Determine rule status based on MOF or DSC results + if ($PSCmdlet.ParameterSetName -eq 'mof') + { + $setting = Get-SettingsFromMof -ReferenceConfiguration $ReferenceConfiguration -Id $vid + $manualCheck = $manualCheckData | Where-Object -FilterScript { $_.STIG -eq $stigFileName -and $_.ID -eq $vid } + + if ($setting) + { + $ruleProperties.status = $statusMapV3['Open'] + $ruleProperties.comments = "To be addressed by PowerStig MOF via $setting" + $ruleProperties.finding_details = Get-FindingDetails -Setting $setting + } + elseif ($manualCheck) + { + $ruleProperties.status = $statusMapV3["$($manualCheck.Status)"] + $ruleProperties.finding_details = $manualCheck.Details + $ruleProperties.comments = $manualCheck.Comments + } + else + { + $ruleProperties.status = $statusMapV3['NotReviewed'] + } + } + elseif ($PSCmdlet.ParameterSetName -eq 'dsc') + { + $manualCheck = $manualCheckData | Where-Object -FilterScript { $_.STIG -eq $stigFileName -and $_.ID -eq $vid } + + if ($manualCheck) + { + $ruleProperties.status = $statusMapV3["$($manualCheck.Status)"] + $ruleProperties.finding_details = $manualCheck.Details + $ruleProperties.comments = $manualCheck.Comments + } + else + { + $setting = Get-SettingsFromResult -DscResults $DscResults -Id $vid + + if ($setting) + { + if ($setting.InDesiredState -eq $true) + { + $ruleProperties.status = $statusMapV3['NotAFinding'] + if ($PSBoundParameters.ContainsKey('Verifier')) + { + $ruleProperties.comments = "Addressed by PowerStig MOF via {0} and verified by {1}" -f $setting, $Verifier + } + else + { + $ruleProperties.comments = "Addressed by PowerStig MOF via $setting" + } + $ruleProperties.finding_details = Get-FindingDetails -Setting $setting + } + elseif ($setting.InDesiredState -eq $false) + { + $ruleProperties.status = $statusMapV3['Open'] + $ruleProperties.comments = "Configuration attempted by PowerStig MOF via $setting, but not currently set." + $ruleProperties.finding_details = Get-FindingDetails -Setting $setting + } + else + { + $ruleProperties.status = $statusMapV3['Open'] + } + } + else + { + $ruleProperties.status = $statusMapV3['NotReviewed'] + } + } + } + + # Handle duplicate rules + $convertedRule = $processed.SelectSingleNode("//Rule[@id='$vid']") + if ($convertedRule.DuplicateOf) + { + if ($PSCmdlet.ParameterSetName -eq 'mof') + { + $originalSetting = Get-SettingsFromMof -ReferenceConfiguration $ReferenceConfiguration -Id $convertedRule.DuplicateOf + if ($originalSetting) + { + $ruleProperties.status = $statusMapV3['Open'] + $ruleProperties.finding_details = 'See {0} for Finding Details.' -f $convertedRule.DuplicateOf + $ruleProperties.comments = 'Managed via PowerStigDsc - this rule is a duplicate of {0}' -f $convertedRule.DuplicateOf + } + } + elseif ($PSCmdlet.ParameterSetName -eq 'dsc') + { + $originalSetting = Get-SettingsFromResult -DscResults $DscResults -Id $convertedRule.DuplicateOf + if ($originalSetting.InDesiredState -eq 'True') + { + $ruleProperties.status = $statusMapV3['NotAFinding'] + $ruleProperties.finding_details = 'See {0} for Finding Details.' -f $convertedRule.DuplicateOf + $ruleProperties.comments = 'Managed via PowerStigDsc - this rule is a duplicate of {0}' -f $convertedRule.DuplicateOf + } + else + { + $ruleProperties.status = $statusMapV3['Open'] + $ruleProperties.finding_details = 'See {0} for Finding Details.' -f $convertedRule.DuplicateOf + $ruleProperties.comments = 'Managed via PowerStigDsc - this rule is a duplicate of {0}' -f $convertedRule.DuplicateOf + } + } + } + + # Add rule to STIG + $stigV3.rules += [PSCustomObject]$ruleProperties + } + + # Set reference_identifier from first rule if available + if ($stigV3.rules.Count -gt 0 -and $stigV3.rules[0].reference_identifier) + { + $stigV3.reference_identifier = $stigV3.rules[0].reference_identifier + } + + # Add STIG to checklist + $checklistV3.stigs += $stigV3 + } + + # Convert to JSON and save + # Depth of 10 ensures all nested structures are properly serialized + $jsonOutput = $checklistV3 | ConvertTo-Json -Depth 10 -Compress:$false + + # Save to file with UTF8 encoding (no BOM for JSON compatibility) + [System.IO.File]::WriteAllText($OutputPath.FullName, $jsonOutput, [System.Text.UTF8Encoding]::new($false)) + + Write-Verbose "V3 Checklist created successfully: $($OutputPath.FullName)" + return $OutputPath +} + <# .SYNOPSIS Gets the vulnerability details from the rule description diff --git a/source/PowerStig.psd1 b/source/PowerStig.psd1 index 2b4e10141..e17c4ba3e 100644 --- a/source/PowerStig.psd1 +++ b/source/PowerStig.psd1 @@ -82,6 +82,7 @@ 'Get-DomainName', 'Get-Stig', 'New-StigCheckList', + 'New-StigCheckListV3', 'Get-StigRuleList', 'Get-StigVersionNumber', 'Get-PowerStigFilelist', diff --git a/source/PowerStig.psm1 b/source/PowerStig.psm1 index a0defbcc3..db64a128a 100644 --- a/source/PowerStig.psm1 +++ b/source/PowerStig.psm1 @@ -15,6 +15,7 @@ Export-ModuleMember -Function @( 'Get-DomainName', 'Get-Stig', 'New-StigCheckList', + 'New-StigCheckListV3', 'Get-StigRuleList', 'Get-StigVersionNumber', 'Get-PowerStigFilelist', diff --git a/source/StigData/Schema/ChecklistV3.json b/source/StigData/Schema/ChecklistV3.json new file mode 100644 index 000000000..9bd1656ac --- /dev/null +++ b/source/StigData/Schema/ChecklistV3.json @@ -0,0 +1,395 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "title": "STIG Viewer 3 Checklist", + "description": "A file used for storing STIG Viewer checklists, containing rules with finding statuses, comments, and data about the target system.", + "additionalProperties": false, + "required": [ + "title", + "id" + ], + "properties": { + "title": { + "description": "The STIG filename when it was last saved", + "type": "string" + }, + "cklb_version": { + "description": "[Optional] Schema Version, Defaults to 1.0", + "type": "string", + "const": "1.0" + }, + "id": { + "description": "A UUID that uniquely itentifies the checklist", + "type": "string", + "format": "uuid" + }, + "active": { + "description": "[Optional] Internal use by SV3", + "type": "boolean" + }, + "mode": { + "description": "[Optional] Used By SV3 to track if the checklist is in build or fill mode", + "type": "number" + }, + "has_path": { + "description": "[Optional] Internal use by SV3", + "type": "boolean" + }, + "target_data": { + "description": "[Optional] Properties of the scanned system", + "$ref": "#/$defs/target_data" + }, + "stigs": { + "description": "[Optional] An array of STIGs contained in the checklist", + "type": "array", + "items": { + "$ref": "#/$defs/stig" + } + } + }, + "$defs": { + "target_data": { + "description": "Properties of the scanned system", + "type": "object", + "additionalProperties": false, + "required": [], + "properties": { + "target_type": { + "description": "", + "type": "string" + }, + "host_name": { + "description": "", + "type": "string" + }, + "ip_address": { + "description": "", + "type": "string" + }, + "mac_address": { + "description": "", + "type": "string" + }, + "fqdn": { + "description": "", + "type": "string" + }, + "comments": { + "description": "", + "type": "string" + }, + "role": { + "description": "", + "type": "string" + }, + "is_web_database": { + "description": "", + "type": "boolean" + }, + "technology_area": { + "description": "", + "type": "string" + }, + "web_db_site": { + "description": "", + "type": "string" + }, + "web_db_instance": { + "description": "", + "type": "string" + } + } + }, + "stig": { + "description": "", + "type": "object", + "additionalProperties": false, + "required": [ + "stig_name", + "display_name", + "stig_id", + "release_info", + "uuid", + "size" + ], + "properties": { + "stig_name": { + "description": "The Full STIG Name taken from the title field of the origin STIG", + "type": "string" + }, + "display_name": { + "description": "A formatted STIG Name that's more suitable for compact display like abbreviating 'Security Technical Implementation Guide' to 'STIG'", + "type": "string" + }, + "stig_id": { + "description": "The Benchmark ID taken from the origin STIG", + "type": "string" + }, + "release_info": { + "description": "The Release Info taken from the origin STIG, usually contains the STIG version and release date", + "type": "string" + }, + "uuid": { + "type": "string", + "description": "A unique identifier used to tie a STIG to a specific STIG", + "format": "uuid" + }, + "reference_identifier": { + "description": "The Refrence -> identifier from the first rule in the checklist", + "type": [ + "string", + "null" + ] + }, + "size": { + "description": "The TOTAL number of rules in the origin STIG, even if the rules were cherrypicked. Comparing this to the length of rules will indicate if there are missing rules", + "type": "integer" + }, + "rules": { + "description": "An array of Checklist Rule Objects that contain data from STIG rules and any data captured by the checklist editor", + "type": "array", + "items": { + "$ref": "#/$defs/stig_rule" + } + } + } + }, + "stig_rule": { + "description": "Rules taken from the origin STIG, any fields without descriptions are copied 1:1 from the origin.", + "additionalProperties": false, + "properties": { + "uuid": { + "description": "A unique identifier for the checklist rule", + "type": "string" + }, + "stig_uuid": { + "description": "The UUID of the origin STIG", + "type": "string" + }, + "group_id": { + "description": "A prettier version of group_id_src for display, removes text like 'xccdf_mil.disa.stig_group_'", + "type": "string" + }, + "group_id_src": { + "description": "The GroupID from the rule in the origin STIG", + "type": "string" + }, + "rule_id": { + "description": "A prettier version of rule_id_src for rule display, removes text like 'xccdf_mil.disa.stig_rule_' or 'rule_'", + "type": "string" + }, + "rule_id_src": { + "description": "The RuleID from the rule in the origin STIG", + "type": "string" + }, + "target_key": { + "description": "The identifier value from the Reference tag", + "type": [ + "string", + "null" + ] + }, + "stig_ref": { + "type": [ + "string", + "null" + ] + }, + "weight": { + "description": "Weight from origin STIG", + "type": "string" + }, + "classification": { + "description": "Class from origin STIG", + "type": "string" + }, + "severity": { + "description": "Severity from origin STIG", + "type": "string", + "enum": [ + "unknown", + "low", + "medium", + "high" + ] + }, + "rule_version": { + "description": "Rule_Ver from origin STIG", + "type": "string" + }, + "rule_title": { + "description": "Rule_Title from origin STIG", + "type": "string" + }, + "fix_text": { + "description": "FixText from origin STIG", + "type": "string" + }, + "reference_identifier": { + "description": "The identifier value from the Reference tag", + "type": [ + "string", + "null" + ] + }, + "group_title": { + "description": "Group_Title from origin STIG", + "type": "string" + }, + "false_positives": { + "description": "False_Positives from origin STIG", + "type": "string" + }, + "false_negatives": { + "description": "False_Negatives from origin STIG", + "type": "string" + }, + "discussion": { + "description": "Discussion from origin STIG", + "type": "string" + }, + "check_content": { + "description": "CheckContent from origin", + "type": "string" + }, + "documentable": { + "description": "Documentable from origin STIG", + "type": "string" + }, + "mitigations": { + "description": "Mitigations from origin STIG", + "type": "string" + }, + "potential_impacts": { + "description": "Potential_Impacts from origin STIG", + "type": "string" + }, + "third_party_tools": { + "description": "Third_Party_Tools from origin STIG", + "type": "string" + }, + "mitigation_control": { + "description": "Mitigation_Control from origin STIG", + "type": "string" + }, + "responsibility": { + "description": "Responsibility from origin STIG", + "type": "string" + }, + "security_override_guidance": { + "description": "Security_Override_Guidance from origin STIG", + "type": "string" + }, + "ia_controls": { + "description": "IA_Controls from origin STIG", + "type": "string" + }, + "check_content": { + "description": "Check_Content from origin STIG", + "type": [ + "string", + "null" + ] + }, + "check_content_ref": { + "description": "CheckContentRef from origin STIG", + "type": [ + "object", + "null" + ], + "properties": { + "name": { + "type": "string" + }, + "href": { + "type": "string" + } + } + }, + "legacy_ids": { + "description": "LEGACY_ID array from origin STIG", + "type": "array", + "items": { + "type": "string" + } + }, + "ccis": { + "description": "CCI_REF array from origin STIG", + "type": "array", + "items": { + "type": "string" + } + }, + "group_tree": { + "description": "An array showing the hierarchy of the group tree structure", + "type": "array", + "items": { + "description": "Each level in the group heirarchy is stored, with the earlier entries in the array representing higher levels of the tree", + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + } + } + } + }, + "createdAt": { + "description": "The datetime string for the time the rule was added to the SV3 library", + "type": "string" + }, + "updatedAt": { + "description": "The datetime string for the last time the rule was modified in the SV3 Library", + "type": "string" + }, + "status": { + "description": "The STATUS field of the rule", + "type": "string", + "enum": [ + "not_reviewed", + "not_applicable", + "open", + "not_a_finding" + ] + }, + "overrides": { + "Description": "Allows rule properties to be overridden without data-loss of the original value. Currently, only 'severity' is used", + "additionalProperties": false, + "patternProperties": { + "^[a-zA-Z_]+$": { + "type": "object", + "additionalProperties": false, + "properties": { + "reason": { + "description": "Justification for overriding the property", + "type": "string" + } + }, + "patternProperties": { + "^[a-zA-Z_]+$": { + "type": "string" + } + } + } + } + }, + "comments": { + "description": "Comments about the current rule", + "type": "string" + }, + "finding_details": { + "description": "Finding details for the current rule, usually information about the tool that was used to generate the finding", + "type": "string" + }, + "STIGUuid": { + "description": "[Deprecated] Not Used", + "type": "string" + } + } + } + } +}