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;!V7MjfF 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" + } +}