Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the report UUID to the ScubaResults.json filename #1426

Merged
merged 40 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
960490b
Initial implementation of adding UUID to the file name
adhilto Nov 13, 2024
e9f353b
Add back missing ConvertFrom-Json call
adhilto Nov 13, 2024
d7e44a6
Mock Get-ChildItem in unit tests
adhilto Nov 13, 2024
f91b119
Document addition of UUID to ScubaResults file name
adhilto Nov 13, 2024
c1e0b1c
Add unit tests for when there are multiple ScubaResults*.json files
adhilto Nov 14, 2024
6451c12
Correct minor typo in documentation
adhilto Nov 14, 2024
e63356e
remove wildcard search in ConvertTo-ResultsCSV code path
buidav Nov 16, 2024
80fc0a4
add error handling of window path length limit errors
buidav Nov 16, 2024
3c504a3
fix some of the tests
buidav Nov 16, 2024
8dcb093
fix the all the current broken unit tests
buidav Nov 16, 2024
f351444
additional unit tests
buidav Nov 18, 2024
c0c8f23
add back in accidentally removed fields in config
buidav Nov 18, 2024
54da434
complete lorem ipsum
buidav Nov 18, 2024
88c0fe2
todo message
buidav Nov 18, 2024
257eb88
remove UUID truncation for now
buidav Nov 18, 2024
19c2122
first draft
buidav Nov 19, 2024
252a648
add truncation param to documenatation
buidav Nov 19, 2024
16e19fc
spacing
buidav Nov 19, 2024
643f689
fix failing test cases; handle full truncation case
buidav Nov 19, 2024
c8b0449
make code consistent; add code comments to describe it's purpose
buidav Nov 19, 2024
e68f055
review feedback; point to additional options in the error message
buidav Nov 19, 2024
8e03b77
PR Review: Fix absolute path check; fix config file override
buidav Nov 19, 2024
011751d
review feedback; move new parameter in alphabetical order in docs
buidav Nov 19, 2024
d78b0a5
keep documentation consistent
buidav Nov 20, 2024
2d3481d
remove configuration paramset from scubacached
buidav Nov 20, 2024
50fbb4a
code comments for the new edge case
buidav Nov 20, 2024
0d4b78e
Remove OBE unit test
adhilto Nov 20, 2024
5d7cfee
Remove duplicate word
adhilto Nov 20, 2024
c38d1f0
fix typos, wording and formatting in config
buidav Nov 20, 2024
9022b72
Refactor truncation logic into own function
adhilto Nov 20, 2024
f2fcb76
rm duplicate text from PowerShell as well
buidav Nov 20, 2024
9f240fb
captialize
buidav Nov 20, 2024
04d0bd3
remove long path check let the set-content naturally error out
buidav Nov 20, 2024
d4008d3
add long path error check within the catch block
buidav Nov 20, 2024
01b9ecb
remove todo
buidav Nov 21, 2024
2c562e9
Add UUID to mock data for cached tests
adhilto Nov 20, 2024
a1f7f80
Fix unit tests
adhilto Nov 20, 2024
a55387f
Remove commented out validation code.
buidav Nov 21, 2024
723da01
add validation set to check invalid config file parameter
buidav Nov 21, 2024
031a26f
Remove stacktrace
adhilto Nov 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
242 changes: 178 additions & 64 deletions PowerShell/ScubaGear/Modules/Orchestrator.psm1

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions PowerShell/ScubaGear/Modules/ScubaConfig/ScubaConfig.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class ScubaConfig {
DefaultOutJsonFileName = "ScubaResults"
DefaultOutCsvFileName = "ScubaResults"
DefaultOutActionPlanFileName = "ActionPlan"
DefaultNumberOfUUIDCharactersToTruncate = 18
DefaultPrivilegedRoles = @(
"Global Administrator",
"Privileged Role Administrator",
Expand Down Expand Up @@ -156,6 +157,10 @@ class ScubaConfig {
$this.Configuration.OutActionPlanFileName = [ScubaConfig]::ScubaDefault('DefaultOutActionPlanFileName')
}

if (-Not $this.Configuration.NumberOfUUIDCharactersToTruncate){
$this.Configuration.NumberOfUUIDCharactersToTruncate = [ScubaConfig]::ScubaDefault('DefaultNumberOfUUIDCharactersToTruncate')
}

return
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
},
"Tool": "ScubaGear",
"ToolVersion": "1.4.0",
"TimestampZulu": "2024-08-02T19:25:11.166Z"
"TimestampZulu": "2024-08-02T19:25:11.166Z",
"ReportUUID": "21189b0e-f045-43ee-b9ba-653b32744e45"
},
"Summary": {
"AAD": {
Expand Down Expand Up @@ -1339,6 +1340,7 @@
"module_version": "1.4.0",
"date": "08/02/2024 14:25:11 Central Daylight Time",
"timestamp_zulu": "2024-08-02T19:25:11.166Z",
"report_uuid": "21189b0e-f045-43ee-b9ba-653b32744e45",
"tenant_details": [
{
"AADAdditionalData": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ InModuleScope Orchestrator {
Mock -CommandName Get-FileEncoding
Mock -CommandName ConvertTo-Csv { "" }
Mock -CommandName Write-Warning {}
Mock -CommandName Get-ChildItem {
[pscustomobject]@{"FullName"="ScubaResults_00000000-0000-0000-0000-000000000000.json"; "CreationTime"=[DateTime]"2024-01-01"}
}
}

It 'Handles multiple products, control groups, and controls' {
Expand Down Expand Up @@ -56,10 +59,10 @@ InModuleScope Orchestrator {
}}
}
$CsvParameters = @{
ProductNames = @("exo", "aad");
OutFolderPath = ".";
OutJsonFileName = "ScubaResults";
OutCsvFileName = "ScubaResults";
ProductNames = @("exo", "aad");
OutFolderPath = ".";
FullScubaResultsName = "ScubaResults";
OutCsvFileName = "ScubaResults";
OutActionPlanFileName = "ActionPlan";
}
{ ConvertTo-ResultsCsv @CsvParameters} | Should -Not -Throw
Expand All @@ -74,10 +77,10 @@ InModuleScope Orchestrator {
Mock -CommandName ConvertFrom-Json {}
Mock -CommandName Get-Content { throw "File not found" }
$CsvParameters = @{
ProductNames = @("exo", "aad");
OutFolderPath = ".";
OutJsonFileName = "ScubaResults";
OutCsvFileName = "ScubaResults";
ProductNames = @("exo", "aad");
OutFolderPath = ".";
FullScubaResultsName = "ScubaResults";
OutCsvFileName = "ScubaResults";
OutActionPlanFileName = "ActionPlan";
}
{ ConvertTo-ResultsCsv @CsvParameters} | Should -Not -Throw
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
$OrchestratorPath = '../../../../Modules/Orchestrator.psm1'
Import-Module (Join-Path -Path $PSScriptRoot -ChildPath $OrchestratorPath) -Function 'Get-FullOutJsonName'

Describe -Tag 'Orchestrator' -Name 'Get-FullOutJsonName' {
InModuleScope Orchestrator {
It 'Adds the full UUID' {
$FullNameParams = @{
'OutJsonFileName' = "ScubaResults";
'Guid' = "30ebce05-f8f0-4a09-8ec2-589efbbd0e72";
'NumberOfUUIDCharactersToTruncate' = 0;
}
(Get-FullOutJsonName @FullNameParams) | Should -eq "ScubaResults_30ebce05-f8f0-4a09-8ec2-589efbbd0e72.json"
}
It 'Handles partial truncation' {
$FullNameParams = @{
'OutJsonFileName' = "ScubaResults";
'Guid' = "30ebce05-f8f0-4a09-8ec2-589efbbd0e72";
'NumberOfUUIDCharactersToTruncate' = 18;
}
(Get-FullOutJsonName @FullNameParams) | Should -eq "ScubaResults_30ebce05-f8f0-4a09.json"
}
It 'Handles full truncation' {
$FullNameParams = @{
'OutJsonFileName' = "ScubaResults";
'Guid' = "30ebce05-f8f0-4a09-8ec2-589efbbd0e72";
'NumberOfUUIDCharactersToTruncate' = 36;
}
(Get-FullOutJsonName @FullNameParams) | Should -eq "ScubaResults.json"
}
It 'Handles non-default names' {
$FullNameParams = @{
'OutJsonFileName' = "my_results";
'Guid' = "30ebce05-f8f0-4a09-8ec2-589efbbd0e72";
'NumberOfUUIDCharactersToTruncate' = 18;
}
(Get-FullOutJsonName @FullNameParams) | Should -eq "my_results_30ebce05-f8f0-4a09.json"
}
}
}

AfterAll {
Remove-Module Orchestrator -ErrorAction SilentlyContinue
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,13 @@ Describe -Tag 'Orchestrator' -Name 'Invoke-ProviderList' {
BeforeAll {
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'ProviderParameters')]
$ProviderParameters = @{
OutFolderPath = "./output";
OutProviderFileName = "ProviderSettingsExport";
M365Environment = "commercial";
TenantDetails = '{"DisplayName": "displayName"}';
ModuleVersion = '1.0';
BoundParameters = @{};
OutFolderPath = "./output";
OutProviderFileName = "ProviderSettingsExport";
M365Environment = "commercial";
TenantDetails = '{"DisplayName": "displayName"}';
ModuleVersion = '1.0';
BoundParameters = @{};
Guid = "00000000-0000-0000-0000-000000000000"
}
}
It 'With -ProductNames "aad", should not throw' {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,16 @@ InModuleScope Orchestrator {

Mock -CommandName Write-Debug {}
Mock -CommandName New-Item {}
Mock -CommandName Get-Content {}
Mock -CommandName Get-Content { "" }
Mock -CommandName Get-Member { $true }
Mock -CommandName New-Guid { "00000000-0000-0000-0000-000000000000" }
Mock -CommandName Get-ChildItem {
[pscustomobject]@{"FullName"="ScubaResults.json"; "CreationTime"=[DateTime]"2024-01-01"}
}
Mock -CommandName Remove-Item {}
Mock -CommandName ConvertFrom-Json {
[PSCustomObject]@{"report_uuid"="00000000-0000-0000-0000-000000000000"}
}
}
Context 'When checking the conformance of commercial tenants' {
BeforeAll {
Expand Down Expand Up @@ -126,6 +133,7 @@ InModuleScope Orchestrator {
Should -Invoke -CommandName New-Guid -Exactly -Times 0
}
It 'Given output without a UUID should generate a new one' {
Mock -CommandName ConvertFrom-Json { [PSCustomObject]@{} }
Mock -CommandName Get-Member { $false }
# Now Get-Member will return False so as far as the provider
# can tell, the existing output does not have a UUID
Expand Down Expand Up @@ -166,6 +174,27 @@ InModuleScope Orchestrator {
{Invoke-SCuBACached @SplatParams} | Should -Throw
}
}
Context "When there are multiple ScubaResults*.json files" {
# It's possible (but not expected) that there are multiple files matching
# "ScubaResults*.json". In this case, ScubaGear should choose the file
# created most recently.
It 'Should select the most recently created' {
Mock -CommandName Get-ChildItem { @(
[pscustomobject]@{"FullName"="ScubaResultsOld.json"; "CreationTime"=[DateTime]"2023-01-01"},
[pscustomobject]@{"FullName"="ScubaResultsNew.json"; "CreationTime"=[DateTime]"2024-01-01"},
[pscustomobject]@{"FullName"="ScubaResultsOldest.json"; "CreationTime"=[DateTime]"2022-01-01"}
) }

Mock -CommandName Get-Content {
if ($Path -ne "ScubaResultsNew.json") {
# Should be the new one, throw if not
throw
}
}

{Invoke-SCuBACached @SplatParams} | Should -Throw
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ Import-Module (Join-Path -Path $PSScriptRoot -ChildPath $OrchestratorPath) -Func
InModuleScope Orchestrator {
Describe -Tag 'Orchestrator' -Name 'Merge-JsonOutput' {
BeforeAll {
Mock -CommandName Join-Path { "." }
Mock -CommandName Out-File {}
Mock -CommandName Set-Content {}
Mock -CommandName Remove-Item {}
Mock -CommandName Get-Content { "" }
Mock -CommandName ConvertFrom-Json { @{
"ReportSummary"=@{"Date"=""}
"Results"=@();
"timestamp_zulu"="";
}
"ReportSummary" = @{"Date" = "" }
"Results" = @();
"timestamp_zulu" = "";
"report_uuid" = "00000000-0000-0000-0000-000000000000"
}
}
Mock -CommandName Add-Member {}
Mock -CommandName ConvertTo-Json { "" }
Expand All @@ -22,34 +22,38 @@ InModuleScope Orchestrator {
BeforeAll {
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'JsonParameters')]
$JsonParameters = @{
TenantDetails = @{"DisplayName" = "displayName"; "TenantId" = "tenantId"; "DomainName" = "domainName"};
ModuleVersion = '1.0';
OutFolderPath = "./"
OutProviderFileName = "ProviderSettingsExport"
OutJsonFileName = "ScubaResults"
TenantDetails = @{"DisplayName" = "displayName"; "TenantId" = "tenantId"; "DomainName" = "domainName" };
ModuleVersion = '1.0';
OutFolderPath = "./";
OutProviderFileName = "ProviderSettingsExport";
FullScubaResultsName = "ScubaResults.json";
Guid = "00000000-0000-0000-0000-000000000000";
}
}
It 'Merge single result' {
Mock -CommandName Join-Path { "." }
$JsonParameters += @{
ProductNames = @("aad")
ProductNames = @("aad");
}
{ Merge-JsonOutput @JsonParameters} | Should -Not -Throw
{ Merge-JsonOutput @JsonParameters } | Should -Not -Throw
Should -Invoke -CommandName ConvertFrom-Json -Exactly -Times 2
$JsonParameters.ProductNames = @()
}
It 'Merge multiple results' {
Mock -CommandName Join-Path { "." }
$JsonParameters += @{
ProductNames = @("aad", "teams")
ProductNames = @("aad", "teams");
}
{ Merge-JsonOutput @JsonParameters} | Should -Not -Throw
{ Merge-JsonOutput @JsonParameters } | Should -Not -Throw
Should -Invoke -CommandName ConvertFrom-Json -Exactly -Times 3
$JsonParameters.ProductNames = @()
}
It 'Delete redundant files' {
Mock -CommandName Join-Path { "." }
$JsonParameters += @{
ProductNames = @("aad", "teams")
ProductNames = @("aad", "teams");
}
{ Merge-JsonOutput @JsonParameters} | Should -Not -Throw
{ Merge-JsonOutput @JsonParameters } | Should -Not -Throw
Should -Invoke -CommandName Remove-Item -Exactly -Times 3
$JsonParameters.ProductNames = @()
}
Expand Down
Loading