18 Commits

Author SHA1 Message Date
Doug Rios
95eb18ccf4 Merge pull request #127 from CriticalSolutionsNetwork/Add-Microsoft-Graph-Consent-for-user-function
Add microsoft graph consent for user function
2024-06-26 21:41:16 -05:00
DrIOS
05a6d76fb7 docs: Update HELP docs 2024-06-26 21:36:55 -05:00
DrIOS
0465c3a41d docs: Update CHANGELOG 2024-06-26 21:31:05 -05:00
DrIOS
d4632c0a6f add: Added Grant-M365SecurityAuditConsent function to consent to the Microsoft Graph Powershell API for a user. 2024-06-26 21:30:41 -05:00
DrIOS
0ea5aa2581 docs: Update helper to retrieve keys 2024-06-26 16:19:17 -05:00
Doug Rios
9402fde503 Merge pull request #123 from CriticalSolutionsNetwork/Test-8.5.3,8.6.1-logic
Test 8.5.3,8.6.1 logic
2024-06-26 09:09:30 -05:00
DrIOS
6ed0e239b7 docs: Update CHANGELOG 2024-06-26 09:06:58 -05:00
DrIOS
168cc38679 docs: Update CHANGELOG 2024-06-26 09:00:39 -05:00
DrIOS
59278f4a27 Fix: Export when tests with nested tables not included. 2024-06-26 08:54:57 -05:00
DrIOS
51f662ff58 Fix: 8.6.1 output and formatting in line with recommendation 2024-06-26 08:54:32 -05:00
DrIOS
c4bbf25e8b docs: Update CHANGELOG 2024-06-24 19:24:15 -05:00
DrIOS
143ee69fb5 fix: 8.6.1 test logic and output 2024-06-24 19:22:17 -05:00
DrIOS
fd53384f8e docs: Update CHANGELOG 2024-06-24 19:19:29 -05:00
DrIOS
73bce280eb docs: Update Help 2024-06-24 19:15:15 -05:00
DrIOS
0a92100bb6 fix: 8.6.1 test logic and output 2024-06-24 19:14:43 -05:00
DrIOS
18287169c3 docs: swap details / fr in 8.5.3 2024-06-24 18:27:48 -05:00
DrIOS
abe18f1942 docs: Add wiki help docs 2024-06-24 15:06:04 -05:00
DrIOS
95da5a3822 docs: Update CHANGELOG and WIKI 2024-06-24 12:11:24 -05:00
21 changed files with 4053 additions and 34 deletions

View File

@@ -4,6 +4,24 @@ The format is based on and uses the types of changes according to [Keep a Change
## [Unreleased] ## [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`
- Fixed help `about_M365FoundationsCISReport` examples.
- Fixed `Export-M365SecurityAuditTable` to properly export when nested table tests are not included.
### Changed
- Changed output of failure reason and details for 8.5.3 and 8.6.1 to be in line with other tests.
## [0.1.14] - 2024-06-23
### Fixed ### Fixed
- Fixed test 1.3.1 to include notification window for password expiration. - Fixed test 1.3.1 to include notification window for password expiration.

BIN
README.md

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,218 @@
---
external help file: M365FoundationsCISReport-help.xml
Module Name: M365FoundationsCISReport
online version: https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Export-M365SecurityAuditTable
schema: 2.0.0
---
# Export-M365SecurityAuditTable
## SYNOPSIS
Exports M365 security audit results to a CSV file or outputs a specific test result as an object.
## SYNTAX
### OutputObjectFromAuditResultsSingle
```
Export-M365SecurityAuditTable [-AuditResults] <CISAuditResult[]> [-OutputTestNumber] <String>
[-ProgressAction <ActionPreference>] [<CommonParameters>]
```
### ExportAllResultsFromAuditResults
```
Export-M365SecurityAuditTable [-AuditResults] <CISAuditResult[]> [-ExportAllTests] -ExportPath <String>
[-ExportOriginalTests] [-ExportToExcel] [-ProgressAction <ActionPreference>] [<CommonParameters>]
```
### OutputObjectFromCsvSingle
```
Export-M365SecurityAuditTable [-CsvPath] <String> [-OutputTestNumber] <String>
[-ProgressAction <ActionPreference>] [<CommonParameters>]
```
### ExportAllResultsFromCsv
```
Export-M365SecurityAuditTable [-CsvPath] <String> [-ExportAllTests] -ExportPath <String> [-ExportOriginalTests]
[-ExportToExcel] [-ProgressAction <ActionPreference>] [<CommonParameters>]
```
## DESCRIPTION
This function exports M365 security audit results from either an array of CISAuditResult objects or a CSV file.
It can export all results to a specified path or output a specific test result as an object.
## EXAMPLES
### EXAMPLE 1
```
Export-M365SecurityAuditTable -AuditResults $object -OutputTestNumber 6.1.2
# Output object for a single test number from audit results
```
### EXAMPLE 2
```
Export-M365SecurityAuditTable -ExportAllTests -AuditResults $object -ExportPath "C:\temp"
# Export all results from audit results to the specified path
```
### EXAMPLE 3
```
Export-M365SecurityAuditTable -CsvPath "C:\temp\auditresultstoday1.csv" -OutputTestNumber 6.1.2
# Output object for a single test number from CSV
```
### EXAMPLE 4
```
Export-M365SecurityAuditTable -ExportAllTests -CsvPath "C:\temp\auditresultstoday1.csv" -ExportPath "C:\temp"
# Export all results from CSV to the specified path
```
### EXAMPLE 5
```
Export-M365SecurityAuditTable -ExportAllTests -AuditResults $object -ExportPath "C:\temp" -ExportOriginalTests
# Export all results from audit results to the specified path along with the original tests
```
### EXAMPLE 6
```
Export-M365SecurityAuditTable -ExportAllTests -CsvPath "C:\temp\auditresultstoday1.csv" -ExportPath "C:\temp" -ExportOriginalTests
# Export all results from CSV to the specified path along with the original tests
```
## PARAMETERS
### -AuditResults
An array of CISAuditResult objects containing the audit results.
```yaml
Type: CISAuditResult[]
Parameter Sets: OutputObjectFromAuditResultsSingle, ExportAllResultsFromAuditResults
Aliases:
Required: True
Position: 3
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -CsvPath
The path to a CSV file containing the audit results.
```yaml
Type: String
Parameter Sets: OutputObjectFromCsvSingle, ExportAllResultsFromCsv
Aliases:
Required: True
Position: 3
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ExportAllTests
Switch to export all test results.
```yaml
Type: SwitchParameter
Parameter Sets: ExportAllResultsFromAuditResults, ExportAllResultsFromCsv
Aliases:
Required: True
Position: 1
Default value: False
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.
```yaml
Type: String
Parameter Sets: ExportAllResultsFromAuditResults, ExportAllResultsFromCsv
Aliases:
Required: True
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ExportToExcel
Switch to export the results to an Excel file.
```yaml
Type: SwitchParameter
Parameter Sets: ExportAllResultsFromAuditResults, ExportAllResultsFromCsv
Aliases:
Required: False
Position: Named
Default value: False
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
```
### -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).
## INPUTS
### [CISAuditResult[]], [string]
## OUTPUTS
### [PSCustomObject]
## NOTES
## RELATED LINKS
[https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Export-M365SecurityAuditTable](https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Export-M365SecurityAuditTable)

View File

@@ -0,0 +1,89 @@
---
external help file: M365FoundationsCISReport-help.xml
Module Name: M365FoundationsCISReport
online version: https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Get-AdminRoleUserLicense
schema: 2.0.0
---
# Get-AdminRoleUserLicense
## SYNOPSIS
Retrieves user licenses and roles for administrative accounts from Microsoft 365 via the Graph API.
## SYNTAX
```
Get-AdminRoleUserLicense [-SkipGraphConnection] [-ProgressAction <ActionPreference>] [<CommonParameters>]
```
## DESCRIPTION
The Get-AdminRoleUserLicense function connects to Microsoft Graph and retrieves all users who are assigned administrative roles along with their user details and licenses.
This function is useful for auditing and compliance checks to ensure that administrators have appropriate licenses and role assignments.
## EXAMPLES
### EXAMPLE 1
```
Get-AdminRoleUserLicense
```
This example retrieves all administrative role users along with their licenses by connecting to Microsoft Graph using the default scopes.
### EXAMPLE 2
```
Get-AdminRoleUserLicense -SkipGraphConnection
```
This example retrieves all administrative role users along with their licenses without attempting to connect to Microsoft Graph, assuming that the connection is already established.
## 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.
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: False
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
### None. You cannot pipe objects to Get-AdminRoleUserLicense.
## OUTPUTS
### PSCustomObject
### Returns a custom object for each user with administrative roles that includes the following properties: RoleName, UserName, UserPrincipalName, UserId, HybridUser, and Licenses.
## NOTES
Creation Date: 2024-04-15
Purpose/Change: Initial function development to support Microsoft 365 administrative role auditing.
## RELATED LINKS
[https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Get-AdminRoleUserLicense](https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Get-AdminRoleUserLicense)

109
help/Get-MFAStatus.md Normal file
View File

@@ -0,0 +1,109 @@
---
external help file: M365FoundationsCISReport-help.xml
Module Name: M365FoundationsCISReport
online version: https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Get-MFAStatus
schema: 2.0.0
---
# Get-MFAStatus
## SYNOPSIS
Retrieves the MFA (Multi-Factor Authentication) status for Azure Active Directory users.
## SYNTAX
```
Get-MFAStatus [[-UserId] <String>] [-SkipMSOLConnectionChecks] [-ProgressAction <ActionPreference>]
[<CommonParameters>]
```
## DESCRIPTION
The Get-MFAStatus function connects to Microsoft Online Service and retrieves the MFA status for all Azure Active Directory users, excluding guest accounts.
Optionally, you can specify a single user by their User Principal Name (UPN) to get their MFA status.
## EXAMPLES
### EXAMPLE 1
```
Get-MFAStatus
Retrieves the MFA status for all Azure Active Directory users.
```
### EXAMPLE 2
```
Get-MFAStatus -UserId "example@domain.com"
Retrieves the MFA status for the specified user with the UPN "example@domain.com".
```
## 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
```
### -SkipMSOLConnectionChecks
{{ Fill SkipMSOLConnectionChecks Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: False
Accept pipeline input: False
Accept wildcard characters: False
```
### -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: String
Parameter Sets: (All)
Aliases:
Required: False
Position: 1
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.Object
### Returns a sorted list of custom objects containing the following properties:
### - UserPrincipalName
### - DisplayName
### - MFAState
### - MFADefaultMethod
### - MFAPhoneNumber
### - PrimarySMTP
### - Aliases
## NOTES
The function requires the MSOL module to be installed and connected to your tenant.
Ensure that you have the necessary permissions to read user and MFA status information.
## RELATED LINKS
[https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Get-MFAStatus](https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Get-MFAStatus)

View File

@@ -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] <String> [-SkipGraphConnection]
[-SkipModuleCheck] [-SuppressRevertOutput] [-DoNotDisconnect] [-ProgressAction <ActionPreference>] [-WhatIf]
[-Confirm] [<CommonParameters>]
```
## 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)

View File

@@ -0,0 +1,435 @@
---
external help file: M365FoundationsCISReport-help.xml
Module Name: M365FoundationsCISReport
online version: https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Invoke-M365SecurityAudit
schema: 2.0.0
---
# Invoke-M365SecurityAudit
## SYNOPSIS
Invokes a security audit for Microsoft 365 environments.
## SYNTAX
### Default (Default)
```
Invoke-M365SecurityAudit [-TenantAdminUrl <String>] [-M365DomainForPWPolicyTest <String>] [-DoNotConnect]
[-DoNotDisconnect] [-NoModuleCheck] [-DoNotConfirmConnections] [-ProgressAction <ActionPreference>] [-WhatIf]
[-Confirm] [<CommonParameters>]
```
### ELevelFilter
```
Invoke-M365SecurityAudit [-TenantAdminUrl <String>] [-M365DomainForPWPolicyTest <String>] -ELevel <String>
-ProfileLevel <String> [-DoNotConnect] [-DoNotDisconnect] [-NoModuleCheck] [-DoNotConfirmConnections]
[-ProgressAction <ActionPreference>] [-WhatIf] [-Confirm] [<CommonParameters>]
```
### IG1Filter
```
Invoke-M365SecurityAudit [-TenantAdminUrl <String>] [-M365DomainForPWPolicyTest <String>] [-IncludeIG1]
[-DoNotConnect] [-DoNotDisconnect] [-NoModuleCheck] [-DoNotConfirmConnections]
[-ProgressAction <ActionPreference>] [-WhatIf] [-Confirm] [<CommonParameters>]
```
### IG2Filter
```
Invoke-M365SecurityAudit [-TenantAdminUrl <String>] [-M365DomainForPWPolicyTest <String>] [-IncludeIG2]
[-DoNotConnect] [-DoNotDisconnect] [-NoModuleCheck] [-DoNotConfirmConnections]
[-ProgressAction <ActionPreference>] [-WhatIf] [-Confirm] [<CommonParameters>]
```
### IG3Filter
```
Invoke-M365SecurityAudit [-TenantAdminUrl <String>] [-M365DomainForPWPolicyTest <String>] [-IncludeIG3]
[-DoNotConnect] [-DoNotDisconnect] [-NoModuleCheck] [-DoNotConfirmConnections]
[-ProgressAction <ActionPreference>] [-WhatIf] [-Confirm] [<CommonParameters>]
```
### RecFilter
```
Invoke-M365SecurityAudit [-TenantAdminUrl <String>] [-M365DomainForPWPolicyTest <String>]
-IncludeRecommendation <String[]> [-DoNotConnect] [-DoNotDisconnect] [-NoModuleCheck]
[-DoNotConfirmConnections] [-ProgressAction <ActionPreference>] [-WhatIf] [-Confirm] [<CommonParameters>]
```
### SkipRecFilter
```
Invoke-M365SecurityAudit [-TenantAdminUrl <String>] [-M365DomainForPWPolicyTest <String>]
-SkipRecommendation <String[]> [-DoNotConnect] [-DoNotDisconnect] [-NoModuleCheck] [-DoNotConfirmConnections]
[-ProgressAction <ActionPreference>] [-WhatIf] [-Confirm] [<CommonParameters>]
```
## 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.
## EXAMPLES
### EXAMPLE 1
```
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 2
```
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 3
```
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 4
```
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 5
```
$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 6
```
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".
## PARAMETERS
### -DoNotConfirmConnections
If specified, the cmdlet will not prompt for confirmation before proceeding with established connections and will disconnect from all of them.
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: False
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
```
### -ELevel
Specifies the E-Level (E3 or E5) for the audit.
This parameter is optional and can be combined with the ProfileLevel 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.
```yaml
Type: SwitchParameter
Parameter Sets: IG1Filter
Aliases:
Required: True
Position: Named
Default value: False
Accept pipeline input: False
Accept wildcard characters: False
```
### -IncludeIG2
If specified, includes tests where IG2 is true.
```yaml
Type: SwitchParameter
Parameter Sets: IG2Filter
Aliases:
Required: True
Position: Named
Default value: False
Accept pipeline input: False
Accept wildcard characters: False
```
### -IncludeIG3
If specified, includes tests where IG3 is true.
```yaml
Type: SwitchParameter
Parameter Sets: IG3Filter
Aliases:
Required: True
Position: Named
Default value: False
Accept pipeline input: False
Accept wildcard characters: False
```
### -IncludeRecommendation
Specifies specific recommendations to include in the audit.
Accepts an array of recommendation numbers.
```yaml
Type: String[]
Parameter Sets: RecFilter
Aliases:
Required: True
Position: Named
Default value: None
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.
```yaml
Type: String
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -NoModuleCheck
If specified, the cmdlet will not check for the presence of required modules.
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: False
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
```
### -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
```
### -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
Default value: None
Accept pipeline input: False
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
### None. You cannot pipe objects to Invoke-M365SecurityAudit.
## OUTPUTS
### 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
## RELATED LINKS
[https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Invoke-M365SecurityAudit](https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Invoke-M365SecurityAudit)

View File

@@ -0,0 +1,31 @@
---
Module Name: M365FoundationsCISReport
Module Guid: 0d064bfb-d1ce-484b-a173-993b55984dc9
Download Help Link: {{Please enter Link manually}}
Help Version: 1.0.0.0
Locale: en-US
---
# M365FoundationsCISReport Module
## Description
The `M365FoundationsCISReport` module provides a set of cmdlets to audit and report on the security compliance of Microsoft 365 environments based on CIS (Center for Internet Security) benchmarks. It enables administrators to generate detailed reports, sync data with CIS Excel sheets, and perform security audits to ensure compliance.
## M365FoundationsCISReport Cmdlets
### [Export-M365SecurityAuditTable](Export-M365SecurityAuditTable.md)
Exports M365 security audit results to a CSV file or outputs a specific test result as an object.
### [Get-AdminRoleUserLicense](Get-AdminRoleUserLicense.md)
Retrieves user licenses and roles for administrative accounts from Microsoft 365 via the Graph API.
### [Get-MFAStatus](Get-MFAStatus.md)
Retrieves the MFA (Multi-Factor Authentication) status for Azure Active Directory users.
### [Invoke-M365SecurityAudit](Invoke-M365SecurityAudit.md)
Invokes a security audit for Microsoft 365 environments.
### [Remove-RowsWithEmptyCSVStatus](Remove-RowsWithEmptyCSVStatus.md)
Removes rows from an Excel worksheet where the 'CSV_Status' column is empty and saves the result to a new file.
### [Sync-CISExcelAndCsvData](Sync-CISExcelAndCsvData.md)
Synchronizes and updates data in an Excel worksheet with new information from a CSV file, including audit dates.

View File

@@ -0,0 +1,89 @@
---
external help file: M365FoundationsCISReport-help.xml
Module Name: M365FoundationsCISReport
online version:
schema: 2.0.0
---
# Remove-RowsWithEmptyCSVStatus
## SYNOPSIS
Removes rows from an Excel worksheet where the 'CSV_Status' column is empty and saves the result to a new file.
## SYNTAX
```
Remove-RowsWithEmptyCSVStatus [-FilePath] <String> [-WorksheetName] <String>
[-ProgressAction <ActionPreference>] [<CommonParameters>]
```
## DESCRIPTION
The Remove-RowsWithEmptyCSVStatus function imports data from a specified worksheet in an Excel file, checks for the presence of the 'CSV_Status' column, and filters out rows where the 'CSV_Status' column is empty.
The filtered data is then exported to a new Excel file with a '-Filtered' suffix added to the original file name.
## EXAMPLES
### EXAMPLE 1
```
Remove-RowsWithEmptyCSVStatus -FilePath "C:\Reports\Report.xlsx" -WorksheetName "Sheet1"
This command imports data from the "Sheet1" worksheet in the "Report.xlsx" file, removes rows where the 'CSV_Status' column is empty, and saves the filtered data to a new file named "Report-Filtered.xlsx" in the same directory.
```
## PARAMETERS
### -FilePath
The path to the Excel file to be processed.
```yaml
Type: String
Parameter Sets: (All)
Aliases:
Required: True
Position: 1
Default value: None
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
```
### -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).
## INPUTS
## OUTPUTS
## NOTES
This function requires the ImportExcel module to be installed.
## RELATED LINKS

View File

@@ -0,0 +1,117 @@
---
external help file: M365FoundationsCISReport-help.xml
Module Name: M365FoundationsCISReport
online version: https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Sync-CISExcelAndCsvData
schema: 2.0.0
---
# Sync-CISExcelAndCsvData
## SYNOPSIS
Synchronizes and updates data in an Excel worksheet with new information from a CSV file, including audit dates.
## SYNTAX
```
Sync-CISExcelAndCsvData [[-ExcelPath] <String>] [[-CsvPath] <String>] [[-SheetName] <String>]
[-ProgressAction <ActionPreference>] [<CommonParameters>]
```
## DESCRIPTION
The Sync-CISExcelAndCsvData function merges and updates data in a specified Excel worksheet from a CSV file.
This includes adding or updating fields for connection status, details, failure reasons, and the date of the update.
It's designed to ensure that the Excel document maintains a running log of changes over time, ideal for tracking remediation status and audit history.
## EXAMPLES
### EXAMPLE 1
```
Sync-CISExcelAndCsvData -ExcelPath "path\to\excel.xlsx" -CsvPath "path\to\data.csv" -SheetName "AuditData"
Updates the 'AuditData' worksheet in 'excel.xlsx' with data from 'data.csv', adding new information and the date of the update.
```
## PARAMETERS
### -CsvPath
Specifies the path to the CSV file containing new data.
This parameter is mandatory.
```yaml
Type: String
Parameter Sets: (All)
Aliases:
Required: False
Position: 2
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -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
```
### -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
```
### -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).
## INPUTS
### System.String
### The function accepts strings for file paths and worksheet names.
## OUTPUTS
### None
### The function directly updates the Excel file and does not output any objects.
## NOTES
- Ensure that the 'ImportExcel' module is installed and up to date to handle Excel file manipulations.
- It is recommended to back up the Excel file before running this function to avoid accidental data loss.
- The CSV file should have columns that match expected headers like 'Connection', 'Details', 'FailureReason', and 'Status' for correct data mapping.
## RELATED LINKS
[https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Sync-CISExcelAndCsvData](https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Sync-CISExcelAndCsvData)

View File

@@ -0,0 +1,59 @@
# M365FoundationsCISReport
## about_M365FoundationsCISReport
# SHORT DESCRIPTION
The `M365FoundationsCISReport` module provides cmdlets for auditing and reporting on the security compliance of Microsoft 365 environments based on CIS benchmarks.
# LONG DESCRIPTION
The `M365FoundationsCISReport` module is designed to help administrators ensure that their Microsoft 365 environments adhere to the security best practices outlined by the Center for Internet Security (CIS). The module includes cmdlets for performing comprehensive security audits, generating detailed reports, and synchronizing audit results with CIS benchmark Excel sheets. It aims to streamline the process of maintaining security compliance and improving the overall security posture of Microsoft 365 environments.
## Optional Subtopics
### Auditing and Reporting
The module provides cmdlets that allow for the auditing of various security aspects of Microsoft 365 environments, including user MFA status, administrative role licenses, and more. The results can be exported and analyzed to ensure compliance with CIS benchmarks.
### Data Synchronization
The module includes functionality to synchronize audit results with CIS benchmark data stored in Excel sheets. This ensures that the documentation is always up-to-date with the latest audit findings.
# EXAMPLES
```powershell
# Example 1: Performing a security audit based on CIS benchmarks
$auditResults = Invoke-M365SecurityAudit -TenantAdminUrl "https://contoso-admin.sharepoint.com"
# Example 2: Exporting a security audit table to a CSV file
Export-M365SecurityAuditTable -ExportAllTests -AuditResults $auditResults -ExportPath "C:\temp" -ExportOriginalTests
# Example 3: Retrieving licenses for users in administrative roles
Get-AdminRoleUserLicense
# Example 4: Getting MFA status of users
Get-MFAStatus -UserId "user@domain.com"
# Example 5: Removing rows with empty status values from a CSV file
Remove-RowsWithEmptyCSVStatus -FilePath "C:\Reports\Report.xlsx" -WorksheetName "Sheet1"
# 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 your Microsoft 365 environment to run these cmdlets. Proper configuration and setup are required for accurate audit results.
# TROUBLESHOOTING NOTE
If you encounter any issues while using the cmdlets, ensure that your environment meets the module prerequisites. Check for any updates or patches that may address known bugs. For issues related to specific cmdlets, refer to the individual help files for troubleshooting tips.
# SEE ALSO
- [CIS Benchmarks](https://www.cisecurity.org/cis-benchmarks/)
- [Microsoft 365 Security Documentation](https://docs.microsoft.com/en-us/microsoft-365/security/)
- [PowerShell Documentation](https://docs.microsoft.com/en-us/powershell/)
# KEYWORDS
- Microsoft 365
- Security Audit
- CIS Benchmarks
- Compliance
- MFA
- User Licenses
- Security Reporting

View File

@@ -4,7 +4,7 @@ Import-Module .\output\module\M365FoundationsCISReport\*\*.psd1
<# <#
$ver = "v0.1.12" $ver = "v0.1.15"
git checkout main git checkout main
git pull origin main git pull origin main
git tag -a $ver -m "Release version $ver refactor Update" git tag -a $ver -m "Release version $ver refactor Update"
@@ -13,3 +13,52 @@ Import-Module .\output\module\M365FoundationsCISReport\*\*.psd1
git push origin $ver git push origin $ver
# git tag -d $ver # git tag -d $ver
#> #>
$OutputFolder = ".\help"
$parameters = @{
Module = "M365FoundationsCISReport"
OutputFolder = $OutputFolder
AlphabeticParamsOrder = $true
WithModulePage = $true
ExcludeDontShow = $true
Encoding = [System.Text.Encoding]::UTF8
}
New-MarkdownHelp @parameters
New-MarkdownAboutHelp -OutputFolder $OutputFolder -AboutName "M365FoundationsCISReport"
####
$parameters = @{
Path = ".\help"
RefreshModulePage = $true
AlphabeticParamsOrder = $true
UpdateInputOutput = $true
ExcludeDontShow = $true
LogPath = ".\log.txt"
Encoding = [System.Text.Encoding]::UTF8
}
Update-MarkdownHelpModule @parameters -Force
Update-MarkdownHelpModule -Path ".\help" -RefreshModulePage -Force
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

View File

@@ -284,7 +284,7 @@ function Get-CISExoOutput {
# Retrieve the necessary settings for Teams and Exchange Online # Retrieve the necessary settings for Teams and Exchange Online
# Condition B: Verify that 'Monitor reported messages in Microsoft Teams' is checked in the Microsoft 365 Defender portal. # Condition B: Verify that 'Monitor reported messages in Microsoft Teams' is checked in the Microsoft 365 Defender portal.
# Condition C: Ensure the 'Send reported messages to' setting in the Microsoft 365 Defender portal is set to 'My reporting mailbox only' with the correct report email addresses. # Condition C: Ensure the 'Send reported messages to' setting in the Microsoft 365 Defender portal is set to 'My reporting mailbox only' with the correct report email addresses.
$ReportSubmissionPolicy = Get-ReportSubmissionPolicy | Select-Object -Property ReportJunkToCustomizedAddress, ReportNotJunkToCustomizedAddress, ReportPhishToCustomizedAddress, ReportChatMessageToCustomizedAddressEnabled $ReportSubmissionPolicy = Get-ReportSubmissionPolicy | Select-Object -Property ReportJunkToCustomizedAddress, ReportNotJunkToCustomizedAddress, ReportPhishToCustomizedAddress,ReportJunkAddresses,ReportNotJunkAddresses,ReportPhishAddresses,ReportChatMessageEnabled,ReportChatMessageToCustomizedAddressEnabled
return $ReportSubmissionPolicy return $ReportSubmissionPolicy
} }
default { throw "No match found for test: $Rec" } default { throw "No match found for test: $Rec" }

View File

@@ -191,7 +191,7 @@ function Export-M365SecurityAuditTable {
} }
else { else {
if ($ExportOriginalTests) { if ($ExportOriginalTests) {
Write-Information "No specified tests were included in the export other than the full audit results." -InformationAction Continue Write-Information "Full audit results exported however, none of the following tests had exports: `n1.1.1, 1.3.1, 6.1.2, 6.1.3, 7.3.4" -InformationAction Continue
} }
else { else {
Write-Information "No specified tests were included in the export." -InformationAction Continue Write-Information "No specified tests were included in the export." -InformationAction Continue
@@ -201,9 +201,12 @@ function Export-M365SecurityAuditTable {
if ($ExportOriginalTests) { if ($ExportOriginalTests) {
# Define the test numbers to check # Define the test numbers to check
$TestNumbersToCheck = "1.1.1", "1.3.1", "6.1.2", "6.1.3", "7.3.4" $TestNumbersToCheck = "1.1.1", "1.3.1", "6.1.2", "6.1.3", "7.3.4"
if ($exportedTests.Count -gt 0) {
# Check for large details and update the AuditResults array $updatedAuditResults = Get-ExceededLengthResultDetail -AuditResults $AuditResults -TestNumbersToCheck $TestNumbersToCheck -ExportedTests $exportedTests -DetailsLengthLimit 30000 -PreviewLineCount 25
$updatedAuditResults = Get-ExceededLengthResultDetail -AuditResults $AuditResults -TestNumbersToCheck $TestNumbersToCheck -ExportedTests $exportedTests -DetailsLengthLimit 30000 -PreviewLineCount 25 }
else {
$updatedAuditResults = $auditResults
}
$originalFileName = "$ExportPath\$timestamp`_M365FoundationsAudit.csv" $originalFileName = "$ExportPath\$timestamp`_M365FoundationsAudit.csv"
if ($ExportToExcel) { if ($ExportToExcel) {
$xlsxPath = [System.IO.Path]::ChangeExtension($originalFileName, '.xlsx') $xlsxPath = [System.IO.Path]::ChangeExtension($originalFileName, '.xlsx')

View File

@@ -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
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,24 +1,79 @@
TOPIC TOPIC
about_M365FoundationsCISReport about_m365foundationscisreport
SHORT DESCRIPTION SHORT DESCRIPTION
Automated assessment of 50 CIS 365 Foundations v3.0.0 benchmark. The `M365FoundationsCISReport` module provides cmdlets for auditing and
reporting on the security compliance of Microsoft 365 environments based on
CIS benchmarks.
LONG DESCRIPTION LONG DESCRIPTION
Automated assessment of 50 CIS 365 Foundations v3.0.0 benchmark. The `M365FoundationsCISReport` module is designed to help administrators
ensure that their Microsoft 365 environments adhere to the security best
practices outlined by the Center for Internet Security (CIS). The module
includes cmdlets for performing comprehensive security audits, generating
detailed reports, and synchronizing audit results with CIS benchmark Excel
sheets. It aims to streamline the process of maintaining security compliance
and improving the overall security posture of Microsoft 365 environments.
Optional Subtopics
AUDITING AND REPORTING
The module provides cmdlets that allow for the auditing of various security
aspects of Microsoft 365 environments, including user MFA status,
administrative role licenses, and more. The results can be exported and
analyzed to ensure compliance with CIS benchmarks.
DATA SYNCHRONIZATION
The module includes functionality to synchronize audit results with CIS
benchmark data stored in Excel sheets. This ensures that the documentation
is always up-to-date with the latest audit findings.
EXAMPLES EXAMPLES
PS C:\> {{ add examples here }} # Example 1: Performing a security audit based on CIS benchmarks
$auditResults = Invoke-M365SecurityAudit -TenantAdminUrl "https://contoso-admin.sharepoint.com"
# Example 2: Exporting a security audit table to a CSV file
Export-M365SecurityAuditTable -ExportAllTests -AuditResults $auditResults -ExportPath "C:\temp" -ExportOriginalTests
# Example 3: Retrieving licenses for users in administrative roles
Get-AdminRoleUserLicense
# Example 4: Getting MFA status of users
Get-MFAStatus -UserId "user@domain.com"
# Example 5: Removing rows with empty status values from a CSV file
Remove-RowsWithEmptyCSVStatus -FilePath "C:\Reports\Report.xlsx" -WorksheetName "Sheet1"
# 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: NOTE
Thank you to all those who contributed to this module, by writing code, sharing opinions, and provided feedback. Ensure that you have the necessary permissions and administrative roles in
your Microsoft 365 environment to run these cmdlets. Proper configuration
and setup are required for accurate audit results.
TROUBLESHOOTING NOTE: TROUBLESHOOTING NOTE
Look out on the Github repository for issues and new releases. If you encounter any issues while using the cmdlets, ensure that your
environment meets the module prerequisites. Check for any updates or patches
that may address known bugs. For issues related to specific cmdlets, refer
to the individual help files for troubleshooting tips.
SEE ALSO SEE ALSO
- {{ Please add Project URI such as github }}} -
CIS Benchmarks
-
Microsoft 365 Security Documentation
-
PowerShell Documentation
KEYWORDS KEYWORDS
{{ Add comma separated keywords here }} - Microsoft 365
- Security Audit
- CIS Benchmarks
- Compliance
- MFA
- User Licenses
- Security Reporting

View File

@@ -39,22 +39,20 @@ function Test-OrgOnlyBypassLobby {
# Prepare failure reasons and details based on compliance # Prepare failure reasons and details based on compliance
$failureReasons = if (-not $lobbyBypassRestricted) { $failureReasons = if (-not $lobbyBypassRestricted) {
# Condition A: The `AutoAdmittedUsers` setting in the Teams meeting policy is not set to `EveryoneInCompanyExcludingGuests`. # Condition C: Verification using the Microsoft Teams admin center indicates that the meeting join & lobby settings are not configured as recommended.
"External participants can bypass the lobby" "AutoAdmittedUsers is set to $($CsTeamsMeetingPolicyLobby.AutoAdmittedUsers)"
}
else { }else {
"N/A" "N/A"
} }
$details = if ($lobbyBypassRestricted) { $details = if ($lobbyBypassRestricted) {
# Condition B: The setting for "Who can bypass the lobby" is configured to "People in my org" using the UI. # Condition B: The setting for "Who can bypass the lobby" is configured to "People in my org" using the UI.
"Only people in the organization can bypass the lobby." "Only people in the organization can bypass the lobby."
}else {
# Condition A: The `AutoAdmittedUsers` setting in the Teams meeting policy is not set to `EveryoneInCompanyExcludingGuests`.
"External participants can bypass the lobby"
} }
else {
# Condition C: Verification using the Microsoft Teams admin center indicates that the meeting join & lobby settings are not configured as recommended.
"AutoAdmittedUsers is set to $($CsTeamsMeetingPolicyLobby.AutoAdmittedUsers)"
}
# Create and populate the CISAuditResult object # Create and populate the CISAuditResult object
$params = @{ $params = @{
Rec = $recnum Rec = $recnum

View File

@@ -30,21 +30,51 @@ function Test-ReportSecurityInTeams {
$ReportSubmissionPolicy.ReportJunkToCustomizedAddress -and $ReportSubmissionPolicy.ReportJunkToCustomizedAddress -and
$ReportSubmissionPolicy.ReportNotJunkToCustomizedAddress -and $ReportSubmissionPolicy.ReportNotJunkToCustomizedAddress -and
$ReportSubmissionPolicy.ReportPhishToCustomizedAddress -and $ReportSubmissionPolicy.ReportPhishToCustomizedAddress -and
$ReportSubmissionPolicy.ReportChatMessageToCustomizedAddressEnabled $null -ne $ReportSubmissionPolicy.ReportJunkAddresses -and
$null -ne $ReportSubmissionPolicy.ReportNotJunkAddresses -and
$null -ne $ReportSubmissionPolicy.ReportPhishAddresses -and
$ReportSubmissionPolicy.ReportChatMessageToCustomizedAddressEnabled -and
-not $ReportSubmissionPolicy.ReportChatMessageEnabled
$detailsString = @"
The following settings are required for users to report security concerns in Teams:
MS Teams:
AllowSecurityEndUserReporting: True
EXO:
ReportJunkToCustomizedAddress: True
ReportNotJunkToCustomizedAddress: True
ReportPhishToCustomizedAddress: True
ReportJunkAddresses: <security@contoso.com>
ReportNotJunkAddresses: <security@contoso.com>
ReportPhishAddresses: <security@contoso.com>
ReportChatMessageEnabled: False
ReportChatMessageToCustomizedAddressEnabled: True
"@
$faildetailstring = "Users cannot report security concerns in Teams due to one or more of the found incorrect settings:`n`n" +
"MSTeams: `nAllowSecurityEndUserReporting: $($CsTeamsMessagingPolicy.AllowSecurityEndUserReporting); `n`n" +
"EXO: `nReportJunkToCustomizedAddress: $($ReportSubmissionPolicy.ReportJunkToCustomizedAddress); `n" +
"ReportNotJunkToCustomizedAddress: $($ReportSubmissionPolicy.ReportNotJunkToCustomizedAddress); `n" +
"ReportPhishToCustomizedAddress: $($ReportSubmissionPolicy.ReportPhishToCustomizedAddress); `n" +
"ReportJunkAddresses: $($ReportSubmissionPolicy.ReportJunkAddresses -join ', '); `n" +
"ReportNotJunkAddresses: $($ReportSubmissionPolicy.ReportNotJunkAddresses -join ', '); `n" +
"ReportPhishAddresses: $($ReportSubmissionPolicy.ReportPhishAddresses -join ', '); `n" +
"ReportChatMessageEnabled: $($ReportSubmissionPolicy.ReportChatMessageEnabled); `n" +
"ReportChatMessageToCustomizedAddressEnabled: $($ReportSubmissionPolicy.ReportChatMessageToCustomizedAddressEnabled); "
# Prepare failure reasons and details based on compliance # Prepare failure reasons and details based on compliance
$failureReasons = if (-not $securityReportEnabled) { $failureReasons = if (-not $securityReportEnabled) {
"Users cannot report security concerns in Teams due to one or more incorrect settings" $detailsString
} }
else { else {
"N/A" "N/A"
} }
$details = if ($securityReportEnabled) {
$details = "AllowSecurityEndUserReporting: $($CsTeamsMessagingPolicy.AllowSecurityEndUserReporting); " + "Users can report security concerns in Teams."
"ReportJunkToCustomizedAddress: $($ReportSubmissionPolicy.ReportJunkToCustomizedAddress); " + }
"ReportNotJunkToCustomizedAddress: $($ReportSubmissionPolicy.ReportNotJunkToCustomizedAddress); " + else {
"ReportPhishToCustomizedAddress: $($ReportSubmissionPolicy.ReportPhishToCustomizedAddress); " + $faildetailstring
"ReportChatMessageToCustomizedAddressEnabled: $($ReportSubmissionPolicy.ReportChatMessageToCustomizedAddressEnabled)" }
# Create and populate the CISAuditResult object # Create and populate the CISAuditResult object
$params = @{ $params = @{

View File

@@ -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
}
}
}