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

Allow config file to override command line parameters #761

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
51 changes: 47 additions & 4 deletions PowerShell/ScubaGear/Modules/Orchestrator.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -110,29 +110,34 @@ function Invoke-SCuBA {
#>
[CmdletBinding(DefaultParameterSetName='Report')]
param (
[Parameter(Mandatory = $false, ParameterSetName = 'Configuration')]
[Parameter(Mandatory = $false, ParameterSetName = 'Report')]
[ValidateNotNullOrEmpty()]
[ValidateSet("teams", "exo", "defender", "aad", "powerplatform", "sharepoint", '*', IgnoreCase = $false)]
[string[]]
$ProductNames = @("teams", "exo", "defender", "aad", "sharepoint"),

[Parameter(Mandatory = $false, ParameterSetName = 'Configuration')]
[Parameter(Mandatory = $false, ParameterSetName = 'Report')]
[ValidateSet("commercial", "gcc", "gcchigh", "dod", IgnoreCase = $false)]
[ValidateNotNullOrEmpty()]
[string]
$M365Environment = "commercial",

[Parameter(Mandatory = $false, ParameterSetName = 'Configuration')]
[Parameter(Mandatory = $false, ParameterSetName = 'Report')]
[ValidateScript({Test-Path -PathType Container $_})]
[string]
$OPAPath = (Join-Path -Path $env:USERPROFILE -ChildPath ".scubagear\Tools"),

[Parameter(Mandatory = $false, ParameterSetName = 'Configuration')]
[Parameter(Mandatory = $false, ParameterSetName = 'Report')]
[ValidateNotNullOrEmpty()]
[ValidateSet($true, $false)]
[boolean]
$LogIn = $true,

[Parameter(Mandatory = $false, ParameterSetName = 'Configuration')]
[Parameter(Mandatory = $false, ParameterSetName = 'Report')]
[ValidateNotNullOrEmpty()]
[switch]
Expand All @@ -143,41 +148,49 @@ function Invoke-SCuBA {
[switch]
$Version,

[Parameter(Mandatory = $false, ParameterSetName = 'Configuration')]
[Parameter(Mandatory = $false, ParameterSetName = 'Report')]
[ValidateNotNullOrEmpty()]
[string]
$AppID,

[Parameter(Mandatory = $false, ParameterSetName = 'Configuration')]
[Parameter(Mandatory = $false, ParameterSetName = 'Report')]
[ValidateNotNullOrEmpty()]
[string]
$CertificateThumbprint,

[Parameter(Mandatory = $false, ParameterSetName = 'Configuration')]
[Parameter(Mandatory = $false, ParameterSetName = 'Report')]
[ValidateNotNullOrEmpty()]
[string]
$Organization,

[Parameter(Mandatory = $false, ParameterSetName = 'Configuration')]
[Parameter(Mandatory = $false, ParameterSetName = 'Report')]
[ValidateNotNullOrEmpty()]
[string]
$OutPath = '.',

[Parameter(Mandatory = $false, ParameterSetName = 'Configuration')]
[Parameter(Mandatory = $false, ParameterSetName = 'Report')]
[ValidateNotNullOrEmpty()]
[string]
$OutFolderName = "M365BaselineConformance",
kennethpalmer marked this conversation as resolved.
Show resolved Hide resolved

[Parameter(Mandatory = $false, ParameterSetName = 'Configuration')]
[Parameter(Mandatory = $false, ParameterSetName = 'Report')]
[ValidateNotNullOrEmpty()]
[string]
$OutProviderFileName = "ProviderSettingsExport",

[Parameter(Mandatory = $false, ParameterSetName = 'Configuration')]
[Parameter(Mandatory = $false, ParameterSetName = 'Report')]
[ValidateNotNullOrEmpty()]
[string]
$OutRegoFileName = "TestResults",

[Parameter(Mandatory = $false, ParameterSetName = 'Configuration')]
[Parameter(Mandatory = $false, ParameterSetName = 'Report')]
[ValidateNotNullOrEmpty()]
[string]
Expand All @@ -197,6 +210,7 @@ function Invoke-SCuBA {
[System.IO.FileInfo]
$ConfigFilePath,

[Parameter(Mandatory = $false, ParameterSetName = 'Configuration')]
[Parameter(Mandatory = $false, ParameterSetName = 'Report')]
[ValidateNotNullOrEmpty()]
[switch]
Expand Down Expand Up @@ -245,17 +259,46 @@ function Invoke-SCuBA {

# Loads and executes parameters from a Configuration file
if ($PSCmdlet.ParameterSetName -eq 'Configuration'){
[ScubaConfig]::ResetInstance()
if (-Not ([ScubaConfig]::GetInstance().LoadConfig($ConfigFilePath))){
Write-Error -Message "The config file failed to load: $ConfigFilePath"
}
else {
$ScubaConfig = [ScubaConfig]::GetInstance().Configuration
}

if ($ScubaConfig.AppID){
$PSBoundParameters.Add("AppID", $ScubaConfig.AppID)
$PSBoundParameters.Add("CertificateThumbprint", $ScubaConfig.CertificateThumbprint)
$PSBoundParameters.Add("Organization", $ScubaConfig.Organization)
# Authentications parameters use below
$SPparams = 'AppID', 'CertificateThumbprint', 'Organization'

# Bound parameters indicate a parameter has been passed in.
# However authentication parameters are special and are not handled within
# the config module (since you can't make a default). If an authentication
# parameter is set in the config file but not supplied on the command line
# set the Bound parameters value which make it appear as if it was supplied on the
# command line

foreach ( $value in $SPparams )
{
if ( $ScubaConfig[$value] -and (-not $PSBoundParameters[$value] )) {
$PSBoundParameters.Add($value, $ScubaConfig[$value])
}
}

# Now the bound parameters contain the following
# 1) Non Authentication Parameters explicitly passed in
# 2) Authentication parameters ( passed in or from the config file as per code above )
#
# So to provide for a command line override of config values just set the corresponding
# config value from the bound parameters to override. This is redundant copy for
# the authentication parameters ( but keeps the logic simpler)
# We do not allow ConfigFilePath to be copied as it will be propagated to the
# config module by reference and causes issues
#
foreach ( $value in $PSBoundParameters.keys ) {
if ( $value -ne "ConfigFilePath" )
{
$ScubaConfig[$value] = $PSBoundParameters[$value]
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions PowerShell/ScubaGear/Modules/ScubaConfig/ScubaConfig.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class ScubaConfig {
}

if (-Not $this.Configuration.OPAPath){
$this.Configuration.OPAPath = (Join-Path -Path $PSScriptRoot -ChildPath "..\..\..")
$this.Configuration.OPAPath = (Join-Path -Path $PSScriptRoot -ChildPath "..\..\..\..")
kennethpalmer marked this conversation as resolved.
Show resolved Hide resolved
}

if (-Not $this.Configuration.LogIn){
Expand All @@ -62,7 +62,7 @@ class ScubaConfig {
}

if (-Not $this.Configuration.OutRegoFileName){
$this.Configuration.OutFolderName = "TestResults"
$this.Configuration.OutRegoFileName = "TestResults"
}

if (-Not $this.Configuration.OutReportName){
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
$OrchestratorPath = '../../../../Modules/Orchestrator.psm1'
Import-Module (Join-Path -Path $PSScriptRoot -ChildPath $OrchestratorPath) -Force

InModuleScope Orchestrator {
Context "Parameter override test"{
BeforeAll{
$ConnectionPath = '../../../../Modules/Connection/Connection.psm1'
Import-Module (Join-Path -Path $PSScriptRoot -ChildPath $ConnectionPath) -Function Disconnect-SCuBATenant -Force

function SetupMocks{
$script:TestSplat = @{}
Mock -ModuleName Orchestrator Remove-Resources {}
Mock -ModuleName Orchestrator Import-Resources {}
Mock -ModuleName Orchestrator Invoke-Connection {
$script:TestSplat.Add('LogIn', $LogIn)
}
Mock -ModuleName Orchestrator Get-TenantDetail { '{"DisplayName": "displayName"}' }
Mock -ModuleName Orchestrator Invoke-ProviderList {
$script:TestSplat.Add('AppID', $BoundParameters.AppID)
$script:TestSplat.Add('Organization', $BoundParameters.Organization)
$script:TestSplat.Add('CertificateThumbprint', $BoundParameters.CertificateThumbprint)
}
Mock -ModuleName Orchestrator Invoke-RunRego {
$script:TestSplat.Add('OPAPath', $OPAPath)
$script:TestSplat.Add('OutProviderFileName', $OutProviderFileName)
$script:TestSplat.Add('OutRegoFileName', $OutRegoFileName)
}
Mock -ModuleName Orchestrator Invoke-ReportCreation {
$script:TestSplat.Add('ProductNames', $ProductNames)
$script:TestSplat.Add('M365Environment', $M365Environment)
$script:TestSplat.Add('OutPath', $ScubaConfig.OutPath)
$script:TestSplat.Add('OutFolderName', $ScubaConfig.OutFolderName)
$script:TestSplat.Add('OutReportName', $ScubaConfig.OutReportName)
}
Mock -ModuleName Orchestrator Disconnect-SCuBATenant {
$script:TestSplat.Add('DisconnectOnExit', $DisconnectOnExit)
}
Mock -CommandName New-Item {}
Mock -CommandName Copy-Item {}
}
}

Describe -Tag 'Orchestrator' -Name 'Invoke-Scuba config with no command line override' {
BeforeAll {
SetupMocks
Invoke-SCuBA -ConfigFilePath (Join-Path -Path $PSScriptRoot -ChildPath "orchestrator_config_test.yaml")
}

It "Verify parameter ""<parameter>"" with value ""<value>""" -ForEach @(
@{ Parameter = "M365Environment"; Value = "commercial" },
@{ Parameter = "ProductNames"; Value = @("teams") },
@{ Parameter = "OPAPath"; Value = "." },
@{ Parameter = "LogIn"; Value = $true },
@{ Parameter = "OutPath"; Value = ".." },
@{ Parameter = "OutFolderName"; Value = "ScubaReports" },
@{ Parameter = "OutProviderFileName"; Value = "TenantSettingsExport" },
@{ Parameter = "OutRegoFileName"; Value = "ScubaTestResults" },
@{ Parameter = "OutReportName"; Value = "ScubaReports" },
@{ Parameter = "Organization"; Value = "sub.domain.com" },
@{ Parameter = "AppID"; Value = "7892dfe467aef9023be" },
@{ Parameter = "CertificateThumbprint"; Value = "8A673F1087453ABC894" }
){
$script:TestSplat[$Parameter] | Should -BeExactly $Value -Because "got $($script:TestSplat[$Parameter])"
}
}
Describe -Tag 'Orchestrator' -Name 'Invoke-Scuba config with command line override' {
BeforeAll {
SetupMocks
Invoke-SCuBA `
-M365Environment "gcc" `
-ProductNames "aad" `
-OPAPath $env:TEMP `
-LogIn:$false `
-OutPath $env:TEMP `
-OutFolderName "MyReports" `
-OutProviderFileName "MySettingsExport" `
-OutRegoFileName "RegoResults" `
-OutReportName "MyReport" `
-Organization "good.four.us" `
-AppID "1212121212121212121" `
-CertificateThumbprint "AB123456789ABCDEF01" `
-ConfigFilePath (Join-Path -Path $PSScriptRoot -ChildPath "orchestrator_config_test.yaml")
}

It "Verify parameter ""<parameter>"" with value ""<value>""" -ForEach @(
@{ Parameter = "M365Environment"; Value = "gcc" },
@{ Parameter = "ProductNames"; Value = @("aad") },
@{ Parameter = "OPAPath"; Value = $env:TEMP },
@{ Parameter = "LogIn"; Value = $false },
@{ Parameter = "OutPath"; Value = $env:TEMP },
@{ Parameter = "OutFolderName"; Value = "MyReports" },
@{ Parameter = "OutProviderFileName"; Value = "MySettingsExport" },
@{ Parameter = "OutRegoFileName"; Value = "RegoResults" },
@{ Parameter = "OutReportName"; Value = "MyReport" },
@{ Parameter = "Organization"; Value = "good.four.us" },
@{ Parameter = "AppID"; Value = "1212121212121212121" },
@{ Parameter = "CertificateThumbprint"; Value = "AB123456789ABCDEF01" }
){
$script:TestSplat[$Parameter] | Should -BeExactly $Value -Because "got $($script:TestSplat[$Parameter])"
}
}
}
}
AfterAll {
Remove-Module Orchestrator -ErrorAction SilentlyContinue
Remove-Module Connection -ErrorAction SilentlyContinue
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Description: YAML Configuration file for unit test of ConfigFilePath overrides
ProductNames:
- teams
M365Environment: commercial
OPAPath: .
LogIn: true
DisconnectOnExit: false
OutPath: ..
OutFolderName: ScubaReports
OutProviderFileName: TenantSettingsExport
OutRegoFileName: ScubaTestResults
OutReportName: ScubaReports

# Test parameters for credentials
Organization: sub.domain.com
AppID: 7892dfe467aef9023be
CertificateThumbprint: 8A673F1087453ABC894
Loading
Loading