From f926c63533f15d391961c1d2ad23a779fc3bef34 Mon Sep 17 00:00:00 2001
From: DrIOS <58635327+DrIOSX@users.noreply.github.com>
Date: Sat, 8 Jun 2024 17:19:22 -0500
Subject: [PATCH 01/13] add: tenantadmin url as optional parameter
---
source/Private/Connect-M365Suite.ps1 | 2 +-
source/Public/Invoke-M365SecurityAudit.ps1 | 35 ++++++++++++----------
2 files changed, 20 insertions(+), 17 deletions(-)
diff --git a/source/Private/Connect-M365Suite.ps1 b/source/Private/Connect-M365Suite.ps1
index 468d068..3e2404e 100644
--- a/source/Private/Connect-M365Suite.ps1
+++ b/source/Private/Connect-M365Suite.ps1
@@ -1,7 +1,7 @@
function Connect-M365Suite {
[CmdletBinding()]
param (
- [Parameter(Mandatory)]
+ [Parameter(Mandatory=$false)]
[string]$TenantAdminUrl,
[Parameter(Mandatory)]
diff --git a/source/Public/Invoke-M365SecurityAudit.ps1 b/source/Public/Invoke-M365SecurityAudit.ps1
index 87509c6..5a8b249 100644
--- a/source/Public/Invoke-M365SecurityAudit.ps1
+++ b/source/Public/Invoke-M365SecurityAudit.ps1
@@ -4,7 +4,7 @@
.DESCRIPTION
The Invoke-M365SecurityAudit cmdlet performs a comprehensive security audit based on the specified parameters. It allows auditing of various configurations and settings within a Microsoft 365 environment, such as compliance with CIS benchmarks.
.PARAMETER TenantAdminUrl
- The URL of the tenant admin. This parameter is mandatory.
+ The URL of the tenant admin. If not specified, none of the SharePoint Online tests will run.
.PARAMETER M365DomainForPWPolicyTest
The domain name of the Microsoft 365 environment to test. This parameter is not mandatory and by default it will pass/fail all found domains as a group if a specific domain is not specified.
.PARAMETER ELevel
@@ -28,21 +28,17 @@
.PARAMETER NoModuleCheck
If specified, the cmdlet will not check for the presence of required modules.
.EXAMPLE
- PS> Invoke-M365SecurityAudit -TenantAdminUrl "https://contoso-admin.sharepoint.com" -DomainName "contoso.com" -ELevel "E5" -ProfileLevel "L1"
-
+ PS> Invoke-M365SecurityAudit -TenantAdminUrl "https://contoso-admin.sharepoint.com" -M365DomainForPWPolicyTest "contoso.com" -ELevel "E5" -ProfileLevel "L1"
Performs a security audit for the E5 level and L1 profile in the specified Microsoft 365 environment.
.EXAMPLE
- PS> Invoke-M365SecurityAudit -TenantAdminUrl "https://contoso-admin.sharepoint.com" -DomainName "contoso.com" -IncludeIG1
-
+ PS> Invoke-M365SecurityAudit -TenantAdminUrl "https://contoso-admin.sharepoint.com" -M365DomainForPWPolicyTest "contoso.com" -IncludeIG1
Performs an audit including all tests where IG1 is true.
.EXAMPLE
- PS> Invoke-M365SecurityAudit -TenantAdminUrl "https://contoso-admin.sharepoint.com" -DomainName "contoso.com" -SkipRecommendation '1.1.3', '2.1.1'
-
+ PS> Invoke-M365SecurityAudit -TenantAdminUrl "https://contoso-admin.sharepoint.com" -M365DomainForPWPolicyTest "contoso.com" -SkipRecommendation '1.1.3', '2.1.1'
Performs an audit while excluding specific recommendations 1.1.3 and 2.1.1.
.EXAMPLE
- PS> $auditResults = Invoke-M365SecurityAudit -TenantAdminUrl "https://contoso-admin.sharepoint.com" -DomainName "contoso.com"
+ PS> $auditResults = Invoke-M365SecurityAudit -TenantAdminUrl "https://contoso-admin.sharepoint.com" -M365DomainForPWPolicyTest "contoso.com"
PS> $auditResults | Export-Csv -Path "auditResults.csv" -NoTypeInformation
-
Captures the audit results into a variable and exports them to a CSV file.
.INPUTS
None. You cannot pipe objects to Invoke-M365SecurityAudit.
@@ -50,20 +46,21 @@
CISAuditResult[]
The cmdlet returns an array of CISAuditResult objects representing the results of the security audit.
.NOTES
- - This module is based on CIS benchmarks.
- - Governed by the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
- - Commercial use is not permitted. This module cannot be sold or used for commercial purposes.
- - Modifications and sharing are allowed under the same license.
- - For full license details, visit: https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en
- - Register for CIS Benchmarks at: https://www.cisecurity.org/cis-benchmarks
+ - This module is based on CIS benchmarks.
+ - Governed by the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
+ - Commercial use is not permitted. This module cannot be sold or used for commercial purposes.
+ - Modifications and sharing are allowed under the same license.
+ - For full license details, visit: https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en
+ - Register for CIS Benchmarks at: https://www.cisecurity.org/cis-benchmarks
.LINK
https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Invoke-M365SecurityAudit
#>
+
function Invoke-M365SecurityAudit {
[CmdletBinding(SupportsShouldProcess = $true, DefaultParameterSetName = 'Default')]
[OutputType([CISAuditResult[]])]
param (
- [Parameter(Mandatory = $true, HelpMessage = "The SharePoint tenant admin URL, which should end with '-admin.sharepoint.com'.")]
+ [Parameter(Mandatory = $false, HelpMessage = "The SharePoint tenant admin URL, which should end with '-admin.sharepoint.com'. If not specified none of the Sharepoint Online tests will run.")]
[ValidatePattern('^https://[a-zA-Z0-9-]+-admin\.sharepoint\.com$')]
[string]$TenantAdminUrl,
@@ -151,6 +148,12 @@ function Invoke-M365SecurityAudit {
$testDefinitions = Get-TestDefinitionsObject @params
# Extract unique connections needed
$requiredConnections = $testDefinitions.Connection | Sort-Object -Unique
+ if ($requiredConnections -contains 'SPO'){
+ if (-not $TenantAdminUrl) {
+ $requiredConnections = $requiredConnections | Where-Object { $_ -ne 'SPO' }
+ $testDefinitions = $testDefinitions | Where-Object { $_.Connection -ne 'SPO' }
+ }
+ }
# Establishing connections if required
if (!($DoNotConnect)) {
Connect-M365Suite -TenantAdminUrl $TenantAdminUrl -RequiredConnections $requiredConnections
From 5d681f3d72b57426735e8bada31d758b9bf1dc4e Mon Sep 17 00:00:00 2001
From: DrIOS <58635327+DrIOSX@users.noreply.github.com>
Date: Sat, 8 Jun 2024 17:19:39 -0500
Subject: [PATCH 02/13] docs: update CHANGELOG
---
CHANGELOG.md | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9dca7b8..3499940 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,13 @@ The format is based on and uses the types of changes according to [Keep a Change
- Added pipeline support to `Sync-CISExcelAndCsvData` function for `[CISAuditResult[]]` input.
+### Changed
+
+- Updated `Connect-M365Suite` to make `TenantAdminUrl` an optional parameter.
+- Updated `Invoke-M365SecurityAudit` to make `TenantAdminUrl` an optional parameter.
+- Improved connection handling and error messaging in `Connect-M365Suite`.
+- Enhanced `Invoke-M365SecurityAudit` to allow flexible inclusion and exclusion of specific recommendations, IG filters, and profile levels.
+
## [0.1.5] - 2024-06-08
### Added
From 9199d97fc24051a07a01fa5d5c58a23edec1a5f0 Mon Sep 17 00:00:00 2001
From: DrIOS <58635327+DrIOSX@users.noreply.github.com>
Date: Sat, 8 Jun 2024 17:22:39 -0500
Subject: [PATCH 03/13] docs: Update Help and README
---
README.md | Bin 24558 -> 24766 bytes
docs/index.html | Bin 66884 -> 67100 bytes
2 files changed, 0 insertions(+), 0 deletions(-)
diff --git a/README.md b/README.md
index 956c8f35beb2e356587e47b82e0d9dd3d075a764..c306c67966493af5bd0379e9fdd60538062d3929 100644
GIT binary patch
delta 337
zcmaF2pK;$o#tpyNC+i3rZ8qRo!^;>w`Jk2JWCKY7#@NaBlKzvU#J-@31#Uhk?!<^J
zxY=GZ8btu8GkLO(^bcf3V6km7=wk7kZR9l2H3v>kvsT;8r4Yu%?8%TexmHDX@&<2~
z$UKI8hCGH;1_dCU1|&-uGQhlGAf3oi1Y`#QWio+kN`SKdKspD^1L-IM$`%93Vj#O5
zD4GL=3P3%jKvjB^6+Oi#UoeoE?BFS|`HE7D$mAArlg)YN5=klxF)a0s2smTj$CvCQ}+oA{nj!8k;!V
7MjfF
qZnxP)xkY61hZu>;Zgvuz*)0As!Z|@!H3*K3%@-Kw$Yv({J&FJ;omZRy
diff --git a/docs/index.html b/docs/index.html
index 93cd28e8b7fca8f70efea22a9016c3775bbf6d39..da84fbc8956432eeb6d7e4908a9cba0ff38f8d76 100644
GIT binary patch
delta 328
zcmX@o#WJUdWx_pfa|SC0BL+hdx$)(6560-p2mNd(ZwO+U9O50ZSj>wNA+kBd`v4Lb
zs32
Date: Sat, 8 Jun 2024 17:26:30 -0500
Subject: [PATCH 04/13] fix: throw error if no test definitioins after SPO
removal
---
source/Public/Invoke-M365SecurityAudit.ps1 | 3 +++
1 file changed, 3 insertions(+)
diff --git a/source/Public/Invoke-M365SecurityAudit.ps1 b/source/Public/Invoke-M365SecurityAudit.ps1
index 5a8b249..ba4966f 100644
--- a/source/Public/Invoke-M365SecurityAudit.ps1
+++ b/source/Public/Invoke-M365SecurityAudit.ps1
@@ -152,6 +152,9 @@ function Invoke-M365SecurityAudit {
if (-not $TenantAdminUrl) {
$requiredConnections = $requiredConnections | Where-Object { $_ -ne 'SPO' }
$testDefinitions = $testDefinitions | Where-Object { $_.Connection -ne 'SPO' }
+ if ($null -eq $testDefinitions) {
+ throw "No tests to run as no SharePoint Online tests are available."
+ }
}
}
# Establishing connections if required
From f2e799af2f01e792247761442ad586efb79cdcc3 Mon Sep 17 00:00:00 2001
From: DrIOS <58635327+DrIOSX@users.noreply.github.com>
Date: Sat, 8 Jun 2024 17:31:28 -0500
Subject: [PATCH 05/13] docs: Update HelpE
---
source/Public/Invoke-M365SecurityAudit.ps1 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/source/Public/Invoke-M365SecurityAudit.ps1 b/source/Public/Invoke-M365SecurityAudit.ps1
index ba4966f..5f3795a 100644
--- a/source/Public/Invoke-M365SecurityAudit.ps1
+++ b/source/Public/Invoke-M365SecurityAudit.ps1
@@ -64,7 +64,7 @@ function Invoke-M365SecurityAudit {
[ValidatePattern('^https://[a-zA-Z0-9-]+-admin\.sharepoint\.com$')]
[string]$TenantAdminUrl,
- [Parameter(Mandatory = $false, HelpMessage = "Specify this to test only the default domain for password expiration policy when '1.3.1' is included in the tests to be run. The domain name of your organization, e.g., 'example.com'.")]
+ [Parameter(Mandatory = $false, HelpMessage = "All domains tested unless you Specify this to test only the selected domain for password expiration policy when '1.3.1' is included in the tests to be run. The domain name of your organization, e.g., 'example.com'.")]
[ValidatePattern('^[a-zA-Z0-9-]+\.[a-zA-Z]{2,}$')]
[string]$M365DomainForPWPolicyTest,
From ff9066998468fecde91bfdd0fed5801f4e0b0387 Mon Sep 17 00:00:00 2001
From: DrIOS <58635327+DrIOSX@users.noreply.github.com>
Date: Sat, 8 Jun 2024 17:41:09 -0500
Subject: [PATCH 06/13] fix: Update supports should process for
connection/disconect
---
source/Public/Invoke-M365SecurityAudit.ps1 | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/source/Public/Invoke-M365SecurityAudit.ps1 b/source/Public/Invoke-M365SecurityAudit.ps1
index 5f3795a..526eab6 100644
--- a/source/Public/Invoke-M365SecurityAudit.ps1
+++ b/source/Public/Invoke-M365SecurityAudit.ps1
@@ -55,7 +55,6 @@
.LINK
https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Invoke-M365SecurityAudit
#>
-
function Invoke-M365SecurityAudit {
[CmdletBinding(SupportsShouldProcess = $true, DefaultParameterSetName = 'Default')]
[OutputType([CISAuditResult[]])]
@@ -64,7 +63,7 @@ function Invoke-M365SecurityAudit {
[ValidatePattern('^https://[a-zA-Z0-9-]+-admin\.sharepoint\.com$')]
[string]$TenantAdminUrl,
- [Parameter(Mandatory = $false, HelpMessage = "All domains tested unless you Specify this to test only the selected domain for password expiration policy when '1.3.1' is included in the tests to be run. The domain name of your organization, e.g., 'example.com'.")]
+ [Parameter(Mandatory = $false, HelpMessage = "Specify this to test only the default domain for password expiration policy when '1.3.1' is included in the tests to be run. The domain name of your organization, e.g., 'example.com'.")]
[ValidatePattern('^[a-zA-Z0-9-]+\.[a-zA-Z]{2,}$')]
[string]$M365DomainForPWPolicyTest,
@@ -157,10 +156,6 @@ function Invoke-M365SecurityAudit {
}
}
}
- # Establishing connections if required
- if (!($DoNotConnect)) {
- Connect-M365Suite -TenantAdminUrl $TenantAdminUrl -RequiredConnections $requiredConnections
- }
# Determine which test files to load based on filtering
$testsToLoad = $testDefinitions.TestFileName | ForEach-Object { $_ -replace '.ps1$', '' }
Write-Verbose "The $(($testsToLoad).count) test/s that would be loaded based on filter criteria:"
@@ -168,6 +163,7 @@ function Invoke-M365SecurityAudit {
# Initialize a collection to hold failed test details
$script:FailedTests = [System.Collections.ArrayList]::new()
} # End Begin
+
Process {
$allAuditResults = [System.Collections.ArrayList]::new() # Initialize a collection to hold all results
# Dynamically dot-source the test scripts
@@ -178,6 +174,11 @@ function Invoke-M365SecurityAudit {
$totalTests = $testFiles.Count
$currentTestIndex = 0
+ # Establishing connections if required
+ if (!($DoNotConnect) -and $PSCmdlet.ShouldProcess("Establish connections to Microsoft 365 services")) {
+ Connect-M365Suite -TenantAdminUrl $TenantAdminUrl -RequiredConnections $requiredConnections
+ }
+
# Import the test functions
$testFiles | ForEach-Object {
$currentTestIndex++
@@ -218,4 +219,3 @@ function Invoke-M365SecurityAudit {
return $allAuditResults.ToArray() | Sort-Object -Property Rec
}
}
-
From 270e980a57028a1c7f62956fa4dde54ad0a15dcb Mon Sep 17 00:00:00 2001
From: DrIOS <58635327+DrIOSX@users.noreply.github.com>
Date: Sat, 8 Jun 2024 17:41:23 -0500
Subject: [PATCH 07/13] docs: Update CHANGELOG
---
CHANGELOG.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3499940..924569f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,7 @@ The format is based on and uses the types of changes according to [Keep a Change
- Updated `Invoke-M365SecurityAudit` to make `TenantAdminUrl` an optional parameter.
- Improved connection handling and error messaging in `Connect-M365Suite`.
- Enhanced `Invoke-M365SecurityAudit` to allow flexible inclusion and exclusion of specific recommendations, IG filters, and profile levels.
+- SupportsShoudProcess to also bypass connection checks in `Invoke-M365SecurityAudit` as well as Disconnect-M365Suite.
## [0.1.5] - 2024-06-08
From f855ef7d0baa252aefb1ba8998983eee230b2bc3 Mon Sep 17 00:00:00 2001
From: DrIOS <58635327+DrIOSX@users.noreply.github.com>
Date: Sat, 8 Jun 2024 17:44:16 -0500
Subject: [PATCH 08/13] fix: Update supports should process for
connection/disconect
---
source/Public/Invoke-M365SecurityAudit.ps1 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/source/Public/Invoke-M365SecurityAudit.ps1 b/source/Public/Invoke-M365SecurityAudit.ps1
index 526eab6..4475e98 100644
--- a/source/Public/Invoke-M365SecurityAudit.ps1
+++ b/source/Public/Invoke-M365SecurityAudit.ps1
@@ -209,7 +209,7 @@ function Invoke-M365SecurityAudit {
}
End {
- if (!($DoNotDisconnect)) {
+ if (!($DoNotDisconnect) -and $PSCmdlet.ShouldProcess("Disconnect from Microsoft 365 services")) {
# Clean up sessions
Disconnect-M365Suite -RequiredConnections $requiredConnections
}
From 702f557579934060c9281078bdd8c543ddc067b6 Mon Sep 17 00:00:00 2001
From: DrIOS <58635327+DrIOSX@users.noreply.github.com>
Date: Sat, 8 Jun 2024 17:45:31 -0500
Subject: [PATCH 09/13] fix: module check included for whatif
---
source/Public/Invoke-M365SecurityAudit.ps1 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/source/Public/Invoke-M365SecurityAudit.ps1 b/source/Public/Invoke-M365SecurityAudit.ps1
index 4475e98..aef7700 100644
--- a/source/Public/Invoke-M365SecurityAudit.ps1
+++ b/source/Public/Invoke-M365SecurityAudit.ps1
@@ -123,7 +123,7 @@ function Invoke-M365SecurityAudit {
$script:MaximumFunctionCount = 8192
}
# Ensure required modules are installed
- if (!($NoModuleCheck)) {
+ if (!($NoModuleCheck) -and $PSCmdlet.ShouldProcess("Check for required modules")) {
$requiredModules = Get-RequiredModule -AuditFunction
foreach ($module in $requiredModules) {
Assert-ModuleAvailability -ModuleName $module.ModuleName -RequiredVersion $module.RequiredVersion -SubModuleName $module.SubModuleName
From afe657ffc0b4d8fcdd20beff8a153973c46e74b9 Mon Sep 17 00:00:00 2001
From: DrIOS <58635327+DrIOSX@users.noreply.github.com>
Date: Sat, 8 Jun 2024 17:48:43 -0500
Subject: [PATCH 10/13] fix: module check included for whatif
---
source/Public/Invoke-M365SecurityAudit.ps1 | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/source/Public/Invoke-M365SecurityAudit.ps1 b/source/Public/Invoke-M365SecurityAudit.ps1
index aef7700..6577644 100644
--- a/source/Public/Invoke-M365SecurityAudit.ps1
+++ b/source/Public/Invoke-M365SecurityAudit.ps1
@@ -213,9 +213,11 @@ function Invoke-M365SecurityAudit {
# Clean up sessions
Disconnect-M365Suite -RequiredConnections $requiredConnections
}
- # Call the private function to calculate and display results
+ if ($PSCmdlet.ShouldProcess("Measure and display audit results")) {
+ # Call the private function to calculate and display results
Measure-AuditResult -AllAuditResults $allAuditResults -FailedTests $script:FailedTests
# Return all collected audit results
return $allAuditResults.ToArray() | Sort-Object -Property Rec
+ }
}
}
From 9dc99636d3a16c9eba8caaba00d5aeee5596630d Mon Sep 17 00:00:00 2001
From: DrIOS <58635327+DrIOSX@users.noreply.github.com>
Date: Sat, 8 Jun 2024 17:57:42 -0500
Subject: [PATCH 11/13] fix: module check included for whatif
---
source/Public/Invoke-M365SecurityAudit.ps1 | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/source/Public/Invoke-M365SecurityAudit.ps1 b/source/Public/Invoke-M365SecurityAudit.ps1
index 6577644..bd4e675 100644
--- a/source/Public/Invoke-M365SecurityAudit.ps1
+++ b/source/Public/Invoke-M365SecurityAudit.ps1
@@ -123,7 +123,7 @@ function Invoke-M365SecurityAudit {
$script:MaximumFunctionCount = 8192
}
# Ensure required modules are installed
- if (!($NoModuleCheck) -and $PSCmdlet.ShouldProcess("Check for required modules")) {
+ if (!($NoModuleCheck) -and $PSCmdlet.ShouldProcess("Check for required modules", "Check")) {
$requiredModules = Get-RequiredModule -AuditFunction
foreach ($module in $requiredModules) {
Assert-ModuleAvailability -ModuleName $module.ModuleName -RequiredVersion $module.RequiredVersion -SubModuleName $module.SubModuleName
@@ -175,7 +175,7 @@ function Invoke-M365SecurityAudit {
$currentTestIndex = 0
# Establishing connections if required
- if (!($DoNotConnect) -and $PSCmdlet.ShouldProcess("Establish connections to Microsoft 365 services")) {
+ if (!($DoNotConnect) -and $PSCmdlet.ShouldProcess("Establish connections to Microsoft 365 services", "Connect")) {
Connect-M365Suite -TenantAdminUrl $TenantAdminUrl -RequiredConnections $requiredConnections
}
@@ -209,15 +209,15 @@ function Invoke-M365SecurityAudit {
}
End {
- if (!($DoNotDisconnect) -and $PSCmdlet.ShouldProcess("Disconnect from Microsoft 365 services")) {
+ if (!($DoNotDisconnect) -and $PSCmdlet.ShouldProcess("Disconnect from Microsoft 365 services", "Disconnect")) {
# Clean up sessions
Disconnect-M365Suite -RequiredConnections $requiredConnections
}
- if ($PSCmdlet.ShouldProcess("Measure and display audit results")) {
- # Call the private function to calculate and display results
- Measure-AuditResult -AllAuditResults $allAuditResults -FailedTests $script:FailedTests
- # Return all collected audit results
- return $allAuditResults.ToArray() | Sort-Object -Property Rec
+ if ($PSCmdlet.ShouldProcess("Measure and display audit results", "Measure")) {
+ # Call the private function to calculate and display results
+ Measure-AuditResult -AllAuditResults $allAuditResults -FailedTests $script:FailedTests
+ # Return all collected audit results
+ return $allAuditResults.ToArray() | Sort-Object -Property Rec
}
}
}
From 03b5bb47e2e0f0a134d11436b7ad3ce38487dbe2 Mon Sep 17 00:00:00 2001
From: DrIOS <58635327+DrIOSX@users.noreply.github.com>
Date: Sat, 8 Jun 2024 18:12:01 -0500
Subject: [PATCH 12/13] docs: Update HelpE
---
README.md | Bin 24766 -> 29808 bytes
docs/index.html | Bin 67100 -> 72076 bytes
source/Public/Invoke-M365SecurityAudit.ps1 | 60 +++++++++++++++++++++
3 files changed, 60 insertions(+)
diff --git a/README.md b/README.md
index c306c67966493af5bd0379e9fdd60538062d3929..f4582578d955466e7a3f3679d84212bce701d59c 100644
GIT binary patch
delta 4153
zcmeHKOHUL*5Uxou5DX%L4XjEstl=R6%r0nfNl+rI5Eprc#RsAzEDtlVWFHz6lhwqd
z34}g-@CTR}=Wg_mm~ivx!ILMysjdb_HtzN)F(?(fqV>-#tB!_R89
zQ$OH!*POekp2Q<+ZP0EmP>$AVlUB*5WlGZuIaDB5y}H%hmZLt*+Ehoia(7cVO+uQd
zEqTV3)zEq0Xv|{X!Oa$V&RlVfZa}h5uFSEu1SR3?DQ-RI*G*8r(Nk|b!u7m9Nzu~W
zNKNPj>&Mmh>GMU6ZU&Z?M8jCpZ(bWk6#C{l_RiWljuL47`Ua^BX<8(#J&G|$#`yh_
zvG(m2${=~YaGs$Jq{W4rgPFW?svC=}qFv63$t)xe^t5rm>le_Qfelxn`6ZRcykd-=
z(__lQ=Q5S2pQRH;2y(d0_f2B71P7b)G|>2arC}sW*Iy`2$er!8jN`|=1QP?j*#gPVkO|F(hJDOL|RJCL6W#iq+n#!i}W0*7jdy9DK9`b
zk2S0xlY)IjxK!Ih>uy7r>KXds)ebgUttMAoqUNS)j
zZMmPugCnjZf0dP|pQS-t{Jux>C}YDiz;7t}SOSOb7cUc7tG_q+p+PaX|PN`=lDX
z+vW8PeLZ%Q47xEmwaT%^4!RM4%KxMr6KX2;TI~$IQH#T;LKRP|o;w`d@7FS(Svq)H
zu}*M5m{8NHa04@x99SfqEFF=p%gjn~N*OE{KaQb6e13&SYcFirVfApX9YR{2DY;gva&W=gAS
z??Fg?Zm&A431P)FBn)ctC&%=u!`9$G4|GfIhih#e_4N-{KDha
z9;yfNDti+|FJ6Trc<>+uyb0o=e}Lb-H8p`$@K7kYEbr}mGjC?To!Q6x-o}!9
z$#OsW>N!g>3Q+|82%UNT{oOLZh=us$+HwA|qWP*+p*)#%pESymK{KRNl?puh#%EOM
zGSnpkUXPYmNUGxtl?(b$Dv^FVZks3A6ag?jx}U$7|86_(p3aC5OqUS07^soPU0=d1z$UI
z@p*%a$U~5_c+cT$3s|K?B0hCUMP4QIAOsbFJ31H$PAkV{EYe|ObOaY557DMzR)DU;
zdjH^MkzAuX-J>$x=cqH0q8*34f~QrK3`SYlo6<|vVM)3H`!J2cgMgI}GLaG+x_G&Y
zm_5A~*i{
zZvS>$+Uf;Y*T^)qt41(JRAE~`T@`sT)X$MYssZ
zM+4UTXE~Q;u0&n>UhaZXXBRlTVE^ud7bv%nZ-vGDC0c$)C}9L6Fm;Sma~!Dfah>;8t2WDR5w
zj9jhH!){htwfMT+PK5s2TvxvV}YkFWxBfa7n&+?RBF?YUe<%D8&Tr9`w(&wF_+)$bax^h>oK>+@#X_yrUF
BajpOW
delta 110
zcmeC#%rd8kWx_pPa|SC0BL+h-X|eJ3{z;q9%=pDP`H6MUWIs=%$>(Mqnk=?p%j6IF
zER$bYJ53gN?gkUzEVYaWq|j~hgC%a0@4RZ6G_z;&w$~1mTUJYLezS&yadV1Y3G-&R
HEpDj*WgIfP
diff --git a/source/Public/Invoke-M365SecurityAudit.ps1 b/source/Public/Invoke-M365SecurityAudit.ps1
index bd4e675..abdaa72 100644
--- a/source/Public/Invoke-M365SecurityAudit.ps1
+++ b/source/Public/Invoke-M365SecurityAudit.ps1
@@ -28,18 +28,77 @@
.PARAMETER NoModuleCheck
If specified, the cmdlet will not check for the presence of required modules.
.EXAMPLE
+ PS> Invoke-M365SecurityAudit
+ Performs a security audit using default parameters.
+ Output:
+ Status : Fail
+ ELevel : E3
+ ProfileLevel: L1
+ Connection : Microsoft Graph
+ Rec : 1.1.1
+ Result : False
+ Details : Non-compliant accounts:
+ Username | Roles | HybridStatus | Missing Licence
+ user1@domain.com| Global Administrator | Cloud-Only | AAD_PREMIUM
+ user2@domain.com| Global Administrator | Hybrid | AAD_PREMIUM, AAD_PREMIUM_P2
+ FailureReason: Non-Compliant Accounts: 2
+ .EXAMPLE
PS> Invoke-M365SecurityAudit -TenantAdminUrl "https://contoso-admin.sharepoint.com" -M365DomainForPWPolicyTest "contoso.com" -ELevel "E5" -ProfileLevel "L1"
Performs a security audit for the E5 level and L1 profile in the specified Microsoft 365 environment.
+ Output:
+ Status : Fail
+ ELevel : E5
+ ProfileLevel: L1
+ Connection : Microsoft Graph
+ Rec : 1.1.1
+ Result : False
+ Details : Non-compliant accounts:
+ Username | Roles | HybridStatus | Missing Licence
+ user1@domain.com| Global Administrator | Cloud-Only | AAD_PREMIUM
+ user2@domain.com| Global Administrator | Hybrid | AAD_PREMIUM, AAD_PREMIUM_P2
+ FailureReason: Non-Compliant Accounts: 2
.EXAMPLE
PS> Invoke-M365SecurityAudit -TenantAdminUrl "https://contoso-admin.sharepoint.com" -M365DomainForPWPolicyTest "contoso.com" -IncludeIG1
Performs an audit including all tests where IG1 is true.
+ Output:
+ Status : Fail
+ ELevel : E3
+ ProfileLevel: L1
+ Connection : Microsoft Graph
+ Rec : 1.1.1
+ Result : False
+ Details : Non-compliant accounts:
+ Username | Roles | HybridStatus | Missing Licence
+ user1@domain.com| Global Administrator | Cloud-Only | AAD_PREMIUM
+ user2@domain.com| Global Administrator | Hybrid | AAD_PREMIUM, AAD_PREMIUM_P2
+ FailureReason: Non-Compliant Accounts: 2
.EXAMPLE
PS> Invoke-M365SecurityAudit -TenantAdminUrl "https://contoso-admin.sharepoint.com" -M365DomainForPWPolicyTest "contoso.com" -SkipRecommendation '1.1.3', '2.1.1'
Performs an audit while excluding specific recommendations 1.1.3 and 2.1.1.
+ Output:
+ Status : Fail
+ ELevel : E3
+ ProfileLevel: L1
+ Connection : Microsoft Graph
+ Rec : 1.1.1
+ Result : False
+ Details : Non-compliant accounts:
+ Username | Roles | HybridStatus | Missing Licence
+ user1@domain.com| Global Administrator | Cloud-Only | AAD_PREMIUM
+ user2@domain.com| Global Administrator | Hybrid | AAD_PREMIUM, AAD_PREMIUM_P2
+ FailureReason: Non-Compliant Accounts: 2
.EXAMPLE
PS> $auditResults = Invoke-M365SecurityAudit -TenantAdminUrl "https://contoso-admin.sharepoint.com" -M365DomainForPWPolicyTest "contoso.com"
PS> $auditResults | Export-Csv -Path "auditResults.csv" -NoTypeInformation
Captures the audit results into a variable and exports them to a CSV file.
+ Output:
+ CISAuditResult[]
+ auditResults.csv
+ .EXAMPLE
+ PS> Invoke-M365SecurityAudit -WhatIf
+ Displays what would happen if the cmdlet is run without actually performing the audit.
+ Output:
+ What if: Performing the operation "Invoke-M365SecurityAudit" on target "Microsoft 365 environment".
.INPUTS
None. You cannot pipe objects to Invoke-M365SecurityAudit.
.OUTPUTS
@@ -55,6 +114,7 @@
.LINK
https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Invoke-M365SecurityAudit
#>
+
function Invoke-M365SecurityAudit {
[CmdletBinding(SupportsShouldProcess = $true, DefaultParameterSetName = 'Default')]
[OutputType([CISAuditResult[]])]
From fbfb5b598630b9f95167fcfe385df52b0350e481 Mon Sep 17 00:00:00 2001
From: DrIOS <58635327+DrIOSX@users.noreply.github.com>
Date: Sat, 8 Jun 2024 19:31:29 -0500
Subject: [PATCH 13/13] add: build help for issues
---
helpers/Build-Help.ps1 | 68 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 68 insertions(+)
diff --git a/helpers/Build-Help.ps1 b/helpers/Build-Help.ps1
index 933f032..3cda1d0 100644
--- a/helpers/Build-Help.ps1
+++ b/helpers/Build-Help.ps1
@@ -14,4 +14,72 @@ Import-Module .\output\module\M365FoundationsCISReport\*\*.psd1
# git tag -d $ver
#>
+# Refresh authentication to ensure the correct scopes
+gh auth refresh -s project,read:project,write:project,repo
+# Create the project
+gh project create --owner CriticalSolutionsNetwork --title "Test Validation Project"
+
+$repoOwner = "CriticalSolutionsNetwork"
+$repoName = "M365FoundationsCISReport"
+$directoryPath = ".\source\tests"
+$projectName = "Test Validation Project"
+
+# Function to create GitHub issues
+function Create-GitHubIssue {
+ param (
+ [string]$title,
+ [string]$body,
+ [string]$project
+ )
+
+ # Create the issue and add it to the specified project
+ $issue = gh issue create --repo "$repoOwner/$repoName" --title "$title" --body "$body" --project "$project"
+ return $issue
+}
+
+# Load test definitions from CSV
+$testDefinitionsPath = ".\source\helper\TestDefinitions.csv"
+$testDefinitions = Import-Csv -Path $testDefinitionsPath
+
+# Iterate over each .ps1 file in the directory
+Get-ChildItem -Path $directoryPath -Filter "*.ps1" | ForEach-Object {
+ $fileName = $_.Name
+ $testDefinition = $testDefinitions | Where-Object { $_.TestFileName -eq $fileName }
+
+ if ($testDefinition) {
+ $rec = $testDefinition.Rec
+ $elevel = $testDefinition.ELevel
+ $profileLevel = $testDefinition.ProfileLevel
+ $ig1 = $testDefinition.IG1
+ $ig2 = $testDefinition.IG2
+ $ig3 = $testDefinition.IG3
+ $connection = $testDefinition.Connection
+
+ $issueTitle = "Rec: $rec - Validate $fileName, ELevel: $elevel, ProfileLevel: $profileLevel, IG1: $ig1, IG2: $ig2, IG3: $ig3, Connection: $connection"
+ $issueBody = @"
+# Validation for $fileName
+
+## Tasks
+- [ ] Validate test for a pass
+ - Description of passing criteria:
+- [ ] Validate test for a fail
+ - Description of failing criteria:
+- [ ] Add notes and observations
+ - Placeholder for additional notes:
+"@
+
+ # Create the issue using GitHub CLI
+ try {
+ Create-GitHubIssue -title "$issueTitle" -body "$issueBody" -project "$projectName"
+ Write-Output "Created issue for $fileName"
+ } catch {
+ Write-Error "Failed to create issue for $fileName : $_"
+ }
+
+ # Introduce a delay of 2 seconds
+ Start-Sleep -Seconds 2
+ } else {
+ Write-Warning "No matching test definition found for $fileName"
+ }
+}