Skip to content

Commit

Permalink
Make ScubaResults.json the default JSON output (#1316)
Browse files Browse the repository at this point in the history
* Invert MergeJSON to KeepIndividualJSON

* remove debuging output message

* rm trailing whitespace

* rm other trailing whitespace

* add todo comment

* fix files

* update smoketests

* address missing mergejson documentation

* Update KeepIndividualJSON description

Co-authored-by: Alden Hilton <[email protected]>

* add missing keep json call

* Update docs/execution/reports.md from review feedback

Co-authored-by: mitchelbaker-cisa <[email protected]>

* Update PowerShell/ScubaGear/Modules/Orchestrator.psm1 from review feedback

Co-authored-by: mitchelbaker-cisa <[email protected]>

* add in nobom fix to ScubaCached

* fix comment language

* innoculous change

* retrigger the action

---------

Co-authored-by: Alden Hilton <[email protected]>
Co-authored-by: mitchelbaker-cisa <[email protected]>
  • Loading branch information
3 people committed Sep 20, 2024
1 parent 4d9c7a4 commit b8f5480
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 34 deletions.
45 changes: 30 additions & 15 deletions PowerShell/ScubaGear/Modules/Orchestrator.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,11 @@ function Invoke-SCuBA {
.Parameter OutReportName
The name of the main html file page created in the folder created in OutPath.
Defaults to "BaselineReports".
.Parameter MergeJson
Set switch to merge all json output into a single file and delete the individual files
after merging.
.Parameter KeepIndividualJSON
Keeps ScubaGear legacy output where files are not merged into an all in one JSON.
This parameter is for backwards compatibility for those working with the older ScubaGear output files.
.Parameter OutJsonFileName
If MergeJson is set, the name of the consolidated json created in the folder
If KeepIndividualJSON is not set, the name of the consolidated json created in the folder
created in OutPath. Defaults to "ScubaResults".
.Parameter OutCsvFileName
The CSV created in the folder created in OutPath that contains the CSV version of the test results.
Expand Down Expand Up @@ -208,7 +208,7 @@ function Invoke-SCuBA {
[Parameter(Mandatory = $false, ParameterSetName = 'Report')]
[ValidateNotNullOrEmpty()]
[switch]
$MergeJson,
$KeepIndividualJSON,

[Parameter(Mandatory = $false, ParameterSetName = 'Configuration')]
[Parameter(Mandatory = $false, ParameterSetName = 'Report')]
Expand Down Expand Up @@ -277,7 +277,7 @@ function Invoke-SCuBA {
'OutProviderFileName' = $OutProviderFileName
'OutRegoFileName' = $OutRegoFileName
'OutReportName' = $OutReportName
'MergeJson' = $MergeJson
'KeepIndividualJSON' = $KeepIndividualJSON
'OutJsonFileName' = $OutJsonFileName
'OutCsvFileName' = $OutCsvFileName
}
Expand Down Expand Up @@ -408,7 +408,7 @@ function Invoke-SCuBA {
}
Invoke-ReportCreation @ReportParams

if ($MergeJson) {
if (-not $KeepIndividualJSON) {
# Craft the complete json version of the output
$JsonParams = @{
'ProductNames' = $ScubaConfig.ProductNames;
Expand Down Expand Up @@ -1544,11 +1544,11 @@ function Invoke-SCuBACached {
.Parameter OutReportName
The name of the main html file page created in the folder created in OutPath.
Defaults to "BaselineReports".
.Parameter MergeJson
Set switch to merge all json output into a single file and delete the individual files
after merging.
.Parameter KeepIndividualJSON
Keeps ScubaGear legacy output where files are not merged into an all in one JSON.
This parameter is for backwards compatibility for those working with the older ScubaGear output files.
.Parameter OutJsonFileName
If MergeJson is set, the name of the consolidated json created in the folder
If KeepIndividualJSON is set, the name of the consolidated json created in the folder
created in OutPath. Defaults to "ScubaResults".
.Parameter OutCsvFileName
The CSV created in the folder created in OutPath that contains the CSV version of the test results.
Expand Down Expand Up @@ -1651,7 +1651,7 @@ function Invoke-SCuBACached {
[Parameter(Mandatory = $false, ParameterSetName = 'Report')]
[ValidateNotNullOrEmpty()]
[switch]
$MergeJson,
$KeepIndividualJSON,

[Parameter(Mandatory = $false, ParameterSetName = 'Report')]
[ValidateNotNullOrEmpty()]
Expand Down Expand Up @@ -1732,8 +1732,23 @@ function Invoke-SCuBACached {
}
Invoke-ProviderList @ProviderParams
}
$FileName = Join-Path -Path $OutPath -ChildPath "$($OutProviderFileName).json"
$SettingsExport = Get-Content $FileName | ConvertFrom-Json

$ProviderJSONFilePath = Join-Path -Path $OutPath -ChildPath "$($OutProviderFileName).json"
if (-not (Test-Path $ProviderJSONFilePath)) {
# When running Invoke-ScubaCached, the provider output might not exist as a stand-alone
# file depending on what version of ScubaGear created the output. If the provider output
# does not exist as a stand-alone file, create it from the ScubaResults file so the other functions
# can execute as normal.
$ScubaResultsFileName = Join-Path -Path $OutPath -ChildPath "$($OutJsonFileName).json"
$SettingsExport = $(Get-Content $ScubaResultsFileName | ConvertFrom-Json).Raw

# Uses the custom UTF8 NoBOM function to reoutput the Provider JSON file
$ProviderContent = $SettingsExport | ConvertTo-Json -Depth 20
$ActualSavedLocation = Set-Utf8NoBom -Content $ProviderContent `
-Location $ProviderJSONFilePath -FileName "$OutProviderFileName.json"
Write-Debug $ActualSavedLocation
}
$SettingsExport = Get-Content $ProviderJSONFilePath | ConvertFrom-Json
$TenantDetails = $SettingsExport.tenant_details
$RegoParams = @{
'ProductNames' = $ProductNames;
Expand All @@ -1757,7 +1772,7 @@ function Invoke-SCuBACached {
Invoke-RunRego @RegoParams
Invoke-ReportCreation @ReportParams

if ($MergeJson) {
if (-not $KeepIndividualJSON) {
# Craft the complete json version of the output
$JsonParams = @{
'ProductNames' = $ProductNames;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ InModuleScope Orchestrator {
function Get-ScubaDefault {throw 'this will be mocked'}
Mock -ModuleName Orchestrator Get-ScubaDefault {"."}

function Merge-JsonOutput {throw 'this will be mocked'}
Mock -ModuleName Orchestrator Merge-JsonOutput {}

function ConvertTo-ResultsCsv {throw 'this will be mocked'}
Mock -ModuleName Orchestrator ConvertTo-ResultsCsv {}

Mock -CommandName New-Item {}
Mock -CommandName Copy-Item {}
}
Expand All @@ -30,6 +36,7 @@ InModuleScope Orchestrator {
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'SplatParams')]
$SplatParams = @{
M365Environment = 'commercial';
KeepIndividualJSON = $true;
}
}
It 'Do it quietly (Do not automatically show report)' {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ InModuleScope Orchestrator {
function Disconnect-SCuBATenant {}
Mock -ModuleName Orchestrator Disconnect-SCuBATenant

function Set-Utf8NoBom {}
Mock -ModuleName Orchestrator Set-Utf8NoBom

Mock -CommandName Write-Debug {}
Mock -CommandName New-Item {}
Mock -CommandName Get-Content {}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ InModuleScope Orchestrator {
Mock -ModuleName Orchestrator Merge-JsonOutput {
$script:TestSplat.Add('OutJsonFileName', $ScubaConfig.OutJsonFileName)
}
function ConvertTo-ResultsCsv {throw 'this will be mocked'}
Mock -ModuleName Orchestrator ConvertTo-ResultsCsv {}
function Disconnect-SCuBATenant {
$script:TestSplat.Add('DisconnectOnExit', $DisconnectOnExit)
}
Expand Down Expand Up @@ -65,8 +67,7 @@ InModuleScope Orchestrator {
}
}
[ScubaConfig]::ResetInstance()
Invoke-SCuBA -ConfigFilePath (Join-Path -Path $PSScriptRoot -ChildPath "orchestrator_config_test.yaml")`
-MergeJson
Invoke-SCuBA -ConfigFilePath (Join-Path -Path $PSScriptRoot -ChildPath "orchestrator_config_test.yaml")
}

It "Verify parameter ""<parameter>"" with value ""<value>""" -ForEach @(
Expand Down Expand Up @@ -100,7 +101,6 @@ InModuleScope Orchestrator {
-OutFolderName "MyReports" `
-OutProviderFileName "MySettingsExport" `
-OutRegoFileName "RegoResults" `
-MergeJson:$true `
-OutReportName "MyReport" `
-OutJsonFileName "JsonResults" `
-Organization "good.four.us" `
Expand Down
8 changes: 4 additions & 4 deletions Testing/Functional/Products/Products.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -205,10 +205,10 @@ BeforeAll {
function RunScuba() {
if (-not [string]::IsNullOrEmpty($Thumbprint))
{
Invoke-SCuBA -CertificateThumbPrint $Thumbprint -AppId $AppId -Organization $TenantDomain -Productnames $ProductName -OutPath . -M365Environment $M365Environment -Quiet
Invoke-SCuBA -CertificateThumbPrint $Thumbprint -AppId $AppId -Organization $TenantDomain -Productnames $ProductName -OutPath . -M365Environment $M365Environment -Quiet -KeepIndividualJSON
}
else {
Invoke-SCuBA -Login $false -Productnames $ProductName -OutPath . -M365Environment $M365Environment -Quiet
Invoke-SCuBA -Login $false -Productnames $ProductName -OutPath . -M365Environment $M365Environment -Quiet -KeepIndividualJSON
}
}
}
Expand Down Expand Up @@ -241,7 +241,7 @@ Describe "Policy Checks for <ProductName>"{

Set-Content -Path $TestConfigFilePath -Value ($ScubaConfig | ConvertTo-Yaml)
SetConditions -Conditions $Preconditions.ToArray()
Invoke-SCuBA -ConfigFilePath $TestConfigFilePath -Quiet
Invoke-SCuBA -ConfigFilePath $TestConfigFilePath -Quiet -KeepIndividualJSON
}
# Ensure case matches driver in test plan
elseif ('RunScuba' -eq $TestDriver){
Expand All @@ -256,7 +256,7 @@ Describe "Policy Checks for <ProductName>"{
$ReportFolders = Get-ChildItem . -directory -Filter "M365BaselineConformance*" | Sort-Object -Property LastWriteTime -Descending
$OutputFolder = $ReportFolders[0].Name
SetConditions -Conditions $Preconditions.ToArray() -OutputFolder $OutputFolder
Invoke-SCuBACached -Productnames $ProductName -ExportProvider $false -OutPath $OutputFolder -OutProviderFileName 'ModifiedProviderSettingsExport' -Quiet
Invoke-SCuBACached -Productnames $ProductName -ExportProvider $false -OutPath $OutputFolder -OutProviderFileName 'ModifiedProviderSettingsExport' -Quiet -KeepIndividualJSON
}
else {
Write-Debug "Driver: $TestDriver"
Expand Down
4 changes: 2 additions & 2 deletions Testing/Functional/SmokeTest/SmokeTest001.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ Describe "Smoke Test: Generate Output" {
Context "Invoke Scuba for $Organization" {
BeforeAll {
if ($PSCmdlet.ParameterSetName -eq 'Manual'){
{ Invoke-SCuBA -ProductNames "*" -M365Environment $M365Environment -Quiet} |
{ Invoke-SCuBA -ProductNames "*" -M365Environment $M365Environment -Quiet -KeepIndividualJSON} |
Should -Not -Throw
}
else {
{ Invoke-SCuBA -CertificateThumbprint $Thumbprint -AppID $AppId -Organization $Organization -ProductNames "*" -M365Environment $M365Environment -Quiet} |
{ Invoke-SCuBA -CertificateThumbprint $Thumbprint -AppID $AppId -Organization $Organization -ProductNames "*" -M365Environment $M365Environment -Quiet -KeepIndividualJSON} |
Should -Not -Throw
}
$ReportFolders = Get-ChildItem . -directory -Filter "M365BaselineConformance*" | Sort-Object -Property LastWriteTime -Descending
Expand Down
15 changes: 7 additions & 8 deletions docs/configuration/parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,9 @@ The list of acceptable values are:
| Government cloud tenants (high) | gcchigh |
| Department of Defense tenants | dod |

## MergeJson
## KeepIndividualJSON

**MergeJson** combines the individual JSON files (named `TeamsReport.json`) in the `IndividualReports` folder together with the `ProviderSettingsExport.json` into an uber JSON file named `ScubaResults.json`. The individual JSON files are deleted.
**KeepIndividualJSON** Keeps the individual JSON files (e.g., `TeamsReport.json`) in the `IndividualReports` folder along with `ProviderSettingsExport.json` without combining the results in to one uber JSON file named the `ScubaResults.json`. The parameter is for backwards compatibility with older versions of ScubaGear.

| Parameter | Value |
|-------------|--------|
Expand All @@ -172,9 +172,9 @@ The list of acceptable values are:
| Config File | No |

```powershell
# Create a merged JSON file
# Outputs legacy ScubaGear individual JSON output
Invoke-SCuBA -ProductNames teams `
-MergeJson
-KeepIndividualJSON
```

## OPAPath
Expand Down Expand Up @@ -238,7 +238,7 @@ Invoke-SCuBA -ProductNames teams `

## OutJsonFileName

**OutJsonFileName** renames the uber JSON file that is created if the [MergeJson](#mergejson) parameter is used. This should only be the base file name, as the extension `.json` will automatically be added.
**OutJsonFileName** renames the uber output JSON file that is created after a ScubaGear run. This should only be the base file name, as the extension `.json` will automatically be added.

| Parameter | Value |
|-------------|--------------------|
Expand All @@ -247,13 +247,12 @@ Invoke-SCuBA -ProductNames teams `
| Default | `ScubaResults.json` |
| Config File | No |

> **Note**: This parameter does not work if the `-MergeJson` parameter is not present.
> **Note**: This parameter does not work if the `-KeepIndividualJSON` parameter is present.
```powershell
# Change the output JSON file
Invoke-SCuBA -ProductNames teams `
-OutJsonFileName myresults `
-MergeJson
-OutJsonFileName myresults
```

## OutCsvFileName
Expand Down
4 changes: 2 additions & 2 deletions docs/execution/reports.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ When ScubaGear runs, it creates a new time-stamped subdirectory wherein it will
|------------------------------|-----------|
| `IndividualReports` | This directory contains the detailed reports for each product tested. |
| `BaselineReports.html` | This HTML file is a summary of the detailed reports. By default, this file is automatically opened in a web browser after running ScubaGear. |
| `ProvideSettingsExport.json` | This JSON file contains all of the information that ScubaGear extracted from the products. A highly-motivated admin might find this useful for understanding how ScubaGear arrived at its results. Only present if ScubaGear is run without the `MergeJson` flag; if run with the `MergeJson` parameter, the contents of this file will be merged into the ScubaResults.json file. |
| `ScubaResults.json` | This JSON file encapsulates all ScubaGear output in a format can could be automatically parsed by a downstream system. It contains metadata about the run and the tenant, summary counts of the test results, the test results, and the raw provider output. Only present if ScubaGear is run with the `MergeJson` flag. |
| `ProvideSettingsExport.json` | This JSON file contains all of the information that ScubaGear extracted from the products. A highly-motivated admin might find this useful for understanding how ScubaGear arrived at its results. Only present if ScubaGear is run with the `KeepIndividualJson` flag; if run without the `KeepIndividualJSON` parameter, the contents of this file will be merged into the ScubaResults.json file. |
| `ScubaResults.json` | This JSON file encapsulates all ScubaGear output in a format that is automatically parsed by a downstream system. It contains metadata about the run and the tenant, summary counts of the test results, the test results, and the raw provider output. Not present if ScubaGear is run with the `KeepIndividualJSON` flag. |
| `ScubaResults.csv` | This CSV file contains the test results in a format can could be automatically parsed by a downstream system. Note that this CSV file only contains the results (i.e., the control ID, requirement string, etc.). It does not contain all data contained in the HTML or JSON versions of the output (i.e., the metadata, summary counts, or raw provider output) due to the limitations of CSV files. Additionally, it includes fields where users can document reasons for failures and timelines for remediation, if they so choose. |

You can learn more about setting parameters on the [parameters](../configuration/parameters.md) page.

0 comments on commit b8f5480

Please sign in to comment.