From 0ea5aa2581f17c5dc7b6b07c9135e6cd56301073 Mon Sep 17 00:00:00 2001 From: DrIOS <58635327+DrIOSX@users.noreply.github.com> Date: Wed, 26 Jun 2024 16:19:17 -0500 Subject: [PATCH 1/4] docs: Update helper to retrieve keys --- helpers/Build-Help.ps1 | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/helpers/Build-Help.ps1 b/helpers/Build-Help.ps1 index ef68208..ab6e3fe 100644 --- a/helpers/Build-Help.ps1 +++ b/helpers/Build-Help.ps1 @@ -4,7 +4,7 @@ Import-Module .\output\module\M365FoundationsCISReport\*\*.psd1 <# - $ver = "v0.1.14" + $ver = "v0.1.15" git checkout main git pull origin main git tag -a $ver -m "Release version $ver refactor Update" @@ -39,4 +39,26 @@ $parameters = @{ } Update-MarkdownHelpModule @parameters -Force Update-MarkdownHelpModule -Path ".\help" -RefreshModulePage -Force -New-ExternalHelp -Path ".\help" -OutputPath ".\source\en-US" -force \ No newline at end of file +New-ExternalHelp -Path ".\help" -OutputPath ".\source\en-US" -force + + + +# Install Secret Management +Install-Module -Name "Microsoft.PowerShell.SecretManagement", ` +"SecretManagement.JustinGrote.CredMan" -Scope CurrentUser + +# Register Vault +Register-SecretVault -Name ModuleBuildCreds -ModuleName ` +"SecretManagement.JustinGrote.CredMan" -ErrorAction Stop + + +Set-Secret -Name "GalleryApiToken" -Vault ModuleBuildCreds +Set-Secret -Name "GitHubToken" -Vault ModuleBuildCreds + + +$GalleryApiToken = Get-Secret -Name "GalleryApiToken" -Vault ModuleBuildCreds -AsPlainText +$GitHubToken = Get-Secret -Name "GitHubToken" -Vault ModuleBuildCreds -AsPlainText + + +$GalleryApiToken +$GitHubToken From d4632c0a6f2baa0723b5677d39bc3103ed5c46aa Mon Sep 17 00:00:00 2001 From: DrIOS <58635327+DrIOSX@users.noreply.github.com> Date: Wed, 26 Jun 2024 21:30:41 -0500 Subject: [PATCH 2/4] add: Added Grant-M365SecurityAuditConsent function to consent to the Microsoft Graph Powershell API for a user. --- .../Public/Grant-M365SecurityAuditConsent.ps1 | 182 ++++++++++++++++++ .../Grant-M365SecurityAuditConsent.tests.ps1 | 71 +++++++ 2 files changed, 253 insertions(+) create mode 100644 source/Public/Grant-M365SecurityAuditConsent.ps1 create mode 100644 tests/Unit/Public/Grant-M365SecurityAuditConsent.tests.ps1 diff --git a/source/Public/Grant-M365SecurityAuditConsent.ps1 b/source/Public/Grant-M365SecurityAuditConsent.ps1 new file mode 100644 index 0000000..0b13d9c --- /dev/null +++ b/source/Public/Grant-M365SecurityAuditConsent.ps1 @@ -0,0 +1,182 @@ +<# + .SYNOPSIS + Grants Microsoft Graph permissions for an auditor. + .DESCRIPTION + This function grants the specified Microsoft Graph permissions to a user, allowing the user to perform audits. It connects to Microsoft Graph, checks if a service principal exists for the client application, creates it if it does not exist, and then grants the specified permissions. Finally, it assigns the app to the user. + .PARAMETER UserPrincipalNameForConsent + The UPN or ID of the user to grant consent for. + .PARAMETER SkipGraphConnection + If specified, skips connecting to Microsoft Graph. + .PARAMETER DoNotDisconnect + If specified, does not disconnect from Microsoft Graph after granting consent. + .PARAMETER SkipModuleCheck + If specified, skips the check for the Microsoft.Graph module. + .PARAMETER SuppressRevertOutput + If specified, suppresses the output of the revert commands. + .EXAMPLE + Grant-M365SecurityAuditConsent -UserPrincipalNameForConsent user@example.com + + Grants Microsoft Graph permissions to user@example.com for the client application with the specified Application ID. + .EXAMPLE + Grant-M365SecurityAuditConsent -UserPrincipalNameForConsent user@example.com -SkipGraphConnection + + Grants Microsoft Graph permissions to user@example.com, skipping the connection to Microsoft Graph. + .NOTES + This function requires the Microsoft.Graph module version 2.4.0 or higher. + .LINK + https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Grant-M365SecurityAuditConsent +#> +function Grant-M365SecurityAuditConsent { + [CmdletBinding( + SupportsShouldProcess = $true, + ConfirmImpact = 'High' + )] + [OutputType([void])] + param ( + [Parameter( + Mandatory = $true, + Position = 0, + ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true, + HelpMessage = 'Specify the UPN of the user to grant consent for.' + )] + [ValidatePattern('^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$')] + [String]$UserPrincipalNameForConsent, + [Parameter( + Mandatory = $false, + HelpMessage = 'Skip connecting to Microsoft Graph.' + )] + [switch]$SkipGraphConnection, + [Parameter( + Mandatory = $false, + HelpMessage = 'Skip the check for the Microsoft.Graph module.' + )] + [switch]$SkipModuleCheck, + [Parameter( + Mandatory = $false, + HelpMessage = 'Suppress the output of the revert commands.' + )] + [switch]$SuppressRevertOutput, + [Parameter( + Mandatory = $false, + HelpMessage = 'Do not disconnect from Microsoft Graph after granting consent.' + )] + [switch]$DoNotDisconnect + ) + begin { + if (!($SkipModuleCheck)) { + Assert-ModuleAvailability -ModuleName Microsoft.Graph -RequiredVersion "2.4.0" + } + # Adjusted from: https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/grant-consent-single-user?pivots=msgraph-powershell + # Needed: A user account with a Privileged Role Administrator, Application Administrator, or Cloud Application Administrator + # The app for which consent is being granted. + $clientAppId = "14d82eec-204b-4c2f-b7e8-296a70dab67e" # Microsoft Graph PowerShell + # The API to which access will be granted. Microsoft Graph PowerShell makes API + # requests to the Microsoft Graph API, so we'll use that here. + $resourceAppId = "00000003-0000-0000-c000-000000000000" # Microsoft Graph API + # The permissions to grant. + $permissions = @("Directory.Read.All", "Domain.Read.All", "Policy.Read.All", "Organization.Read.All") + # The user on behalf of whom access will be granted. The app will be able to access + # the API on behalf of this user. + $userUpnOrId = $UserPrincipalNameForConsent + } + process { + try { + if (-not $SkipGraphConnection -and $PSCmdlet.ShouldProcess("Scopes: User.ReadBasic.All, Application.ReadWrite.All, DelegatedPermissionGrant.ReadWrite.All, AppRoleAssignment.ReadWrite.All", "Connect-MgGraph")) { + # Step 0. Connect to Microsoft Graph PowerShell. We need User.ReadBasic.All to get + # users' IDs, Application.ReadWrite.All to list and create service principals, + # DelegatedPermissionGrant.ReadWrite.All to create delegated permission grants, + # and AppRoleAssignment.ReadWrite.All to assign an app role. + # WARNING: These are high-privilege permissions! + Write-Host "Connecting to Microsoft Graph with scopes: User.ReadBasic.All, Application.ReadWrite.All, DelegatedPermissionGrant.ReadWrite.All, AppRoleAssignment.ReadWrite.All" -ForegroundColor Yellow + Connect-MgGraph -Scopes ("User.ReadBasic.All Application.ReadWrite.All " + "DelegatedPermissionGrant.ReadWrite.All " + "AppRoleAssignment.ReadWrite.All") -NoWelcome + $context = Get-MgContext + Write-Host "Connected to Microsoft Graph with user: $(($context.Account)) with the authtype `"$($context.AuthType)`" for the `"$($context.Environment)`" environment." -ForegroundColor Green + } + } + catch { + throw "Connection execution aborted: $_" + break + } + try { + if ($PSCmdlet.ShouldProcess("Create Microsoft Graph API service princial if not found", "New-MgServicePrincipal")) { + # Step 1. Check if a service principal exists for the client application. + # If one doesn't exist, create it. + $clientSp = Get-MgServicePrincipal -Filter "appId eq '$($clientAppId)'" -ErrorAction SilentlyContinue + if (-not $clientSp) { + Write-Host "Client service principal not found. Creating one." -ForegroundColor Yellow + $clientSp = New-MgServicePrincipal -AppId $clientAppId + } + $user = Get-MgUser -UserId $userUpnOrId + if (!($user)) { + throw "User with UPN or ID `"$userUpnOrId`" not found." + } + Write-Verbose "User: $($user.UserPrincipalName) Found!" + $resourceSp = Get-MgServicePrincipal -Filter "appId eq '$($resourceAppId)'" + $scopeToGrant = $permissions -join " " + $existingGrant = Get-MgOauth2PermissionGrant -Filter "clientId eq '$($clientSp.Id)' and principalId eq '$($user.Id)' and resourceId eq '$($resourceSp.Id)'" + } + if (-not $existingGrant -and $PSCmdlet.ShouldProcess("User: $userUpnOrId for Microsoft Graph PowerShell Scopes: $($permissions -join ', ')", "New-MgOauth2PermissionGrant: Granting Consent")) { + # Step 2. Create a delegated permission that grants the client app access to the + # API, on behalf of the user. + $grant = New-MgOauth2PermissionGrant -ResourceId $resourceSp.Id -Scope $scopeToGrant -ClientId $clientSp.Id -ConsentType "Principal" -PrincipalId $user.Id + Write-Host "Consent granted to user $($user.UserPrincipalName) for Microsoft Graph API with scopes: $((($grant.Scope) -split ' ') -join ', ')" -ForegroundColor Green + } + if ($existingGrant -and $PSCmdlet.ShouldProcess("Update existing Microsoft Graph permissions for user $userUpnOrId", "Update-MgOauth2PermissionGrant")) { + # Step 2. Update the existing permission grant with the new scopes. + Write-Host "Updating existing permission grant for user $($user.UserPrincipalName)." -ForegroundColor Yellow + $updatedGrant = Update-MgOauth2PermissionGrant -PermissionGrantId $existingGrant.Id -Scope $scopeToGrant -Confirm:$false + Write-Host "Updated permission grant with ID $($updatedGrant.Id) for scopes: $scopeToGrant" -ForegroundColor Green + } + if ($PSCmdlet.ShouldProcess("Assigning app to user $userUpnOrId", "New-MgServicePrincipalAppRoleAssignedTo")) { + # Step 3. Assign the app to the user. This ensures that the user can sign in if assignment + # is required, and ensures that the app shows up under the user's My Apps portal. + if ($clientSp.AppRoles | Where-Object { $_.AllowedMemberTypes -contains "User" }) { + Write-Warning "A default app role assignment cannot be created because the client application exposes user-assignable app roles. You must assign the user a specific app role for the app to be listed in the user's My Apps access panel." + } + else { + # The app role ID 00000000-0000-0000-0000-000000000000 is the default app role + # indicating that the app is assigned to the user, but not for any specific + # app role. + $assignment = New-MgServicePrincipalAppRoleAssignedTo -ServicePrincipalId $clientSp.Id -ResourceId $clientSp.Id -PrincipalId $user.Id -AppRoleId "00000000-0000-0000-0000-000000000000" + # $assignments = Get-MgServicePrincipalAppRoleAssignedTo -ServicePrincipalId $assignment.ResourceId -All -WhatIf + } + } + } + catch { + throw "An error occurred while granting consent:`n$_" + } + finally { + if (!($DoNotDisconnect) -and $PSCmdlet.ShouldProcess("Disconnect from Microsoft Graph", "Disconnect")) { + # Clean up sessions + Write-Host "Disconnecting from Microsoft Graph." -ForegroundColor Yellow + Disconnect-MgGraph | Out-Null + } + } + } + end { + if (-not $SuppressRevertOutput -and $PSCmdlet.ShouldProcess("Instructions to undo this change", "Generate Revert Commands")) { + <# + # Instructions to revert the changes made by this script + $resourceAppId = "00000003-0000-0000-c000-000000000000" + $clientAppId = "14d82eec-204b-4c2f-b7e8-296a70dab67e" + # Get the user object + #$user = Get-MgUser -UserId "user@example.com" + $resourceSp = Get-MgServicePrincipal -Filter "appId eq '$($resourceAppId)'" + # Get the service principal using $clientAppId + $clientSp = Get-MgServicePrincipal -Filter "appId eq '$($clientAppId)'" + $existingGrant = Get-MgOauth2PermissionGrant -Filter "clientId eq '$($clientSp.Id)' and principalId eq '$($user.Id)' and resourceId eq '$($resourceSp.Id)'" + # Get all app role assignments for the service principal + $appRoleAssignments = Get-MgServicePrincipalAppRoleAssignedTo -ServicePrincipalId $clientSp.Id -All + # At index of desired user assignment + Remove-MgServicePrincipalAppRoleAssignedTo -AppRoleAssignmentId $appRoleAssignments[1].Id -ServicePrincipalId $clientSp.Id + Remove-MgOAuth2PermissionGrant -OAuth2PermissionGrantId $existingGrant.Id + #> + Write-Host "App assigned to user $($assignment.PrincipalDisplayName) for $($assignment.ResourceDisplayName) at $($assignment.CreatedDateTime)." -ForegroundColor Green + Write-Host "If you made a mistake and would like to remove the assignement for `"$($user.UserPrincipalName)`", you can run the following:`n" -ForegroundColor Yellow + Write-Host "Connect-MgGraph -Scopes (`"User.ReadBasic.All Application.ReadWrite.All `" + `"DelegatedPermissionGrant.ReadWrite.All `" + `"AppRoleAssignment.ReadWrite.All`")" -ForegroundColor Cyan + Write-Host "Remove-MgServicePrincipalAppRoleAssignedTo -AppRoleAssignmentId `"$($assignment.Id)`" -ServicePrincipalId `"$($assignment.ResourceId)`"" -ForegroundColor Cyan + Write-Host "Remove-MgOAuth2PermissionGrant -OAuth2PermissionGrantId `"$($grant.Id)`"" -ForegroundColor Cyan + } + } +} diff --git a/tests/Unit/Public/Grant-M365SecurityAuditConsent.tests.ps1 b/tests/Unit/Public/Grant-M365SecurityAuditConsent.tests.ps1 new file mode 100644 index 0000000..5998a20 --- /dev/null +++ b/tests/Unit/Public/Grant-M365SecurityAuditConsent.tests.ps1 @@ -0,0 +1,71 @@ +BeforeAll { + $script:moduleName = '<% $PLASTER_PARAM_ModuleName %>' + + # If the module is not found, run the build task 'noop'. + if (-not (Get-Module -Name $script:moduleName -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../build.ps1" -Tasks 'noop' 2>&1 4>&1 5>&1 6>&1 > $null + } + + # Re-import the module using force to get any code changes between runs. + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:moduleName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:moduleName + $PSDefaultParameterValues['Should:ModuleName'] = $script:moduleName +} + +AfterAll { + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') + + Remove-Module -Name $script:moduleName +} + +Describe Get-Something { + + Context 'Return values' { + BeforeEach { + $return = Get-Something -Data 'value' + } + + It 'Returns a single object' { + ($return | Measure-Object).Count | Should -Be 1 + } + + } + + Context 'Pipeline' { + It 'Accepts values from the pipeline by value' { + $return = 'value1', 'value2' | Get-Something + + $return[0] | Should -Be 'value1' + $return[1] | Should -Be 'value2' + } + + It 'Accepts value from the pipeline by property name' { + $return = 'value1', 'value2' | ForEach-Object { + [PSCustomObject]@{ + Data = $_ + OtherProperty = 'other' + } + } | Get-Something + + + $return[0] | Should -Be 'value1' + $return[1] | Should -Be 'value2' + } + } + + Context 'ShouldProcess' { + It 'Supports WhatIf' { + (Get-Command Get-Something).Parameters.ContainsKey('WhatIf') | Should -Be $true + { Get-Something -Data 'value' -WhatIf } | Should -Not -Throw + } + + + } +} + From 0465c3a41d6b6996874fefb212603006baff2abe Mon Sep 17 00:00:00 2001 From: DrIOS <58635327+DrIOSX@users.noreply.github.com> Date: Wed, 26 Jun 2024 21:31:05 -0500 Subject: [PATCH 3/4] docs: Update CHANGELOG --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index aaa5b22..87f5b60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ The format is based on and uses the types of changes according to [Keep a Change ## [Unreleased] +### Added + +- Added `Grant-M365SecurityAuditConsent` function to consent to the Microsoft Graph Powershell API for a user. + +## [0.1.15] - 2024-06-26 + ### Fixed - Fixed test 8.6.1 to include all of the following properties in it's checks and output: `ReportJunkToCustomizedAddress`, `ReportNotJunkToCustomizedAddress`, `ReportPhishToCustomizedAddress`,`ReportJunkAddresses`,`ReportNotJunkAddresses`,`ReportPhishAddresses`,`ReportChatMessageEnabled`,`ReportChatMessageToCustomizedAddressEnabled` From 05a6d76fb7ddd82053df4494a29ced53c98bf5bc Mon Sep 17 00:00:00 2001 From: DrIOS <58635327+DrIOSX@users.noreply.github.com> Date: Wed, 26 Jun 2024 21:36:55 -0500 Subject: [PATCH 4/4] docs: Update HELP docs --- README.md | Bin 37784 -> 20489 bytes docs/index.html | Bin 99072 -> 54847 bytes help/Export-M365SecurityAuditTable.md | 52 +- help/Get-AdminRoleUserLicense.md | 32 +- help/Get-MFAStatus.md | 24 +- help/Grant-M365SecurityAuditConsent.md | 179 ++ help/Invoke-M365SecurityAudit.md | 156 +- help/Remove-RowsWithEmptyCSVStatus.md | 32 +- help/Sync-CISExcelAndCsvData.md | 40 +- help/about_M365FoundationsCISReport.md | 3 + .../en-US/M365FoundationsCISReport-help.xml | 1542 ++++++++++------- .../about_M365FoundationsCISReport.help.txt | 3 + 12 files changed, 1246 insertions(+), 817 deletions(-) create mode 100644 help/Grant-M365SecurityAuditConsent.md diff --git a/README.md b/README.md index daa40ca610e4ed6a3a624526661373f91bda7817..8e92751f4322abc42d5ca8d5b02a76243719e285 100644 GIT binary patch literal 20489 zcmeHPYj4{~vi+`K(NGrfCa~nOoy-Ep+}YLGPS${(2(~k`7k02ilP!xk6v@knZ7uTS z_nhkHOCn`CQFel0=K)I;*-&(l?Wrq1?%eDylYL(j?lC`=DeF3xovC7C*lygbmo z-m_=w)OU55;`8OyPt`cO*U80H2Z5T&Jqj0ZoK$-%3Ka%WH#&5uGbj0&Dkt>#v*)K- z;@{*MZo*tTQQ1_h!$f1&JA8;{Gfb{VnYjy;4Bkc|FYCnhonUY=brL-a{Eu3_9R8qA z!b~Tjkn98neM2Sm&9oDy2ff}vy?B8^25vdZix&s#f1_N@oVg04Oy#K-I%W<=!z^kN zC91kz#d#7(sZNJ7Rz(8GIhm+AhD!9zf7n)8f;sW@Y+GT7o7@ku&KT_AGK=B2<%wCI zW;K5B8Yd0Qm8UfhrOr&Nz_4FAsSFn-{;eN6fuX9#GLkil<0Oi)m`p1-(Vm|vneaxd zTW~tuR`~tS_q1{_Zun7Ukqm0**ftv$dcMmM{E2d>PI#+Rg+1p=JU#67USo}u9Q$8T z=IPAwgA{`Y8iJti{1g*kZFqk_{CS#XaeA<`gO!QkaIYXY!zj7kv9zQ+H}gU04pL_a zg0kaj?G1JK98_PO>syE+WRKfS!Stg0Fo+yag!Y$GXsdbd@9&4MpK3Qx{A@1M;On50 z@8_Z)#}Cw)0afY3-aE>{`b*~q8uSbrbTJR3IQ7$>xiuBFQ^ml_;oXp>G!HUta)iw} zy!cg3{6JHlqCAUp{NSiG)~-MCU6pA_k$He};e;x>`9JMu!(zJ3dFcKA`|mN8HKnrl z?A#q>s;hy}d~S&NpnifT*REWB_!+mn6G|>I`P+PUqZ8bA0l^J#@#9Za*C-r234|7G zPJjNekvR>^MnS-7(+_H3E{vUQTASToeP@-!-g{*)Uq;6dt`0tYCY6Wj9jB|WcJr)g zo8&*Rb_j{cOto*lPwFl0j{2lvaUos!aHLZ=@niZ3d^^|wpZl;bf5qpqA8S|=4Vw%h zm0KqcY6mf5LrSZ)Wiv3mpEuStL1lN!b_Ozn1a>RL7L~!n`BX8mSz)04n>(b zsZsT&N|Temr|!s4s5R3!y3gwlB}xmdB^9+xJk3K@tvB#CCt9U@h|UX9Ydr&4MbQuq?p zLAkk098CZ4;5yT@xDUF`WzmCTE0<|30xIjN5%1ETEK$DyRLZTjQUyWRV(Ba$S>!qM z-JzS_^*6+Kgda;ZzkDjqi`-s+4Nu$w21_=OeT46?zH|*WACy+I-bQZ`s5Fezmx&Q% zFM^|kWrks{8#3xmy0l?Ge(7SrY{Q<)fX-c9YuU7Tr^sm19xdfnl`8ldl9?clf?P7( zP-pj1@^N?zCgwLoKicU^fp?ynZSAmoRhodv=qt_f9EM!I(b-_+&HV5@3iSI_C#NNsVahQyo#M^OQ=#Eo{vG*1XfdMS)ojbdpxlRJ|>q49TAj7RWrokK0LdE@CPPrWcn_NFKtJSHq141LgyAk z=?4K;f?&RWR05Di4+U6poshUnjFg}Z(6R6?;XqQp5T`VQ6yzCMo&Xnelq<1IJ!a4j zI3l7h=Fn*hwvl-5jPgS_$UVqES3QY>Ai5_9iIeCg^L2Wls8~#Sw$*#+PW5Swc*^x- zC#Wu+c-!jl^P9x?c&ountUdxKlJ&feGTk%S2ePFj04WDb?ftO#a`3~;!R{+HHn7sp zp+GBul0ujdqEC4!+MztCaS+8b9cGl9G>;7;*HF)v1)FFIi?f8R729=fj(8IhMQuVv zzzv0kVJgrzKeq$B)o@aN%@*CvOR;0VwyYAl2sby%(zjX~?y0){| zql?VR@>Gx{f24RMwD8nBo>N?9a9Io#63k&gE$1_D7es>kC23?HzFE9(?w1=a&4dekf$S}s84lHmQk<| z%O+t#idHNA&1gVakc0 z%_Mw6Ydhmp||rzsv>i-&ViO$0o8CLq{*tK;0k9ui!&U%_&kT%S;

9{4hm-@X9F-8?C8t#1& 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 KdB^C_d;bP8W0hL~ literal 37784 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¬AfIa8*Ct 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 diff --git a/docs/index.html b/docs/index.html index e8a93e49c5f35c9bcea9e054710dfebb12e2fb08..27236b2e47a28c7ddde385fa1c5402281f910ef2 100644 GIT binary patch literal 54847 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 UW4ZVPmx7ENMSej#fRXC|0dan-A^-pY literal 99072 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 diff --git a/help/Export-M365SecurityAuditTable.md b/help/Export-M365SecurityAuditTable.md index 6afe3bf..a2a7ba0 100644 --- a/help/Export-M365SecurityAuditTable.md +++ b/help/Export-M365SecurityAuditTable.md @@ -1,4 +1,4 @@ ---- +--- external help file: M365FoundationsCISReport-help.xml Module Name: M365FoundationsCISReport online version: https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Export-M365SecurityAuditTable @@ -110,22 +110,6 @@ Accept pipeline input: False Accept wildcard characters: False ``` -### -OutputTestNumber -The test number to output as an object. -Valid values are "1.1.1", "1.3.1", "6.1.2", "6.1.3", "7.3.4". - -```yaml -Type: String -Parameter Sets: OutputObjectFromAuditResultsSingle, OutputObjectFromCsvSingle -Aliases: - -Required: True -Position: 2 -Default value: None -Accept pipeline input: False -Accept wildcard characters: False -``` - ### -ExportAllTests Switch to export all test results. @@ -141,6 +125,21 @@ Accept pipeline input: False Accept wildcard characters: False ``` +### -ExportOriginalTests +Switch to export the original audit results to a CSV file. + +```yaml +Type: SwitchParameter +Parameter Sets: ExportAllResultsFromAuditResults, ExportAllResultsFromCsv +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + ### -ExportPath The path where the CSV files will be exported. @@ -156,8 +155,8 @@ Accept pipeline input: False Accept wildcard characters: False ``` -### -ExportOriginalTests -Switch to export the original audit results to a CSV file. +### -ExportToExcel +Switch to export the results to an Excel file. ```yaml Type: SwitchParameter @@ -171,17 +170,18 @@ Accept pipeline input: False Accept wildcard characters: False ``` -### -ExportToExcel -Switch to export the results to an Excel file. +### -OutputTestNumber +The test number to output as an object. +Valid values are "1.1.1", "1.3.1", "6.1.2", "6.1.3", "7.3.4". ```yaml -Type: SwitchParameter -Parameter Sets: ExportAllResultsFromAuditResults, ExportAllResultsFromCsv +Type: String +Parameter Sets: OutputObjectFromAuditResultsSingle, OutputObjectFromCsvSingle Aliases: -Required: False -Position: Named -Default value: False +Required: True +Position: 2 +Default value: None Accept pipeline input: False Accept wildcard characters: False ``` diff --git a/help/Get-AdminRoleUserLicense.md b/help/Get-AdminRoleUserLicense.md index 629903e..22625bb 100644 --- a/help/Get-AdminRoleUserLicense.md +++ b/help/Get-AdminRoleUserLicense.md @@ -1,4 +1,4 @@ ---- +--- external help file: M365FoundationsCISReport-help.xml Module Name: M365FoundationsCISReport online version: https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Get-AdminRoleUserLicense @@ -38,6 +38,21 @@ This example retrieves all administrative role users along with their licenses w ## PARAMETERS +### -ProgressAction +{{ Fill ProgressAction Description }} + +```yaml +Type: ActionPreference +Parameter Sets: (All) +Aliases: proga + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### -SkipGraphConnection A switch parameter that, when set, skips the connection to Microsoft Graph if already established. This is useful for batch processing or when used within scripts where multiple calls are made and the connection is managed externally. @@ -54,21 +69,6 @@ Accept pipeline input: False Accept wildcard characters: False ``` -### -ProgressAction -{{ Fill ProgressAction Description }} - -```yaml -Type: ActionPreference -Parameter Sets: (All) -Aliases: proga - -Required: False -Position: Named -Default value: None -Accept pipeline input: False -Accept wildcard characters: False -``` - ### CommonParameters This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). diff --git a/help/Get-MFAStatus.md b/help/Get-MFAStatus.md index e5accc3..9e9b878 100644 --- a/help/Get-MFAStatus.md +++ b/help/Get-MFAStatus.md @@ -1,4 +1,4 @@ ---- +--- external help file: M365FoundationsCISReport-help.xml Module Name: M365FoundationsCISReport online version: https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Get-MFAStatus @@ -37,17 +37,16 @@ Retrieves the MFA status for the specified user with the UPN "example@domain.com ## PARAMETERS -### -UserId -The User Principal Name (UPN) of a specific user to retrieve MFA status for. -If not provided, the function retrieves MFA status for all users. +### -ProgressAction +{{ Fill ProgressAction Description }} ```yaml -Type: String +Type: ActionPreference Parameter Sets: (All) -Aliases: +Aliases: proga Required: False -Position: 1 +Position: Named Default value: None Accept pipeline input: False Accept wildcard characters: False @@ -68,16 +67,17 @@ Accept pipeline input: False Accept wildcard characters: False ``` -### -ProgressAction -{{ Fill ProgressAction Description }} +### -UserId +The User Principal Name (UPN) of a specific user to retrieve MFA status for. +If not provided, the function retrieves MFA status for all users. ```yaml -Type: ActionPreference +Type: String Parameter Sets: (All) -Aliases: proga +Aliases: Required: False -Position: Named +Position: 1 Default value: None Accept pipeline input: False Accept wildcard characters: False diff --git a/help/Grant-M365SecurityAuditConsent.md b/help/Grant-M365SecurityAuditConsent.md new file mode 100644 index 0000000..e2c864c --- /dev/null +++ b/help/Grant-M365SecurityAuditConsent.md @@ -0,0 +1,179 @@ +--- +external help file: M365FoundationsCISReport-help.xml +Module Name: M365FoundationsCISReport +online version: https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Grant-M365SecurityAuditConsent +schema: 2.0.0 +--- + +# Grant-M365SecurityAuditConsent + +## SYNOPSIS +Grants Microsoft Graph permissions for an auditor. + +## SYNTAX + +``` +Grant-M365SecurityAuditConsent [-UserPrincipalNameForConsent] [-SkipGraphConnection] + [-SkipModuleCheck] [-SuppressRevertOutput] [-DoNotDisconnect] [-ProgressAction ] [-WhatIf] + [-Confirm] [] +``` + +## DESCRIPTION +This function grants the specified Microsoft Graph permissions to a user, allowing the user to perform audits. +It connects to Microsoft Graph, checks if a service principal exists for the client application, creates it if it does not exist, and then grants the specified permissions. +Finally, it assigns the app to the user. + +## EXAMPLES + +### EXAMPLE 1 +``` +Grant-M365SecurityAuditConsent -UserPrincipalNameForConsent user@example.com +``` + +Grants Microsoft Graph permissions to user@example.com for the client application with the specified Application ID. + +### EXAMPLE 2 +``` +Grant-M365SecurityAuditConsent -UserPrincipalNameForConsent user@example.com -SkipGraphConnection +``` + +Grants Microsoft Graph permissions to user@example.com, skipping the connection to Microsoft Graph. + +## PARAMETERS + +### -DoNotDisconnect +If specified, does not disconnect from Microsoft Graph after granting consent. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ProgressAction +{{ Fill ProgressAction Description }} + +```yaml +Type: ActionPreference +Parameter Sets: (All) +Aliases: proga + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -SkipGraphConnection +If specified, skips connecting to Microsoft Graph. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -SkipModuleCheck +If specified, skips the check for the Microsoft.Graph module. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -SuppressRevertOutput +If specified, suppresses the output of the revert commands. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -UserPrincipalNameForConsent +Specify the UPN of the user to grant consent for. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: True (ByPropertyName, ByValue) +Accept wildcard characters: False +``` + +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WhatIf +Shows what would happen if the cmdlet runs. +The cmdlet is not run. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### System.Void +## NOTES +This function requires the Microsoft.Graph module version 2.4.0 or higher. + +## RELATED LINKS + +[https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Grant-M365SecurityAuditConsent](https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Grant-M365SecurityAuditConsent) + diff --git a/help/Invoke-M365SecurityAudit.md b/help/Invoke-M365SecurityAudit.md index 1ee9ffc..706ab6f 100644 --- a/help/Invoke-M365SecurityAudit.md +++ b/help/Invoke-M365SecurityAudit.md @@ -1,4 +1,4 @@ ---- +--- external help file: M365FoundationsCISReport-help.xml Module Name: M365FoundationsCISReport online version: https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Invoke-M365SecurityAudit @@ -164,34 +164,47 @@ What if: Performing the operation "Invoke-M365SecurityAudit" on target "Microsof ## PARAMETERS -### -TenantAdminUrl -The URL of the tenant admin. -If not specified, none of the SharePoint Online tests will run. +### -DoNotConfirmConnections +If specified, the cmdlet will not prompt for confirmation before proceeding with established connections and will disconnect from all of them. ```yaml -Type: String +Type: SwitchParameter Parameter Sets: (All) Aliases: Required: False Position: Named -Default value: None +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -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. +### -DoNotConnect +If specified, the cmdlet will not establish a connection to Microsoft 365 services. ```yaml -Type: String +Type: SwitchParameter Parameter Sets: (All) Aliases: Required: False Position: Named -Default value: None +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -DoNotDisconnect +If specified, the cmdlet will not disconnect from Microsoft 365 services after execution. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` @@ -212,22 +225,6 @@ Accept pipeline input: False Accept wildcard characters: False ``` -### -ProfileLevel -Specifies the profile level (L1 or L2) for the audit. -This parameter is optional and can be combined with the ELevel parameter. - -```yaml -Type: String -Parameter Sets: ELevelFilter -Aliases: - -Required: True -Position: Named -Default value: None -Accept pipeline input: False -Accept wildcard characters: False -``` - ### -IncludeIG1 If specified, includes tests where IG1 is true. @@ -289,52 +286,22 @@ Accept pipeline input: False Accept wildcard characters: False ``` -### -SkipRecommendation -Specifies specific recommendations to exclude from the audit. -Accepts an array of recommendation numbers. +### -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. ```yaml -Type: String[] -Parameter Sets: SkipRecFilter +Type: String +Parameter Sets: (All) Aliases: -Required: True +Required: False Position: Named Default value: None Accept pipeline input: False Accept wildcard characters: False ``` -### -DoNotConnect -If specified, the cmdlet will not establish a connection to Microsoft 365 services. - -```yaml -Type: SwitchParameter -Parameter Sets: (All) -Aliases: - -Required: False -Position: Named -Default value: False -Accept pipeline input: False -Accept wildcard characters: False -``` - -### -DoNotDisconnect -If specified, the cmdlet will not disconnect from Microsoft 365 services after execution. - -```yaml -Type: SwitchParameter -Parameter Sets: (All) -Aliases: - -Required: False -Position: Named -Default value: False -Accept pipeline input: False -Accept wildcard characters: False -``` - ### -NoModuleCheck If specified, the cmdlet will not check for the presence of required modules. @@ -350,29 +317,61 @@ Accept pipeline input: False Accept wildcard characters: False ``` -### -DoNotConfirmConnections -If specified, the cmdlet will not prompt for confirmation before proceeding with established connections and will disconnect from all of them. +### -ProfileLevel +Specifies the profile level (L1 or L2) for the audit. +This parameter is optional and can be combined with the ELevel parameter. ```yaml -Type: SwitchParameter -Parameter Sets: (All) +Type: String +Parameter Sets: ELevelFilter Aliases: -Required: False +Required: True Position: Named -Default value: False +Default value: None Accept pipeline input: False Accept wildcard characters: False ``` -### -WhatIf -Shows what would happen if the cmdlet runs. -The cmdlet is not run. +### -ProgressAction +{{ Fill ProgressAction Description }} ```yaml -Type: SwitchParameter +Type: ActionPreference Parameter Sets: (All) -Aliases: wi +Aliases: proga + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -SkipRecommendation +Specifies specific recommendations to exclude from the audit. +Accepts an array of recommendation numbers. + +```yaml +Type: String[] +Parameter Sets: SkipRecFilter +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -TenantAdminUrl +The URL of the tenant admin. +If not specified, none of the SharePoint Online tests will run. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: Required: False Position: Named @@ -396,13 +395,14 @@ Accept pipeline input: False Accept wildcard characters: False ``` -### -ProgressAction -{{ Fill ProgressAction Description }} +### -WhatIf +Shows what would happen if the cmdlet runs. +The cmdlet is not run. ```yaml -Type: ActionPreference +Type: SwitchParameter Parameter Sets: (All) -Aliases: proga +Aliases: wi Required: False Position: Named diff --git a/help/Remove-RowsWithEmptyCSVStatus.md b/help/Remove-RowsWithEmptyCSVStatus.md index 8582a86..eca797b 100644 --- a/help/Remove-RowsWithEmptyCSVStatus.md +++ b/help/Remove-RowsWithEmptyCSVStatus.md @@ -1,4 +1,4 @@ ---- +--- external help file: M365FoundationsCISReport-help.xml Module Name: M365FoundationsCISReport online version: @@ -46,21 +46,6 @@ Accept pipeline input: False Accept wildcard characters: False ``` -### -WorksheetName -The name of the worksheet within the Excel file to be processed. - -```yaml -Type: String -Parameter Sets: (All) -Aliases: - -Required: True -Position: 2 -Default value: None -Accept pipeline input: False -Accept wildcard characters: False -``` - ### -ProgressAction {{ Fill ProgressAction Description }} @@ -76,6 +61,21 @@ Accept pipeline input: False Accept wildcard characters: False ``` +### -WorksheetName +The name of the worksheet within the Excel file to be processed. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: True +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### CommonParameters This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). diff --git a/help/Sync-CISExcelAndCsvData.md b/help/Sync-CISExcelAndCsvData.md index e412199..663e3e4 100644 --- a/help/Sync-CISExcelAndCsvData.md +++ b/help/Sync-CISExcelAndCsvData.md @@ -1,4 +1,4 @@ ---- +--- external help file: M365FoundationsCISReport-help.xml Module Name: M365FoundationsCISReport online version: https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Sync-CISExcelAndCsvData @@ -32,22 +32,6 @@ Updates the 'AuditData' worksheet in 'excel.xlsx' with data from 'data.csv', add ## PARAMETERS -### -ExcelPath -Specifies the path to the Excel file to be updated. -This parameter is mandatory. - -```yaml -Type: String -Parameter Sets: (All) -Aliases: - -Required: False -Position: 1 -Default value: None -Accept pipeline input: False -Accept wildcard characters: False -``` - ### -CsvPath Specifies the path to the CSV file containing new data. This parameter is mandatory. @@ -64,8 +48,8 @@ Accept pipeline input: False Accept wildcard characters: False ``` -### -SheetName -Specifies the name of the worksheet in the Excel file where data will be merged and updated. +### -ExcelPath +Specifies the path to the Excel file to be updated. This parameter is mandatory. ```yaml @@ -74,7 +58,7 @@ Parameter Sets: (All) Aliases: Required: False -Position: 3 +Position: 1 Default value: None Accept pipeline input: False Accept wildcard characters: False @@ -95,6 +79,22 @@ Accept pipeline input: False Accept wildcard characters: False ``` +### -SheetName +Specifies the name of the worksheet in the Excel file where data will be merged and updated. +This parameter is mandatory. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 3 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### CommonParameters This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). diff --git a/help/about_M365FoundationsCISReport.md b/help/about_M365FoundationsCISReport.md index 6a2e671..709b089 100644 --- a/help/about_M365FoundationsCISReport.md +++ b/help/about_M365FoundationsCISReport.md @@ -33,6 +33,9 @@ Remove-RowsWithEmptyCSVStatus -FilePath "C:\Reports\Report.xlsx" -WorksheetName # Example 6: Synchronizing CIS benchmark data with audit results Sync-CISExcelAndCsvData -ExcelPath "path\to\excel.xlsx" -CsvPath "path\to\data.csv" -SheetName "Combined Profiles" + +# Example 7: Granting Microsoft Graph permissions to the auditor +Grant-M365SecurityAuditConsent -UserPrincipalNameForConsent 'user@example.com' ``` # NOTE diff --git a/source/en-US/M365FoundationsCISReport-help.xml b/source/en-US/M365FoundationsCISReport-help.xml index 9b00f7e..4ea02c5 100644 --- a/source/en-US/M365FoundationsCISReport-help.xml +++ b/source/en-US/M365FoundationsCISReport-help.xml @@ -77,6 +77,17 @@ None + + ExportOriginalTests + + Switch to export the original audit results to a CSV file. + + + SwitchParameter + + + False + ExportPath @@ -89,17 +100,6 @@ None - - ExportOriginalTests - - Switch to export the original audit results to a CSV file. - - - SwitchParameter - - - False - ExportToExcel @@ -188,6 +188,17 @@ None + + ExportOriginalTests + + Switch to export the original audit results to a CSV file. + + + SwitchParameter + + + False + ExportPath @@ -200,17 +211,6 @@ None - - ExportOriginalTests - - Switch to export the original audit results to a CSV file. - - - SwitchParameter - - - False - ExportToExcel @@ -261,18 +261,6 @@ None - - OutputTestNumber - - The test number to output as an object. Valid values are "1.1.1", "1.3.1", "6.1.2", "6.1.3", "7.3.4". - - String - - String - - - None - ExportAllTests @@ -285,6 +273,18 @@ False + + ExportOriginalTests + + Switch to export the original audit results to a CSV file. + + SwitchParameter + + SwitchParameter + + + False + ExportPath @@ -297,18 +297,6 @@ None - - ExportOriginalTests - - Switch to export the original audit results to a CSV file. - - SwitchParameter - - SwitchParameter - - - False - ExportToExcel @@ -321,6 +309,18 @@ False + + OutputTestNumber + + The test number to output as an object. Valid values are "1.1.1", "1.3.1", "6.1.2", "6.1.3", "7.3.4". + + String + + String + + + None + ProgressAction @@ -431,17 +431,6 @@ Get-AdminRoleUserLicense - - SkipGraphConnection - - A switch parameter that, when set, skips the connection to Microsoft Graph if already established. This is useful for batch processing or when used within scripts where multiple calls are made and the connection is managed externally. - - - SwitchParameter - - - False - ProgressAction @@ -454,21 +443,20 @@ None + + SkipGraphConnection + + A switch parameter that, when set, skips the connection to Microsoft Graph if already established. This is useful for batch processing or when used within scripts where multiple calls are made and the connection is managed externally. + + + SwitchParameter + + + False + - - SkipGraphConnection - - A switch parameter that, when set, skips the connection to Microsoft Graph if already established. This is useful for batch processing or when used within scripts where multiple calls are made and the connection is managed externally. - - SwitchParameter - - SwitchParameter - - - False - ProgressAction @@ -481,6 +469,18 @@ None + + SkipGraphConnection + + A switch parameter that, when set, skips the connection to Microsoft Graph if already established. This is useful for batch processing or when used within scripts where multiple calls are made and the connection is managed externally. + + SwitchParameter + + SwitchParameter + + + False + @@ -565,17 +565,6 @@ None - - SkipMSOLConnectionChecks - - {{ Fill SkipMSOLConnectionChecks Description }} - - - SwitchParameter - - - False - ProgressAction @@ -588,17 +577,28 @@ None + + SkipMSOLConnectionChecks + + {{ Fill SkipMSOLConnectionChecks Description }} + + + SwitchParameter + + + False + - - UserId + + ProgressAction - The User Principal Name (UPN) of a specific user to retrieve MFA status for. If not provided, the function retrieves MFA status for all users. + {{ Fill ProgressAction Description }} - String + ActionPreference - String + ActionPreference None @@ -615,14 +615,14 @@ False - - ProgressAction + + UserId - {{ Fill ProgressAction Description }} + The User Principal Name (UPN) of a specific user to retrieve MFA status for. If not provided, the function retrieves MFA status for all users. - ActionPreference + String - ActionPreference + String None @@ -733,6 +733,250 @@ Retrieves the MFA status for the specified user with the UPN "example@domain.com + + + Grant-M365SecurityAuditConsent + Grant + M365SecurityAuditConsent + + Grants Microsoft Graph permissions for an auditor. + + + + This function grants the specified Microsoft Graph permissions to a user, allowing the user to perform audits. It connects to Microsoft Graph, checks if a service principal exists for the client application, creates it if it does not exist, and then grants the specified permissions. Finally, it assigns the app to the user. + + + + Grant-M365SecurityAuditConsent + + UserPrincipalNameForConsent + + Specify the UPN of the user to grant consent for. + + String + + String + + + None + + + DoNotDisconnect + + If specified, does not disconnect from Microsoft Graph after granting consent. + + + SwitchParameter + + + False + + + ProgressAction + + {{ Fill ProgressAction Description }} + + ActionPreference + + ActionPreference + + + None + + + SkipGraphConnection + + If specified, skips connecting to Microsoft Graph. + + + SwitchParameter + + + False + + + SkipModuleCheck + + If specified, skips the check for the Microsoft.Graph module. + + + SwitchParameter + + + False + + + SuppressRevertOutput + + If specified, suppresses the output of the revert commands. + + + SwitchParameter + + + False + + + Confirm + + Prompts you for confirmation before running the cmdlet. + + + SwitchParameter + + + False + + + WhatIf + + Shows what would happen if the cmdlet runs. The cmdlet is not run. + + + SwitchParameter + + + False + + + + + + DoNotDisconnect + + If specified, does not disconnect from Microsoft Graph after granting consent. + + SwitchParameter + + SwitchParameter + + + False + + + ProgressAction + + {{ Fill ProgressAction Description }} + + ActionPreference + + ActionPreference + + + None + + + SkipGraphConnection + + If specified, skips connecting to Microsoft Graph. + + SwitchParameter + + SwitchParameter + + + False + + + SkipModuleCheck + + If specified, skips the check for the Microsoft.Graph module. + + SwitchParameter + + SwitchParameter + + + False + + + SuppressRevertOutput + + If specified, suppresses the output of the revert commands. + + SwitchParameter + + SwitchParameter + + + False + + + UserPrincipalNameForConsent + + Specify the UPN of the user to grant consent for. + + String + + String + + + None + + + Confirm + + Prompts you for confirmation before running the cmdlet. + + SwitchParameter + + SwitchParameter + + + False + + + WhatIf + + Shows what would happen if the cmdlet runs. The cmdlet is not run. + + SwitchParameter + + SwitchParameter + + + False + + + + + + + System.Void + + + + + + + + + This function requires the Microsoft.Graph module version 2.4.0 or higher. + + + + + -------------------------- EXAMPLE 1 -------------------------- + Grant-M365SecurityAuditConsent -UserPrincipalNameForConsent user@example.com + + Grants Microsoft Graph permissions to user@example.com for the client application with the specified Application ID. + + + + -------------------------- EXAMPLE 2 -------------------------- + Grant-M365SecurityAuditConsent -UserPrincipalNameForConsent user@example.com -SkipGraphConnection + + Grants Microsoft Graph permissions to user@example.com, skipping the connection to Microsoft Graph. + + + + + + https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Grant-M365SecurityAuditConsent + https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Grant-M365SecurityAuditConsent + + + Invoke-M365SecurityAudit @@ -749,28 +993,37 @@ Retrieves the MFA status for the specified user with the UPN "example@domain.com Invoke-M365SecurityAudit - TenantAdminUrl + DoNotConfirmConnections - The URL of the tenant admin. If not specified, none of the SharePoint Online tests will run. + If specified, the cmdlet will not prompt for confirmation before proceeding with established connections and will disconnect from all of them. - String - String + SwitchParameter - None + False - M365DomainForPWPolicyTest + DoNotConnect - 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. + If specified, the cmdlet will not establish a connection to Microsoft 365 services. - String - String + SwitchParameter - None + False + + + DoNotDisconnect + + If specified, the cmdlet will not disconnect from Microsoft 365 services after execution. + + + SwitchParameter + + + False ELevel @@ -784,6 +1037,29 @@ Retrieves the MFA status for the specified user with the UPN "example@domain.com None + + 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. + + String + + String + + + None + + + NoModuleCheck + + If specified, the cmdlet will not check for the presence of required modules. + + + SwitchParameter + + + False + ProfileLevel @@ -796,6 +1072,66 @@ Retrieves the MFA status for the specified user with the UPN "example@domain.com None + + ProgressAction + + {{ Fill ProgressAction Description }} + + ActionPreference + + ActionPreference + + + None + + + TenantAdminUrl + + The URL of the tenant admin. If not specified, none of the SharePoint Online tests will run. + + String + + String + + + None + + + Confirm + + Prompts you for confirmation before running the cmdlet. + + + SwitchParameter + + + False + + + WhatIf + + Shows what would happen if the cmdlet runs. The cmdlet is not run. + + + SwitchParameter + + + False + + + + Invoke-M365SecurityAudit + + DoNotConfirmConnections + + If specified, the cmdlet will not prompt for confirmation before proceeding with established connections and will disconnect from all of them. + + + SwitchParameter + + + False + DoNotConnect @@ -818,89 +1154,6 @@ Retrieves the MFA status for the specified user with the UPN "example@domain.com False - - NoModuleCheck - - If specified, the cmdlet will not check for the presence of required modules. - - - SwitchParameter - - - False - - - DoNotConfirmConnections - - If specified, the cmdlet will not prompt for confirmation before proceeding with established connections and will disconnect from all of them. - - - SwitchParameter - - - False - - - WhatIf - - Shows what would happen if the cmdlet runs. The cmdlet is not run. - - - SwitchParameter - - - False - - - Confirm - - Prompts you for confirmation before running the cmdlet. - - - SwitchParameter - - - False - - - ProgressAction - - {{ Fill ProgressAction Description }} - - ActionPreference - - ActionPreference - - - None - - - - Invoke-M365SecurityAudit - - TenantAdminUrl - - The URL of the tenant admin. If not specified, none of the SharePoint Online tests will run. - - String - - String - - - None - - - 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. - - String - - String - - - None - IncludeIG1 @@ -912,6 +1165,89 @@ Retrieves the MFA status for the specified user with the UPN "example@domain.com False + + 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. + + String + + String + + + None + + + NoModuleCheck + + If specified, the cmdlet will not check for the presence of required modules. + + + SwitchParameter + + + False + + + ProgressAction + + {{ Fill ProgressAction Description }} + + ActionPreference + + ActionPreference + + + None + + + TenantAdminUrl + + The URL of the tenant admin. If not specified, none of the SharePoint Online tests will run. + + String + + String + + + None + + + Confirm + + Prompts you for confirmation before running the cmdlet. + + + SwitchParameter + + + False + + + WhatIf + + Shows what would happen if the cmdlet runs. The cmdlet is not run. + + + SwitchParameter + + + False + + + + Invoke-M365SecurityAudit + + DoNotConfirmConnections + + If specified, the cmdlet will not prompt for confirmation before proceeding with established connections and will disconnect from all of them. + + + SwitchParameter + + + False + DoNotConnect @@ -934,89 +1270,6 @@ Retrieves the MFA status for the specified user with the UPN "example@domain.com False - - NoModuleCheck - - If specified, the cmdlet will not check for the presence of required modules. - - - SwitchParameter - - - False - - - DoNotConfirmConnections - - If specified, the cmdlet will not prompt for confirmation before proceeding with established connections and will disconnect from all of them. - - - SwitchParameter - - - False - - - WhatIf - - Shows what would happen if the cmdlet runs. The cmdlet is not run. - - - SwitchParameter - - - False - - - Confirm - - Prompts you for confirmation before running the cmdlet. - - - SwitchParameter - - - False - - - ProgressAction - - {{ Fill ProgressAction Description }} - - ActionPreference - - ActionPreference - - - None - - - - Invoke-M365SecurityAudit - - TenantAdminUrl - - The URL of the tenant admin. If not specified, none of the SharePoint Online tests will run. - - String - - String - - - None - - - 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. - - String - - String - - - None - IncludeIG2 @@ -1028,6 +1281,89 @@ Retrieves the MFA status for the specified user with the UPN "example@domain.com False + + 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. + + String + + String + + + None + + + NoModuleCheck + + If specified, the cmdlet will not check for the presence of required modules. + + + SwitchParameter + + + False + + + ProgressAction + + {{ Fill ProgressAction Description }} + + ActionPreference + + ActionPreference + + + None + + + TenantAdminUrl + + The URL of the tenant admin. If not specified, none of the SharePoint Online tests will run. + + String + + String + + + None + + + Confirm + + Prompts you for confirmation before running the cmdlet. + + + SwitchParameter + + + False + + + WhatIf + + Shows what would happen if the cmdlet runs. The cmdlet is not run. + + + SwitchParameter + + + False + + + + Invoke-M365SecurityAudit + + DoNotConfirmConnections + + If specified, the cmdlet will not prompt for confirmation before proceeding with established connections and will disconnect from all of them. + + + SwitchParameter + + + False + DoNotConnect @@ -1050,89 +1386,6 @@ Retrieves the MFA status for the specified user with the UPN "example@domain.com False - - NoModuleCheck - - If specified, the cmdlet will not check for the presence of required modules. - - - SwitchParameter - - - False - - - DoNotConfirmConnections - - If specified, the cmdlet will not prompt for confirmation before proceeding with established connections and will disconnect from all of them. - - - SwitchParameter - - - False - - - WhatIf - - Shows what would happen if the cmdlet runs. The cmdlet is not run. - - - SwitchParameter - - - False - - - Confirm - - Prompts you for confirmation before running the cmdlet. - - - SwitchParameter - - - False - - - ProgressAction - - {{ Fill ProgressAction Description }} - - ActionPreference - - ActionPreference - - - None - - - - Invoke-M365SecurityAudit - - TenantAdminUrl - - The URL of the tenant admin. If not specified, none of the SharePoint Online tests will run. - - String - - String - - - None - - - 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. - - String - - String - - - None - IncludeIG3 @@ -1144,6 +1397,89 @@ Retrieves the MFA status for the specified user with the UPN "example@domain.com False + + 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. + + String + + String + + + None + + + NoModuleCheck + + If specified, the cmdlet will not check for the presence of required modules. + + + SwitchParameter + + + False + + + ProgressAction + + {{ Fill ProgressAction Description }} + + ActionPreference + + ActionPreference + + + None + + + TenantAdminUrl + + The URL of the tenant admin. If not specified, none of the SharePoint Online tests will run. + + String + + String + + + None + + + Confirm + + Prompts you for confirmation before running the cmdlet. + + + SwitchParameter + + + False + + + WhatIf + + Shows what would happen if the cmdlet runs. The cmdlet is not run. + + + SwitchParameter + + + False + + + + Invoke-M365SecurityAudit + + DoNotConfirmConnections + + If specified, the cmdlet will not prompt for confirmation before proceeding with established connections and will disconnect from all of them. + + + SwitchParameter + + + False + DoNotConnect @@ -1166,89 +1502,6 @@ Retrieves the MFA status for the specified user with the UPN "example@domain.com False - - NoModuleCheck - - If specified, the cmdlet will not check for the presence of required modules. - - - SwitchParameter - - - False - - - DoNotConfirmConnections - - If specified, the cmdlet will not prompt for confirmation before proceeding with established connections and will disconnect from all of them. - - - SwitchParameter - - - False - - - WhatIf - - Shows what would happen if the cmdlet runs. The cmdlet is not run. - - - SwitchParameter - - - False - - - Confirm - - Prompts you for confirmation before running the cmdlet. - - - SwitchParameter - - - False - - - ProgressAction - - {{ Fill ProgressAction Description }} - - ActionPreference - - ActionPreference - - - None - - - - Invoke-M365SecurityAudit - - TenantAdminUrl - - The URL of the tenant admin. If not specified, none of the SharePoint Online tests will run. - - String - - String - - - None - - - 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. - - String - - String - - - None - IncludeRecommendation @@ -1261,6 +1514,89 @@ Retrieves the MFA status for the specified user with the UPN "example@domain.com None + + 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. + + String + + String + + + None + + + NoModuleCheck + + If specified, the cmdlet will not check for the presence of required modules. + + + SwitchParameter + + + False + + + ProgressAction + + {{ Fill ProgressAction Description }} + + ActionPreference + + ActionPreference + + + None + + + TenantAdminUrl + + The URL of the tenant admin. If not specified, none of the SharePoint Online tests will run. + + String + + String + + + None + + + Confirm + + Prompts you for confirmation before running the cmdlet. + + + SwitchParameter + + + False + + + WhatIf + + Shows what would happen if the cmdlet runs. The cmdlet is not run. + + + SwitchParameter + + + False + + + + Invoke-M365SecurityAudit + + DoNotConfirmConnections + + If specified, the cmdlet will not prompt for confirmation before proceeding with established connections and will disconnect from all of them. + + + SwitchParameter + + + False + DoNotConnect @@ -1283,6 +1619,18 @@ Retrieves the MFA status for the specified user with the UPN "example@domain.com False + + 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. + + String + + String + + + None + NoModuleCheck @@ -1294,39 +1642,6 @@ Retrieves the MFA status for the specified user with the UPN "example@domain.com False - - DoNotConfirmConnections - - If specified, the cmdlet will not prompt for confirmation before proceeding with established connections and will disconnect from all of them. - - - SwitchParameter - - - False - - - WhatIf - - Shows what would happen if the cmdlet runs. The cmdlet is not run. - - - SwitchParameter - - - False - - - Confirm - - Prompts you for confirmation before running the cmdlet. - - - SwitchParameter - - - False - ProgressAction @@ -1339,33 +1654,6 @@ Retrieves the MFA status for the specified user with the UPN "example@domain.com None - - - Invoke-M365SecurityAudit - - TenantAdminUrl - - The URL of the tenant admin. If not specified, none of the SharePoint Online tests will run. - - String - - String - - - None - - - 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. - - String - - String - - - None - SkipRecommendation @@ -1379,42 +1667,21 @@ Retrieves the MFA status for the specified user with the UPN "example@domain.com None - DoNotConnect + TenantAdminUrl - If specified, the cmdlet will not establish a connection to Microsoft 365 services. + The URL of the tenant admin. If not specified, none of the SharePoint Online tests will run. + String - SwitchParameter + String - False + None - - DoNotDisconnect + + Confirm - If specified, the cmdlet will not disconnect from Microsoft 365 services after execution. - - - SwitchParameter - - - False - - - NoModuleCheck - - If specified, the cmdlet will not check for the presence of required modules. - - - SwitchParameter - - - False - - - DoNotConfirmConnections - - If specified, the cmdlet will not prompt for confirmation before proceeding with established connections and will disconnect from all of them. + Prompts you for confirmation before running the cmdlet. SwitchParameter @@ -1433,55 +1700,44 @@ Retrieves the MFA status for the specified user with the UPN "example@domain.com False - - Confirm - - Prompts you for confirmation before running the cmdlet. - - - SwitchParameter - - - False - - - ProgressAction - - {{ Fill ProgressAction Description }} - - ActionPreference - - ActionPreference - - - None - - TenantAdminUrl + DoNotConfirmConnections - The URL of the tenant admin. If not specified, none of the SharePoint Online tests will run. + If specified, the cmdlet will not prompt for confirmation before proceeding with established connections and will disconnect from all of them. - String + SwitchParameter - String + SwitchParameter - None + False - M365DomainForPWPolicyTest + DoNotConnect - 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. + If specified, the cmdlet will not establish a connection to Microsoft 365 services. - String + SwitchParameter - String + SwitchParameter - None + False + + + DoNotDisconnect + + If specified, the cmdlet will not disconnect from Microsoft 365 services after execution. + + SwitchParameter + + SwitchParameter + + + False ELevel @@ -1495,18 +1751,6 @@ Retrieves the MFA status for the specified user with the UPN "example@domain.com None - - ProfileLevel - - Specifies the profile level (L1 or L2) for the audit. This parameter is optional and can be combined with the ELevel parameter. - - String - - String - - - None - IncludeIG1 @@ -1555,42 +1799,18 @@ Retrieves the MFA status for the specified user with the UPN "example@domain.com None - - SkipRecommendation + + M365DomainForPWPolicyTest - Specifies specific recommendations to exclude from the audit. Accepts an array of recommendation numbers. + 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. - String[] + String - String[] + String None - - DoNotConnect - - If specified, the cmdlet will not establish a connection to Microsoft 365 services. - - SwitchParameter - - SwitchParameter - - - False - - - DoNotDisconnect - - If specified, the cmdlet will not disconnect from Microsoft 365 services after execution. - - SwitchParameter - - SwitchParameter - - - False - NoModuleCheck @@ -1603,10 +1823,58 @@ Retrieves the MFA status for the specified user with the UPN "example@domain.com False - - DoNotConfirmConnections + + ProfileLevel - If specified, the cmdlet will not prompt for confirmation before proceeding with established connections and will disconnect from all of them. + Specifies the profile level (L1 or L2) for the audit. This parameter is optional and can be combined with the ELevel parameter. + + String + + String + + + None + + + ProgressAction + + {{ Fill ProgressAction Description }} + + ActionPreference + + ActionPreference + + + None + + + SkipRecommendation + + Specifies specific recommendations to exclude from the audit. Accepts an array of recommendation numbers. + + String[] + + String[] + + + None + + + TenantAdminUrl + + The URL of the tenant admin. If not specified, none of the SharePoint Online tests will run. + + String + + String + + + None + + + Confirm + + Prompts you for confirmation before running the cmdlet. SwitchParameter @@ -1627,30 +1895,6 @@ Retrieves the MFA status for the specified user with the UPN "example@domain.com False - - Confirm - - Prompts you for confirmation before running the cmdlet. - - SwitchParameter - - SwitchParameter - - - False - - - ProgressAction - - {{ Fill ProgressAction Description }} - - ActionPreference - - ActionPreference - - - None - @@ -1821,18 +2065,6 @@ PS> $auditResults | Export-Csv -Path "auditResults.csv" -NoTypeInformation None - - WorksheetName - - The name of the worksheet within the Excel file to be processed. - - String - - String - - - None - ProgressAction @@ -1845,6 +2077,18 @@ PS> $auditResults | Export-Csv -Path "auditResults.csv" -NoTypeInformation None + + WorksheetName + + The name of the worksheet within the Excel file to be processed. + + String + + String + + + None + @@ -1931,18 +2175,6 @@ This command imports data from the "Sheet1" worksheet in the "Report.xlsx" file, - - ExcelPath - - Specifies the path to the Excel file to be updated. This parameter is mandatory. - - String - - String - - - None - CsvPath @@ -1955,10 +2187,10 @@ This command imports data from the "Sheet1" worksheet in the "Report.xlsx" file, None - - SheetName + + ExcelPath - Specifies the name of the worksheet in the Excel file where data will be merged and updated. This parameter is mandatory. + Specifies the path to the Excel file to be updated. This parameter is mandatory. String @@ -1979,6 +2211,18 @@ This command imports data from the "Sheet1" worksheet in the "Report.xlsx" file, None + + SheetName + + Specifies the name of the worksheet in the Excel file where data will be merged and updated. This parameter is mandatory. + + String + + String + + + None + diff --git a/source/en-US/about_M365FoundationsCISReport.help.txt b/source/en-US/about_M365FoundationsCISReport.help.txt index 2dc01a1..c64914f 100644 --- a/source/en-US/about_M365FoundationsCISReport.help.txt +++ b/source/en-US/about_M365FoundationsCISReport.help.txt @@ -45,6 +45,9 @@ EXAMPLES # Example 6: Synchronizing CIS benchmark data with audit results Sync-CISExcelAndCsvData -ExcelPath "path\to\excel.xlsx" -CsvPath "path\to\data.csv" -SheetName "Combined Profiles" + + # Example 7: Granting Microsoft Graph permissions to the auditor + Grant-M365SecurityAuditConsent -UserPrincipalNameForConsent 'user@example.com' NOTE Ensure that you have the necessary permissions and administrative roles in