├── Image └── logo.jpg ├── CODE_OF_CONDUCT.md ├── RunCAMPReport.ps1 ├── Outputs └── output-json.ps1 ├── LICENSE ├── SUPPORT.md ├── Utilities ├── CCValidationUtility.ps1 ├── IPValidationUtility.ps1 ├── IRMValidationUtility.ps1 ├── RMValidationUtility.ps1 ├── IGValidationUtility.ps1 └── DLPValidationUtility.ps1 ├── Templates └── NewDLPPolicyTemplate.txt ├── SECURITY.md ├── Checks ├── check-ComplianceManager.ps1 ├── check-DLP.ps1 ├── check-IRM102.ps1 ├── check-IRM103.ps1 ├── check-IP103.ps1 ├── check-RM102.ps1 ├── check-IG102.ps1 ├── check-IG101.ps1 ├── check-RM101.ps1 ├── check-CC102.ps1 ├── check-Audit101.ps1 ├── check-eDiscovery102.ps1 ├── check-CC103.ps1 ├── check-eDiscovery101.ps1 ├── check-Audit102.ps1 ├── check-IP102.ps1 ├── check-CC101.ps1 ├── check-IP104.ps1 └── check-IP101.ps1 ├── .gitignore ├── Remediation └── RemediationAction.ps1 └── README.md /Image/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/CAMP/HEAD/Image/logo.jpg -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | -------------------------------------------------------------------------------- /RunCAMPReport.ps1: -------------------------------------------------------------------------------- 1 | Remove-Module MCCAPreview -ErrorAction SilentlyContinue 2 | Remove-Module ExchangeOnlineManagement -ErrorAction SilentlyContinue 3 | Unblock-File ".\*" 4 | Unblock-File ".\Checks\*" 5 | Unblock-File ".\Outputs\*" 6 | Unblock-File ".\Remediation\*" 7 | Unblock-File ".\Utilities\*" 8 | 9 | Import-Module .\CAMP.psm1 10 | 11 | 12 | #Get-CAMPReport -Geo @("nam") -Solution @("num") 13 | 14 | #Get-CAMPReport -ExchangeEnvironmentName O365USGovGCCHigh 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Outputs/output-json.ps1: -------------------------------------------------------------------------------- 1 | using module "..\CAMP.psm1" 2 | 3 | class json : CAMPOutput 4 | { 5 | 6 | $OutputDirectory=$null 7 | 8 | json() 9 | { 10 | $this.Name="JSON" 11 | } 12 | 13 | RunOutput($Checks,$Collection) 14 | { 15 | 16 | # Write to file 17 | 18 | if($null -eq $this.OutputDirectory) 19 | { 20 | $OutputDir = $this.DefaultOutputDirectory 21 | } 22 | else 23 | { 24 | $OutputDir = $this.OutputDirectory 25 | } 26 | 27 | $Tenant = $(($Collection["AcceptedDomains"] | Where-Object {$_.InitialDomain -eq $True}).DomainName -split '\.')[0] 28 | $ReportFileName = "CAMP-$($tenant)-$(Get-Date -Format 'yyyyMMddHHmm').json" 29 | 30 | $OutputFile = "$OutputDir\$ReportFileName" 31 | 32 | $Result = New-Object -TypeName PSObject -Property @{ 33 | ResultDate=$(Get-Date -format s) 34 | Tenant=$Tenant 35 | Results=$Checks 36 | } 37 | 38 | $Result | ConvertTo-Json -Depth 100 | Out-File -FilePath $OutputFile 39 | 40 | $this.Completed = $True 41 | $this.Result = $OutputFile 42 | 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /SUPPORT.md: -------------------------------------------------------------------------------- 1 | # TODO: The maintainer of this repo has not yet edited this file 2 | 3 | **REPO OWNER**: Do you want Customer Service & Support (CSS) support for this product/project? 4 | 5 | - **No CSS support:** Fill out this template with information about how to file issues and get help. 6 | - **Yes CSS support:** Fill out an intake form at [aka.ms/onboardsupport](https://aka.ms/onboardsupport). CSS will work with/help you to determine next steps. 7 | - **Not sure?** Fill out an intake as though the answer were "Yes". CSS will help you decide. 8 | 9 | *Then remove this first heading from this SUPPORT.MD file before publishing your repo.* 10 | 11 | # Support 12 | 13 | ## How to file issues and get help 14 | 15 | This project uses GitHub Issues to track bugs and feature requests. Please search the existing 16 | issues before filing new issues to avoid duplicates. For new issues, file your bug or 17 | feature request as a new Issue. 18 | 19 | For help and questions about using this project, please **REPO MAINTAINER: INSERT INSTRUCTIONS HERE 20 | FOR HOW TO ENGAGE REPO OWNERS OR COMMUNITY FOR HELP. COULD BE A STACK OVERFLOW TAG OR OTHER 21 | CHANNEL. WHERE WILL YOU HELP PEOPLE?**. 22 | 23 | ## Microsoft Support Policy 24 | 25 | Support for this **PROJECT or PRODUCT** is limited to the resources listed above. 26 | -------------------------------------------------------------------------------- /Utilities/CCValidationUtility.ps1: -------------------------------------------------------------------------------- 1 | 2 | using module "..\CAMP.psm1" 3 | <# 4 | This function returns list of parent labels and sublabels 5 | #> 6 | 7 | Function Get-RoleGroupwithMembers { 8 | Param( 9 | $RoleGroups, 10 | $LogFile, 11 | $Role 12 | ) 13 | 14 | $ConfigObjectList = @() 15 | try { 16 | $RoleGroupName = "" 17 | if ( $null -eq $RoleGroups) { 18 | $ConfigObject = [CAMPCheckConfig]::new() 19 | $ConfigObject.ConfigItem = "$Role" 20 | $ConfigObject.ConfigData = "No Role Group with any Members" 21 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Fail") 22 | $ConfigObjectList += $ConfigObject 23 | } 24 | else { 25 | foreach ($RoleGroup in $RoleGroups ) { 26 | if ($RoleGroupName -ne "") { 27 | $RoleGroupName += ", $($RoleGroup.Name)" 28 | } 29 | else { 30 | $RoleGroupName = $($RoleGroup.Name) 31 | } 32 | } 33 | $ConfigObject = [CAMPCheckConfig]::new() 34 | $ConfigObject.ConfigItem = "$Role" 35 | $ConfigObject.ConfigData = $($RoleGroupName) 36 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Pass") 37 | $ConfigObjectList += $ConfigObject 38 | } 39 | } 40 | catch { 41 | Write-Host "Error:$(Get-Date) There was an issue while running CAMP. Please try running the tool again after some time." -ForegroundColor:Red 42 | $ErrorMessage = $_.ToString() 43 | $StackTraceInfo = $_.ScriptStackTrace 44 | Write-Log -IsError -ErrorMessage $ErrorMessage -StackTraceInfo $StackTraceInfo -LogFile $LogFile -ErrorAction:SilentlyContinue 45 | } 46 | return $ConfigObjectList 47 | } 48 | 49 | -------------------------------------------------------------------------------- /Templates/NewDLPPolicyTemplate.txt: -------------------------------------------------------------------------------- 1 | #Attributes for Policy
2 | $PolicyName = '';
3 | $params = @{
4 | 'Name' = $PolicyName
5 | 'ExchangeLocation' ='All';
6 | 'OneDriveLocation' = 'All';
7 | 'SharePointLocation' = 'All';
8 | 'TeamsLocation' = 'All';
9 | 'Mode' = 'TestWithNotifications';
10 | }
11 |
12 | 13 | #Create New Policy
14 | new-dlpcompliancepolicy @params
15 |
16 | 17 | #Low Volume Rule
18 | $LowSensitiveInfo = @() 19 |
20 | $LowRulevalue = @{
21 | 'Name' = '';
22 | 'Comment' = "Helps detect the presence of information commonly considered to be subject to the compliance";
23 | 'Policy' = $PolicyName;
24 | 'ContentContainsSensitiveInformation' = $LowSensitiveInfo
25 | 'BlockAccess' = $false;
26 | 'AccessScope'='NotInOrganization';
27 | 'Disabled'=$false;
28 | 'ReportSeverityLevel' = 'Low';
29 | 'NotifyUser'=@('SiteAdmin', 'LastModifier', 'Owner')
} 30 |
31 |
32 | 33 | #High Volume Rule
34 | $HighSensitiveInfo = @() 35 |
36 | $HighRulevalue = @{
37 | 'Name' = '';
38 | 'Comment' = "Helps detect the presence of information commonly considered to be subject to the compliance";
39 | 'Policy' = $PolicyName;
40 | 'ContentContainsSensitiveInformation' = $HighSensitiveInfo
41 | 'BlockAccess' = $false;
42 | 'ReportSeverityLevel' = 'High';
43 | 'AccessScope'='NotInOrganization';
44 | 'Disabled'=$false;
45 | 'GenerateIncidentReport'='SiteAdmin';
46 | 'IncidentReportContent'='All';
47 | 'NotifyAllowOverride'='FalsePositive,WithJustification';
48 | 'NotifyUser'=@('SiteAdmin', 'LastModifier', 'Owner')
49 | }
50 |
51 |
52 | #Create Rules for Policy
53 | New-dlpcompliancerule @HighRulevalue
54 | New-dlpcompliancerule @LowRulevalue
55 |
-------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). 40 | 41 | 42 | -------------------------------------------------------------------------------- /Utilities/IPValidationUtility.ps1: -------------------------------------------------------------------------------- 1 | 2 | using module "..\CAMP.psm1" 3 | <# 4 | This function returns list of parent labels and sublabels 5 | #> 6 | 7 | Function Get-LabelClassification { 8 | Param( 9 | $LogFile 10 | ) 11 | $SubLabels = @{} 12 | $ParentLabels = @{} 13 | $ParentSubLabelAssociation = @{} 14 | $ParentNameForSubLabelAssociation = @{} 15 | try { 16 | foreach ($LabelDefined in $Config["GetLabel"]) { 17 | $Label = $LabelDefined 18 | if ($($Label.ParentId)) { 19 | $SubLabels.add($($Label.Name), $Label) 20 | if ($ParentSubLabelAssociation.ContainsKey($($Label.ParentId))) { 21 | $ParentSubLabelAssociation[$($Label.ParentId)].Add($($Label.Name)) #+= $($Label.Name) 22 | } 23 | else { 24 | $ParentSubLabelAssociation.add($($Label.ParentId), [System.Collections.ArrayList]@()) #$($Label.Name)) 25 | $ParentSubLabelAssociation[$($Label.ParentId)].Add($($Label.Name)) 26 | } 27 | } 28 | else { 29 | $ParentLabels.add($($Label.Name), $Label) 30 | } 31 | 32 | } 33 | 34 | # Setting parent name for the parent with sublabels by creating a hash table with key as 35 | # parent guid and value as parent name. 36 | if ($($($ParentSubLabelAssociation.Keys).count) -gt 0) { 37 | foreach ($ParentGUID in $($ParentSubLabelAssociation.Keys)) { 38 | foreach ($LabelDefined in $Config["GetLabel"]) { 39 | if ($($LabelDefined.Guid) -eq $ParentGUID) { 40 | $ParentNameForSubLabelAssociation[$ParentGUID] = $LabelDefined.Name 41 | } 42 | } 43 | } 44 | } 45 | } 46 | catch { 47 | Write-Host "Error:$(Get-Date) There was an issue while running CAMP. Please try running the tool again after some time." -ForegroundColor:Red 48 | $ErrorMessage = $_.ToString() 49 | $StackTraceInfo = $_.ScriptStackTrace 50 | Write-Log -IsError -ErrorMessage $ErrorMessage -StackTraceInfo $StackTraceInfo -LogFile $LogFile -ErrorAction:SilentlyContinue 51 | } 52 | 53 | 54 | $LabelClassification = New-Object -TypeName psobject 55 | $LabelClassification | Add-Member -MemberType NoteProperty -Name sublabels -Value $SubLabels 56 | $LabelClassification | Add-Member -MemberType NoteProperty -Name parentlabels -Value $ParentLabels 57 | $LabelClassification | Add-Member -MemberType NoteProperty -Name parentsublabelassociation -Value $ParentSubLabelAssociation 58 | $LabelClassification | Add-Member -MemberType NoteProperty -Name parentnameforsublabelassociation -Value $ParentNameForSubLabelAssociation 59 | return $LabelClassification 60 | } 61 | 62 | -------------------------------------------------------------------------------- /Checks/check-ComplianceManager.ps1: -------------------------------------------------------------------------------- 1 | using module "..\CAMP.psm1" 2 | 3 | class ComplianceManager : CAMPCheck { 4 | <# 5 | 6 | 7 | #> 8 | 9 | ComplianceManager() { 10 | $this.Control = "Compliance Manager" 11 | $this.ParentArea = "Compliance Manager" 12 | $this.Area = "Compliance Manager" 13 | $this.Name = "Use Compliance Manager to manage your compliance posture" 14 | $this.PassText = "Your organization should use Compliance Manager to manage your compliance posture" 15 | $this.FailRecommendation = "Your organization should use Compliance Manager to manage your compliance posture" 16 | $this.Importance = "Compliance Manager is an end-to-end solution in the Microsoft 365 compliance center for managing and tracking compliance activities. It simplifies compliance and helps reduce risk. Compliance Manager translates complex regulatory requirements to specific controls and through compliance score, provides a quantifiable measure of compliance. It offers intuitive compliance management, a vast library of scalable assessments, and built-in automation. 17 | Its a great place to begin your compliance journey because it gives you an initial assessment of your compliance posture the first time you visit." 18 | $this.ExpandResults = $true 19 | if($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovGCCHigh") 20 | { 21 | $this.Links = @{ 22 | "Visit Compliance Manager" = "https://aka.ms/mcca-gcch-cm-compliance-manager" 23 | "Learn more about Compliance Manager" = "https://aka.ms/mcca-cm-docs-learn-more" 24 | "Compliance Manager Quickstart Guide" = "https://aka.ms/mcca-cm-docs-action" 25 | 26 | } 27 | }elseif ($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovDoD") 28 | { 29 | $this.Links = @{ 30 | "Visit Compliance Manager" = "https://aka.ms/mcca-dod-cm-compliance-manager" 31 | "Learn more about Compliance Manager" = "https://aka.ms/mcca-cm-docs-learn-more" 32 | "Compliance Manager Quickstart Guide" = "https://aka.ms/mcca-cm-docs-action" 33 | 34 | } 35 | }else 36 | { 37 | $this.Links = @{ 38 | "Visit Compliance Manager" = "https://aka.ms/mcca-cm-compliance-manager" 39 | "Learn more about Compliance Manager" = "https://aka.ms/mcca-cm-docs-learn-more" 40 | "Compliance Manager Quickstart Guide" = "https://aka.ms/mcca-cm-docs-action" 41 | 42 | } 43 | } 44 | } 45 | 46 | <# 47 | 48 | RESULTS 49 | 50 | #> 51 | 52 | GetResults($Config) { 53 | 54 | $ConfigObjectList = @() 55 | 56 | $ConfigObject = [CAMPCheckConfig]::new() 57 | 58 | $ConfigObject.SetResult([CAMPConfigLevel]::Recommendation, "Pass") 59 | $this.AddConfig($ConfigObject) 60 | $ConfigObjectList += $ConfigObject 61 | 62 | $this.Completed = $True 63 | } 64 | 65 | } 66 | 67 | -------------------------------------------------------------------------------- /Utilities/IRMValidationUtility.ps1: -------------------------------------------------------------------------------- 1 | 2 | using module "..\CAMP.psm1" 3 | <# 4 | This function returns list of parent labels and sublabels 5 | #> 6 | 7 | Function Get-IRMConfigurationPolicy { 8 | Param( 9 | $Config, 10 | $Templates, 11 | $LogFile 12 | ) 13 | $ConfigObjectList = @() 14 | try { 15 | $AnyPolicyEnabled = $false 16 | $IRMPolicy = @() 17 | foreach($Template in $templates) 18 | { 19 | $IRMPolicy += $Config["GetInsiderRiskPolicy"] | Where-Object { $_.InsiderRiskScenario -eq $Template } 20 | 21 | } 22 | 23 | foreach ($Policy in $IRMPolicy) { 24 | if ($($Policy.Mode) -eq "Enable") { 25 | if ($AnyPolicyEnabled -eq $false) { 26 | $AnyPolicyEnabled = $true 27 | } 28 | 29 | $ConfigObject = [CAMPCheckConfig]::new() 30 | $ConfigObject.Object = "Policy" 31 | $ConfigObject.ConfigItem = "$($Policy.Name)" 32 | 33 | $UsergroupsEnabled = "" 34 | $ExchangeLocation = $Policy.ExchangeLocation 35 | foreach ($Location in $ExchangeLocation) { 36 | if ($UsergroupsEnabled -eq "") { 37 | $UsergroupsEnabled += "$Location" 38 | } 39 | else { 40 | $UsergroupsEnabled += ", $Location" 41 | } 42 | } 43 | if ($($Policy.InsiderRiskScenario) -eq "HighValueEmployeeDataLeak") { 44 | $PolicyGroups = $Policy.CustomTags 45 | foreach ($PolicyGroup in $PolicyGroups) { 46 | $Group = $PolicyGroup.Split("""")#The policy group details come as string hence parsing to get group name 47 | if ($UsergroupsEnabled -eq "") { 48 | $UsergroupsEnabled += "$($Group[3])" 49 | } 50 | else { 51 | $UsergroupsEnabled += ", $($Group[3])" 52 | } 53 | } 54 | } 55 | $ConfigObject.ConfigData = "$UsergroupsEnabled" 56 | 57 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Pass") 58 | $ConfigObjectList += $ConfigObject 59 | } 60 | } 61 | 62 | if ($AnyPolicyEnabled -eq $false) { 63 | $ConfigObject = [CAMPCheckConfig]::new() 64 | $ConfigObject.Object = "Policy" 65 | $ConfigObject.ConfigItem = "No active policy defined" 66 | $ConfigObject.ConfigData = "" 67 | $ConfigObject.SetResult([CAMPConfigLevel]::OK, "Fail") 68 | $ConfigObjectList += $ConfigObject 69 | } 70 | 71 | } 72 | catch { 73 | Write-Host "Error:$(Get-Date) There was an issue while running CAMP. Please try running the tool again after some time." -ForegroundColor:Red 74 | $ErrorMessage = $_.ToString() 75 | $StackTraceInfo = $_.ScriptStackTrace 76 | Write-Log -IsError -ErrorMessage $ErrorMessage -StackTraceInfo $StackTraceInfo -LogFile $LogFile -ErrorAction:SilentlyContinue 77 | } 78 | return $ConfigObjectList 79 | } 80 | 81 | -------------------------------------------------------------------------------- /Checks/check-DLP.ps1: -------------------------------------------------------------------------------- 1 | using module "..\CAMP.psm1" 2 | 3 | class DLP : CAMPCheck { 4 | <# 5 | 6 | 7 | #> 8 | $SIT = $null 9 | $RemediationPolicyName = $null 10 | 11 | DLP($InfoParams) { 12 | $this.Control = $InfoParams["Control"] 13 | $this.ParentArea = $InfoParams["ParentArea"] 14 | $this.Area = $InfoParams["Area"] 15 | $this.Name = $InfoParams["Name"] 16 | $this.RemediationPolicyName = $InfoParams["RemediationPolicyName"] 17 | $this.PassText = $InfoParams["PassText"] 18 | $this.FailRecommendation = $InfoParams["FailRecommendation"] 19 | $this.Importance = $InfoParams["Importance"] 20 | $this.CheckType = [CheckType]::ObjectPropertyValue 21 | $this.ObjectType = "DLP Policy" 22 | $this.ItemName = "Sensitive Information Type" 23 | $this.DataType = "Remarks" 24 | $this.SIT = $InfoParams["SIT"] 25 | $this.Links = $InfoParams["Links"] 26 | 27 | } 28 | 29 | <# 30 | 31 | RESULTS 32 | 33 | #> 34 | 35 | GetResults($Config) { 36 | if (($Config["GetDlpComplianceRule"] -eq "Error") -or ($Config["GetDlpCompliancePolicy"] -eq "Error")) { 37 | $this.Completed = $false 38 | } 39 | else { 40 | if(($null -eq $($this.SIT)) -or ($($this.SIT) -eq "")) 41 | { 42 | $this.ExpandResults = $false 43 | $CheckNameDisplay = $this.RemediationPolicyName 44 | $CheckNameDisplayString = $CheckNameDisplay.Substring(5) 45 | $this.Importance += "
Note : We currently do not support SITs for DLP policies for $CheckNameDisplayString for the geolocations for which this report is generated. Please review your DLP policies to ensure you are protected.
" 46 | $ConfigObject = [CAMPCheckConfig]::new() 47 | $ConfigObject.SetResult([CAMPConfigLevel]::Recommendation, "Pass") 48 | $this.AddConfig($ConfigObject) 49 | 50 | 51 | } 52 | else 53 | { 54 | $SensitiveTypes = @{} 55 | foreach ($SIT in $this.SIT) { 56 | $SensitiveTypes[$SIT] = $null 57 | } 58 | $UtilityFiles = Get-ChildItem "$PSScriptRoot\..\Utilities" 59 | 60 | ForEach ($UtilityFile in $UtilityFiles) { 61 | . $UtilityFile.FullName 62 | } 63 | $Name = "$($this.RemediationPolicyName)" 64 | if ($Name.length -gt 60) { $Name = $Name.substring(0, 60) } 65 | 66 | $LogFile = $this.LogFile 67 | $ConfigObjectList = Get-DLPPolicyValidation -SensitiveTypes $SensitiveTypes -Config $Config -Name $Name -LogFile $LogFile 68 | Foreach ($ConfigObject in $ConfigObjectList) { 69 | $this.AddConfig($ConfigObject) 70 | } 71 | 72 | $hasRemediation = $this.Config | Where-Object { $_.RemediationAction -ne ''} 73 | if ($($hasremediation.count) -gt 0) 74 | { 75 | $this.CAMPRemediationInfo = New-Object -TypeName CAMPRemediationInfo -Property @{ 76 | RemediationAvailable = $True 77 | RemediationText = "You need to connect to Security & Compliance Center PowerShell to execute the below commands. Please follow steps defined in Connect to Security & Compliance Center PowerShell." 78 | } 79 | } 80 | $this.ExpandResults = $True 81 | } 82 | $this.Completed = $True 83 | } 84 | 85 | } 86 | 87 | } -------------------------------------------------------------------------------- /Checks/check-IRM102.ps1: -------------------------------------------------------------------------------- 1 | using module "..\CAMP.psm1" 2 | 3 | class IRM102 : CAMPCheck { 4 | <# 5 | 6 | 7 | #> 8 | 9 | IRM102() { 10 | $this.Control = "IRM-102" 11 | $this.ParentArea = "Insider Risk" 12 | $this.Area = "Insider Risk Management" 13 | $this.Name = "Create customized or use default insider risk management policies for departing employee data theft" 14 | $this.PassText = "Your organization has set up IRM policies for departing employee data theft" 15 | $this.FailRecommendation = "Your organization should set up IRM policies for departing employee data theft" 16 | $this.Importance = "Your organization should create an insider risk management policy to detect, investigate, and take action on departing employee data theft. Insider risk management in Microsoft 365 leverages an HR connector and selected indicators to alert you of any user activity related to data theft among departing employees." 17 | $this.ExpandResults = $True 18 | $this.ItemName = "Policy" 19 | $this.DataType = "User Groups" 20 | if($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovGCCHigh") 21 | { 22 | $this.Links = @{ 23 | "Getting started with Insider risk management" = "https://aka.ms/mcca-irm-docs-action" 24 | "Compliance Center - Insider Risk Management" = "https://aka.ms/mcca-gcch-irm-compliance-center" 25 | "Insider risk management policies" = "https://aka.ms/mcca-irm-docs-learn-more" 26 | } 27 | }elseif ($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovDoD") 28 | { 29 | $this.Links = @{ 30 | "Getting started with Insider risk management" = "https://aka.ms/mcca-irm-docs-action" 31 | "Compliance Center - Insider Risk Management" = "https://aka.ms/mcca-dod-irm-compliance-center" 32 | "Insider risk management policies" = "https://aka.ms/mcca-irm-docs-learn-more" 33 | } 34 | }else 35 | { 36 | $this.Links = @{ 37 | "Getting started with Insider risk management" = "https://aka.ms/mcca-irm-docs-action" 38 | "Compliance Center - Insider Risk Management" = "https://aka.ms/mcca-irm-compliance-center" 39 | "Insider risk management policies" = "https://aka.ms/mcca-irm-docs-learn-more" 40 | } 41 | } 42 | } 43 | 44 | <# 45 | 46 | RESULTS 47 | 48 | #> 49 | 50 | GetResults($Config) { 51 | if ($Config["GetInsiderRiskPolicy"] -eq "Error") { 52 | $this.Completed = $false 53 | } 54 | else { 55 | $UtilityFiles = Get-ChildItem "$PSScriptRoot\..\Utilities" 56 | 57 | ForEach ($UtilityFile in $UtilityFiles) { 58 | . $UtilityFile.FullName 59 | } 60 | 61 | $Template = "IntellectualPropertyTheft" 62 | $LogFile = $this.LogFile 63 | 64 | 65 | $ConfigObjectList = Get-IRMConfigurationPolicy -Config $Config -Templates @($Template) -LogFile $LogFile 66 | Foreach ($ConfigObject in $ConfigObjectList) { 67 | $this.AddConfig($ConfigObject) 68 | } 69 | 70 | 71 | $hasRemediation = $this.Config | Where-Object { $_.RemediationAction -ne '' } 72 | if ($($hasremediation.count) -gt 0) { 73 | $this.CAMPRemediationInfo = New-Object -TypeName CAMPRemediationInfo -Property @{ 74 | RemediationAvailable = $True 75 | RemediationText = "You need to connect to Exchange Online Center PowerShell to execute the below commands. Please follow steps defined in Connect to Exchange Online Center PowerShell." 76 | } 77 | } 78 | $this.Completed = $True 79 | } 80 | 81 | } 82 | 83 | } -------------------------------------------------------------------------------- /Checks/check-IRM103.ps1: -------------------------------------------------------------------------------- 1 | using module "..\CAMP.psm1" 2 | 3 | class IRM103 : CAMPCheck { 4 | <# 5 | 6 | 7 | #> 8 | 9 | IRM103() { 10 | $this.Control = "IRM-103" 11 | $this.ParentArea = "Insider Risk" 12 | $this.Area = "Insider Risk Management" 13 | $this.Name = "Create customized or use default insider risk management policies for data leaks" 14 | $this.PassText = "Your organization has set up IRM policies for data leaks" 15 | $this.FailRecommendation = "Your organization should set up IRM policies for data leaks" 16 | $this.Importance = "Microsoft recommends that your organization create an insider risk management policy to detect, investigate, and take action on data leaks. Data leaks can include accidental oversharing of information outside your organization or data theft with malicious intent." 17 | $this.ExpandResults = $True 18 | $this.ItemName = "Policy" 19 | $this.DataType = "User Groups" 20 | if($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovGCCHigh") 21 | { 22 | $this.Links = @{ 23 | 24 | "Getting started with Insider risk management" = "https://aka.ms/mcca-irm-docs-action" 25 | "Compliance Center - Insider Risk Management" = "https://aka.ms/mcca-gcch-irm-compliance-center" 26 | "Insider risk management policies" = "https://aka.ms/mcca-irm-docs-learn-more" 27 | } 28 | }elseif ($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovDoD") 29 | { 30 | $this.Links = @{ 31 | 32 | "Getting started with Insider risk management" = "https://aka.ms/mcca-irm-docs-action" 33 | "Compliance Center - Insider Risk Management" = "https://aka.ms/mcca-dod-irm-compliance-center" 34 | "Insider risk management policies" = "https://aka.ms/mcca-irm-docs-learn-more" 35 | } 36 | }else 37 | { 38 | $this.Links = @{ 39 | 40 | "Getting started with Insider risk management" = "https://aka.ms/mcca-irm-docs-action" 41 | "Compliance Center - Insider Risk Management" = "https://aka.ms/mcca-irm-compliance-center" 42 | "Insider risk management policies" = "https://aka.ms/mcca-irm-docs-learn-more" 43 | } 44 | } 45 | } 46 | 47 | <# 48 | 49 | RESULTS 50 | 51 | #> 52 | 53 | GetResults($Config) { 54 | if ($Config["GetInsiderRiskPolicy"] -eq "Error") { 55 | $this.Completed = $false 56 | } 57 | else { 58 | $UtilityFiles = Get-ChildItem "$PSScriptRoot\..\Utilities" 59 | 60 | ForEach ($UtilityFile in $UtilityFiles) { 61 | . $UtilityFile.FullName 62 | } 63 | #LeakOfInformation OR DisgruntledEmployeeDataLeak OR HighValueEmployeeDataLeak 64 | $Template = @("LeakOfInformation","DisgruntledEmployeeDataLeak","HighValueEmployeeDataLeak") 65 | $LogFile = $this.LogFile 66 | 67 | 68 | $ConfigObjectList = Get-IRMConfigurationPolicy -Config $Config -Templates $Template -LogFile $LogFile 69 | Foreach ($ConfigObject in $ConfigObjectList) { 70 | $this.AddConfig($ConfigObject) 71 | } 72 | 73 | 74 | $hasRemediation = $this.Config | Where-Object { $_.RemediationAction -ne '' } 75 | if ($($hasremediation.count) -gt 0) { 76 | $this.CAMPRemediationInfo = New-Object -TypeName CAMPRemediationInfo -Property @{ 77 | RemediationAvailable = $True 78 | RemediationText = "You need to connect to Exchange Online Center PowerShell to execute the below commands. Please follow steps defined in Connect to Exchange Online Center PowerShell." 79 | } 80 | } 81 | $this.Completed = $True 82 | } 83 | 84 | } 85 | 86 | } -------------------------------------------------------------------------------- /Checks/check-IP103.ps1: -------------------------------------------------------------------------------- 1 | using module "..\CAMP.psm1" 2 | 3 | class IP103 : CAMPCheck { 4 | <# 5 | 6 | 7 | #> 8 | 9 | IP103() { 10 | $this.Control = "IP-103" 11 | $this.ParentArea = "Microsoft Information Protection" 12 | $this.Area = "Information Protection" 13 | $this.Name = "Use IRM for Exchange Online" 14 | $this.PassText = "Your organization has enabled IRM for Exchange Online" 15 | $this.FailRecommendation = "Your organization should enable IRM for Exchange Online" 16 | $this.Importance = "Your organization should enable and use Azure Information Protection for Exchange Online. This configuration lets Exchange provide protection solutions, such as mail flow rules, data loss prevention policies that contain sets of conditions to filter email messages and take actions, and protection rules for Outlook clients." 17 | $this.ExpandResults = $True 18 | $this.ItemName = "IRM Configuration" 19 | $this.DataType = "Setting" 20 | if($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovGCCHigh") 21 | { 22 | $this.Links = @{ 23 | "How to configure applications for Azure Rights Management" = "https://aka.ms/mcca-ip-docs-action-ARM" 24 | "Compliance Center - Information Protection" = "https://aka.ms/mcca-gcch-ip-compliance-center" 25 | "Compliance Manager - IP Actions" = "https://aka.ms/mcca-gcch-ip-compliance-manager" 26 | } 27 | }elseif ($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovDoD") 28 | { 29 | $this.Links = @{ 30 | "How to configure applications for Azure Rights Management" = "https://aka.ms/mcca-ip-docs-action-ARM" 31 | "Compliance Center - Information Protection" = "https://aka.ms/mcca-dod-ip-compliance-center" 32 | "Compliance Manager - IP Actions" = "https://aka.ms/mcca-dod-ip-compliance-manager" 33 | } 34 | }else 35 | { 36 | $this.Links = @{ 37 | "How to configure applications for Azure Rights Management" = "https://aka.ms/mcca-ip-docs-action-ARM" 38 | "Compliance Center - Information Protection" = "https://aka.ms/mcca-ip-compliance-center" 39 | "Compliance Manager - IP Actions" = "https://aka.ms/mcca-ip-compliance-manager" 40 | } 41 | } 42 | } 43 | 44 | <# 45 | 46 | RESULTS 47 | 48 | #> 49 | 50 | GetResults($Config) { 51 | if ($Config["GetIRMConfiguration"] -eq "Error") { 52 | $this.Completed = $false 53 | } 54 | else { 55 | $ConfigObjectList = @() 56 | $IRMconfiguration = $Config["GetIRMConfiguration"] 57 | $ConfigObject = [CAMPCheckConfig]::new() 58 | $ConfigObject.Object = "IRM Configuration" 59 | $ConfigObject.ConfigItem = "AzureRMSLicensingEnabled" 60 | $ConfigObject.ConfigData = $IRMconfiguration.AzureRMSLicensingEnabled 61 | 62 | # Determine if AzureRMSLicensingEnabled is true in IRM Configuration 63 | If ($IRMconfiguration.AzureRMSLicensingEnabled -eq $true) { 64 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Pass") 65 | } 66 | Else { 67 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Fail") 68 | } 69 | $ConfigObjectList += $ConfigObject 70 | $this.AddConfig($ConfigObject) 71 | 72 | 73 | $hasRemediation = $this.Config | Where-Object { $_.RemediationAction -ne ''} 74 | if ($($hasremediation.count) -gt 0) 75 | { 76 | $this.CAMPRemediationInfo = New-Object -TypeName CAMPRemediationInfo -Property @{ 77 | RemediationAvailable = $True 78 | RemediationText = "You need to connect to Security & Compliance Center PowerShell to execute the below commands. Please follow steps defined in Connect to Security & Compliance Center PowerShell." 79 | } 80 | } 81 | $this.Completed = $True 82 | } 83 | 84 | } 85 | 86 | } -------------------------------------------------------------------------------- /Checks/check-RM102.ps1: -------------------------------------------------------------------------------- 1 | using module "..\CAMP.psm1" 2 | 3 | class RM102 : CAMPCheck { 4 | <# 5 | 6 | 7 | #> 8 | 9 | RM102() { 10 | $this.Control = "RM-102" 11 | $this.ParentArea = "Microsoft Information Governance" 12 | $this.Area = "Records Management" 13 | $this.Name = "Automatically Apply Record Labels" 14 | $this.PassText = "Your organization is using auto apply record label policies" 15 | $this.FailRecommendation = "Your organization should use auto apply record label policies" 16 | $this.Importance = "Your organization should use records management to manage regulatory, legal, and business-critical records across corporate data. You can automatically apply record labels to content that matches certain conditions." 17 | $this.ExpandResults = $True 18 | $this.CheckType = [CheckType]::ObjectPropertyValue 19 | $this.ObjectType = "Policy Name" 20 | $this.ItemName = "Labels" 21 | $this.DataType = "Remarks" 22 | if($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovGCCHigh") 23 | { 24 | $this.Links = @{ 25 | "Overview of Records" = "https://aka.ms/mcca-rm-docs-records" 26 | "Compliance Center - Records Management" = "https://aka.ms/mcca-gcch-rm-compliance-center" 27 | "Records management in Microsoft 365" = "https://aka.ms/mcca-rm-docs-records-management" 28 | "Compliance Manager - RM Actions" = "https://aka.ms/mcca-gcch-rm-compliance-manager" 29 | } 30 | }elseif ($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovDoD") 31 | { 32 | $this.Links = @{ 33 | "Overview of Records" = "https://aka.ms/mcca-rm-docs-records" 34 | "Compliance Center - Records Management" = "https://aka.ms/mcca-dod-rm-compliance-center" 35 | "Records management in Microsoft 365" = "https://aka.ms/mcca-rm-docs-records-management" 36 | "Compliance Manager - RM Actions" = "https://aka.ms/mcca-dod-rm-compliance-manager" 37 | } 38 | }else 39 | { 40 | $this.Links = @{ 41 | "Overview of Records" = "https://aka.ms/mcca-rm-docs-records" 42 | "Compliance Center - Records Management" = "https://aka.ms/mcca-rm-compliance-center" 43 | "Records management in Microsoft 365" = "https://aka.ms/mcca-rm-docs-records-management" 44 | "Compliance Manager - RM Actions" = "https://aka.ms/mcca-rm-compliance-manager" 45 | } 46 | } 47 | } 48 | 49 | <# 50 | 51 | RESULTS 52 | 53 | #> 54 | 55 | GetResults($Config) { 56 | if (($Config["GetRetentionComplianceRule"] -eq "Error") -or ($Config["GetRetentionCompliancePolicy"] -eq "Error") -or ($Config["GetComplianceTag"] -eq "Error")) { 57 | $this.Completed = $false 58 | } 59 | else { 60 | $UtilityFiles = Get-ChildItem "$PSScriptRoot\..\Utilities" 61 | 62 | ForEach ($UtilityFile in $UtilityFiles) { 63 | 64 | . $UtilityFile.FullName 65 | 66 | } 67 | 68 | $LogFile = $this.LogFile 69 | $Mode= "Auto" 70 | $ConfigObjectList = Get-RMPolicyValidation -LogFile $LogFile -Mode $Mode 71 | 72 | Foreach ($ConfigObject in $ConfigObjectList) { 73 | $this.AddConfig($ConfigObject) 74 | } 75 | 76 | 77 | 78 | $hasRemediation = $this.Config | Where-Object { $_.RemediationAction -ne ''} 79 | if ($($hasremediation.count) -gt 0) 80 | { 81 | $this.CAMPRemediationInfo = New-Object -TypeName CAMPRemediationInfo -Property @{ 82 | RemediationAvailable = $True 83 | RemediationText = "You need to connect to Security & Compliance Center PowerShell to execute the below commands. Please follow steps defined in Connect to Security & Compliance Center PowerShell." 84 | } 85 | } 86 | $this.Completed = $True 87 | 88 | } 89 | 90 | } 91 | 92 | } 93 | 94 | -------------------------------------------------------------------------------- /Checks/check-IG102.ps1: -------------------------------------------------------------------------------- 1 | using module "..\CAMP.psm1" 2 | 3 | class IG102 : CAMPCheck { 4 | <# 5 | 6 | 7 | #> 8 | 9 | IG102() { 10 | $this.Control = "IG-102" 11 | $this.ParentArea = "Microsoft Information Governance" 12 | $this.Area = "Information Governance" 13 | $this.Name = "Use Data Retention Labels and Policies" 14 | $this.PassText = "Your organization is using retention policies by publishing a retention label" 15 | $this.FailRecommendation = "Your organization should use retention policies by publishing a retention label" 16 | $this.Importance = "Your organization should apply retention labels to content when it matches specific conditions (such as containing specific keywords or types of sensitive information)." 17 | $this.ExpandResults = $True 18 | $this.CheckType = [CheckType]::ObjectPropertyValue 19 | $this.ObjectType = "Retention Policies" 20 | $this.ItemName = "Labels" 21 | $this.DataType = "Remarks" 22 | if($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovGCCHigh") 23 | { 24 | $this.Links = @{ 25 | "Learn More Overview of retention labels" = "https://aka.ms/mcca-ig-docs-learn-more" 26 | "Overview of retention policies" = "https://aka.ms/mcca-ig-docs-retention-policies" 27 | "Compliance Center - Information Governance" = "https://aka.ms/mcca-gcch-ig-compliance-center" 28 | "Compliance Manager - IG Actions" = "https://aka.ms/mcca-gcch-ig-compliance-manager" 29 | } 30 | }elseif ($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovDoD") 31 | { 32 | $this.Links = @{ 33 | "Learn More Overview of retention labels" = "https://aka.ms/mcca-ig-docs-learn-more" 34 | "Overview of retention policies" = "https://aka.ms/mcca-ig-docs-retention-policies" 35 | "Compliance Center - Information Governance" = "https://aka.ms/mcca-dod-ig-compliance-center" 36 | "Compliance Manager - IG Actions" = "https://aka.ms/mcca-dod-ig-compliance-manager" 37 | } 38 | }else 39 | { 40 | $this.Links = @{ 41 | "Learn More Overview of retention labels" = "https://aka.ms/mcca-ig-docs-learn-more" 42 | "Overview of retention policies" = "https://aka.ms/mcca-ig-docs-retention-policies" 43 | "Compliance Center - Information Governance" = "https://aka.ms/mcca-ig-compliance-center" 44 | "Compliance Manager - IG Actions" = "https://aka.ms/mcca-ig-compliance-manager" 45 | } 46 | } 47 | } 48 | 49 | <# 50 | 51 | RESULTS CC Admin, CC Analyst, CC Investigator and CC Viewer 52 | #> 53 | 54 | GetResults($Config) { 55 | if (($Config["GetRetentionComplianceRule"] -eq "Error") -or ($Config["GetRetentionCompliancePolicy"] -eq "Error")) { 56 | $this.Completed = $false 57 | } 58 | else { 59 | $UtilityFiles = Get-ChildItem "$PSScriptRoot\..\Utilities" 60 | 61 | ForEach ($UtilityFile in $UtilityFiles) { 62 | 63 | . $UtilityFile.FullName 64 | 65 | } 66 | 67 | $LogFile = $this.LogFile 68 | $Mode = "Publish" 69 | $ConfigObjectList = Get-RetentionPolicyValidation -LogFile $LogFile -Mode $Mode 70 | 71 | Foreach ($ConfigObject in $ConfigObjectList) { 72 | $this.AddConfig($ConfigObject) 73 | } 74 | 75 | 76 | 77 | $hasRemediation = $this.Config | Where-Object { $_.RemediationAction -ne ''} 78 | if ($($hasremediation.count) -gt 0) 79 | { 80 | $this.CAMPRemediationInfo = New-Object -TypeName CAMPRemediationInfo -Property @{ 81 | RemediationAvailable = $True 82 | RemediationText = "You need to connect to Security & Compliance Center PowerShell to execute the below commands. Please follow steps defined in Connect to Security & Compliance Center PowerShell." 83 | } 84 | } 85 | $this.Completed = $True 86 | 87 | } 88 | 89 | } 90 | 91 | } -------------------------------------------------------------------------------- /Checks/check-IG101.ps1: -------------------------------------------------------------------------------- 1 | using module "..\CAMP.psm1" 2 | 3 | class IG101 : CAMPCheck { 4 | <# 5 | 6 | 7 | #> 8 | 9 | IG101() { 10 | $this.Control = "IG-101" 11 | $this.ParentArea = "Microsoft Information Governance" 12 | $this.Area = "Information Governance" 13 | $this.Name = "Auto-Apply Retention Labels" 14 | $this.PassText = "Your organization is using auto-apply retention policies" 15 | $this.FailRecommendation = "Your organization should use auto-apply retention policies" 16 | $this.Importance = "Your organization should automatically apply retention labels to content when it matches specific conditions (such as containing specific keywords or types of sensitive information). Microsoft recommends that automatic labeling be implemented to decrease reliance on users for correct classification." 17 | $this.ExpandResults = $True 18 | $this.CheckType = [CheckType]::ObjectPropertyValue 19 | $this.ObjectType = "Retention Policies" 20 | $this.ItemName = "Labels" 21 | $this.DataType = "Remarks" 22 | if($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovGCCHigh") 23 | { 24 | $this.Links = @{ 25 | "Learn More Overview of retention labels" = "https://aka.ms/mcca-ig-docs-learn-more" 26 | "Overview of retention policies" = "https://aka.ms/mcca-ig-docs-retention-policies" 27 | "Compliance Center - Information Governance" = "https://aka.ms/mcca-gcch-ig-compliance-center" 28 | "Compliance Manager - IG Actions" = "https://aka.ms/mcca-gcch-ig-compliance-manager" 29 | } 30 | }elseif ($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovDoD") 31 | { 32 | $this.Links = @{ 33 | "Learn More Overview of retention labels" = "https://aka.ms/mcca-ig-docs-learn-more" 34 | "Overview of retention policies" = "https://aka.ms/mcca-ig-docs-retention-policies" 35 | "Compliance Center - Information Governance" = "https://aka.ms/mcca-dod-ig-compliance-center" 36 | "Compliance Manager - IG Actions" = "https://aka.ms/mcca-dod-ig-compliance-manager" 37 | } 38 | }else 39 | { 40 | $this.Links = @{ 41 | "Learn More Overview of retention labels" = "https://aka.ms/mcca-ig-docs-learn-more" 42 | "Overview of retention policies" = "https://aka.ms/mcca-ig-docs-retention-policies" 43 | "Compliance Center - Information Governance" = "https://aka.ms/mcca-ig-compliance-center" 44 | "Compliance Manager - IG Actions" = "https://aka.ms/mcca-ig-compliance-manager" 45 | } 46 | } 47 | } 48 | 49 | <# 50 | 51 | RESULTS CC Admin, CC Analyst, CC Investigator and CC Viewer 52 | #> 53 | 54 | GetResults($Config) { 55 | if (($Config["GetRetentionComplianceRule"] -eq "Error") -or ($Config["GetRetentionCompliancePolicy"] -eq "Error")) { 56 | $this.Completed = $false 57 | } 58 | else { 59 | $UtilityFiles = Get-ChildItem "$PSScriptRoot\..\Utilities" 60 | 61 | ForEach ($UtilityFile in $UtilityFiles) { 62 | 63 | . $UtilityFile.FullName 64 | 65 | } 66 | 67 | $LogFile = $this.LogFile 68 | $Mode = "Auto" 69 | $ConfigObjectList = Get-RetentionPolicyValidation -LogFile $LogFile -Mode $Mode 70 | 71 | Foreach ($ConfigObject in $ConfigObjectList) { 72 | $this.AddConfig($ConfigObject) 73 | } 74 | 75 | 76 | 77 | $hasRemediation = $this.Config | Where-Object { $_.RemediationAction -ne ''} 78 | if ($($hasremediation.count) -gt 0) 79 | { 80 | $this.CAMPRemediationInfo = New-Object -TypeName CAMPRemediationInfo -Property @{ 81 | RemediationAvailable = $True 82 | RemediationText = "You need to connect to Security & Compliance Center PowerShell to execute the below commands. Please follow steps defined in Connect to Security & Compliance Center PowerShell." 83 | } 84 | } 85 | $this.Completed = $True 86 | 87 | } 88 | 89 | } 90 | 91 | } -------------------------------------------------------------------------------- /Checks/check-RM101.ps1: -------------------------------------------------------------------------------- 1 | using module "..\CAMP.psm1" 2 | 3 | class RM101 : CAMPCheck { 4 | <# 5 | 6 | 7 | #> 8 | 9 | RM101() { 10 | $this.Control = "RM-101" 11 | $this.ParentArea = "Microsoft Information Governance" 12 | $this.Area = "Records Management" 13 | $this.Name = "Declare Data as Records by Creating & Publishing a Record Label" 14 | $this.PassText = "Your organization is using record labels to declare data as records" 15 | $this.FailRecommendation = "Your organization should use record labels to declare data as records" 16 | $this.Importance = "Your organization should use records management to manage regulatory, legal, and business-critical records across corporate data. By using retention labels to declare records, you can implement a single, consistent records-management strategy across all of Office 365." 17 | $this.ExpandResults = $True 18 | $this.CheckType = [CheckType]::ObjectPropertyValue 19 | $this.ObjectType = "Policy Name" 20 | $this.ItemName = "Labels" 21 | $this.DataType = "Remarks" 22 | if($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovGCCHigh") 23 | { 24 | $this.Links = @{ 25 | "Overview of Records" = "https://aka.ms/mcca-rm-docs-records" 26 | "Compliance Center - Records Management" = "https://aka.ms/mcca-gcch-rm-compliance-center" 27 | "Records management in Microsoft 365" = "https://aka.ms/mcca-rm-docs-records-management" 28 | "Compliance Manager - RM Actions" = "https://aka.ms/mcca-gcch-rm-compliance-manager" 29 | } 30 | }elseif ($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovDoD") 31 | { 32 | $this.Links = @{ 33 | "Overview of Records" = "https://aka.ms/mcca-rm-docs-records" 34 | "Compliance Center - Records Management" = "https://aka.ms/mcca-dod-rm-compliance-center" 35 | "Records management in Microsoft 365" = "https://aka.ms/mcca-rm-docs-records-management" 36 | "Compliance Manager - RM Actions" = "https://aka.ms/mcca-dod-rm-compliance-manager" 37 | } 38 | }else 39 | { 40 | $this.Links = @{ 41 | "Overview of Records" = "https://aka.ms/mcca-rm-docs-records" 42 | "Compliance Center - Records Management" = "https://aka.ms/mcca-rm-compliance-center" 43 | "Records management in Microsoft 365" = "https://aka.ms/mcca-rm-docs-records-management" 44 | "Compliance Manager - RM Actions" = "https://aka.ms/mcca-rm-compliance-manager" 45 | } 46 | } 47 | } 48 | 49 | <# 50 | 51 | RESULTS 52 | 53 | #> 54 | 55 | GetResults($Config) { 56 | if (($Config["GetRetentionComplianceRule"] -eq "Error") -or ($Config["GetRetentionCompliancePolicy"] -eq "Error") -or ($Config["GetComplianceTag"] -eq "Error")) { 57 | $this.Completed = $false 58 | } 59 | else { 60 | $UtilityFiles = Get-ChildItem "$PSScriptRoot\..\Utilities" 61 | 62 | ForEach ($UtilityFile in $UtilityFiles) { 63 | 64 | . $UtilityFile.FullName 65 | 66 | } 67 | 68 | $LogFile = $this.LogFile 69 | $Mode= "Publish" 70 | $ConfigObjectList = Get-RMPolicyValidation -LogFile $LogFile -Mode $Mode 71 | 72 | Foreach ($ConfigObject in $ConfigObjectList) { 73 | $this.AddConfig($ConfigObject) 74 | } 75 | 76 | 77 | 78 | $hasRemediation = $this.Config | Where-Object { $_.RemediationAction -ne ''} 79 | if ($($hasremediation.count) -gt 0) 80 | { 81 | $this.CAMPRemediationInfo = New-Object -TypeName CAMPRemediationInfo -Property @{ 82 | RemediationAvailable = $True 83 | RemediationText = "You need to connect to Security & Compliance Center PowerShell to execute the below commands. Please follow steps defined in Connect to Security & Compliance Center PowerShell." 84 | } 85 | } 86 | $this.Completed = $True 87 | 88 | } 89 | 90 | } 91 | 92 | } 93 | 94 | -------------------------------------------------------------------------------- /Checks/check-CC102.ps1: -------------------------------------------------------------------------------- 1 | using module "..\CAMP.psm1" 2 | 3 | class CC102 : CAMPCheck { 4 | <# 5 | 6 | 7 | #> 8 | 9 | CC102() { 10 | $this.Control = "CC-102" 11 | $this.ParentArea = "Insider Risk" 12 | $this.Area = "Communication Compliance" 13 | $this.Name = "Monitor Communications for Offensive or Threatening Language" 14 | $this.PassText = "Your organization has defined policies to monitor internal communications" 15 | $this.FailRecommendation = "Your organization should define policies to monitor internal communications" 16 | $this.Importance = "Your organization should use communication compliance to monitor internal communication for offensive and threatening language. You can create a policy that uses pretrained classifier to detect content containing profanities or language that might be considered threatening or harrassment." 17 | $this.ExpandResults = $True 18 | $this.ItemName = "Policy" 19 | $this.DataType = "Policy Status" 20 | if($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovGCCHigh") 21 | { 22 | $this.Links = @{ 23 | "Communication compliance in Microsoft 365" = "https://aka.ms/mcca-cc-docs-learn-more" 24 | "Compliance Center - Communication Compliance" = "https://aka.ms/mcca-gcch-cc-compliance-center" 25 | "Compliance Manager - CC Actions" = "https://aka.ms/mcca-gcch-cc-compliance-manager" 26 | } 27 | }elseif ($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovDoD") 28 | { 29 | $this.Links = @{ 30 | "Communication compliance in Microsoft 365" = "https://aka.ms/mcca-cc-docs-learn-more" 31 | "Compliance Center - Communication Compliance" = "https://aka.ms/mcca-dod-cc-compliance-center" 32 | "Compliance Manager - CC Actions" = "https://aka.ms/mcca-dod-cc-compliance-manager" 33 | } 34 | }else 35 | { 36 | $this.Links = @{ 37 | "Communication compliance in Microsoft 365" = "https://aka.ms/mcca-cc-docs-learn-more" 38 | "Compliance Center - Communication Compliance" = "https://aka.ms/mcca-cc-compliance-center" 39 | "Compliance Manager - CC Actions" = "https://aka.ms/mcca-cc-compliance-manager" 40 | 41 | } 42 | } 43 | } 44 | 45 | <# 46 | 47 | RESULTS CC Admin, CC Analyst, CC Investigator and CC Viewer 48 | #> 49 | 50 | GetResults($Config) { 51 | if ($Config["GetSupervisoryReviewPolicyV2"] -eq "Error") { 52 | $this.Completed = $false 53 | } 54 | else { 55 | $ConfigObjectList = @() 56 | $PolicyExists = $False 57 | ForEach ($Policy in $Config["GetSupervisoryReviewPolicyV2"]) { 58 | $PolicyExists = $True 59 | $ConfigObject = [CAMPCheckConfig]::new() 60 | $ConfigObject.ConfigItem = "$($Policy.Name)" 61 | $ConfigObject.ConfigData = $($Policy.PolicyStatus) 62 | if ($($Policy.PolicyStatus) -ieq "Active") { 63 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Pass") 64 | } 65 | else { 66 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Fail") 67 | 68 | } 69 | $ConfigObjectList += $ConfigObject 70 | $this.AddConfig($ConfigObject) 71 | 72 | } 73 | 74 | If ($PolicyExists -eq $False) { 75 | $ConfigObject = [CAMPCheckConfig]::new() 76 | 77 | $ConfigObject.ConfigItem = "No Active Policy Defined" 78 | $ConfigObject.ConfigData = "No Active Policy Defined" 79 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Fail") 80 | $ConfigObjectList += $ConfigObject 81 | $this.AddConfig($ConfigObject) 82 | } 83 | 84 | $hasRemediation = $this.Config | Where-Object { $_.RemediationAction -ne ''} 85 | if ($($hasremediation.count) -gt 0) 86 | { 87 | $this.CAMPRemediationInfo = New-Object -TypeName CAMPRemediationInfo -Property @{ 88 | RemediationAvailable = $True 89 | RemediationText = "You need to connect to Security & Compliance Center PowerShell to execute the below commands. Please follow steps defined in Connect to Security & Compliance Center PowerShell." 90 | } 91 | } 92 | $this.Completed = $True 93 | } 94 | } 95 | 96 | } -------------------------------------------------------------------------------- /Checks/check-Audit101.ps1: -------------------------------------------------------------------------------- 1 | using module "..\CAMP.psm1" 2 | 3 | class Audit101 : CAMPCheck { 4 | <# 5 | 6 | 7 | #> 8 | 9 | Audit101() { 10 | 11 | $this.Control = "Audit-101" 12 | $this.ParentArea = "Discovery & Response" 13 | $this.Area = "Audit" 14 | $this.Name = "Enable Auditing in Office 365" 15 | $this.PassText = "Your organisation has enabled auditing for your Office 365 tenant" 16 | $this.FailRecommendation = "Your organization should enable auditing for your Office 365 tenant" 17 | $this.Importance = "Your organization should enable auditing for your Office 365 tenant. When audit log search in the Security & Compliance Center is turned on, user and admin activity from your organization is recorded in the audit log and retained for 90 days, and up to one year depending on the license assigned to users." 18 | $this.ExpandResults = $True 19 | $this.ItemName = "Configuration" 20 | $this.DataType = "Setting" 21 | if($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovGCCHigh") 22 | { 23 | $this.Links = @{ 24 | "How to search Audit Log" = "https://aka.ms/mcca-aa-docs-action-audit-log" 25 | "Advanced Audit" = "https://aka.ms/mcca-aa-docs-learn-more-audit" 26 | "Compliance Center - Audit Log search" = "https://aka.ms/mcca-gcch-aa-compliance-center" 27 | "Compliance Manager - Audit Actions" = "https://aka.ms/mcca-gcch-aa-compliance-manager" 28 | } 29 | }elseif ($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovDoD") 30 | { 31 | $this.Links = @{ 32 | "How to search Audit Log" = "https://aka.ms/mcca-aa-docs-action-audit-log" 33 | "Advanced Audit" = "https://aka.ms/mcca-aa-docs-learn-more-audit" 34 | "Compliance Center - Audit Log search" = "https://aka.ms/mcca-dod-aa-compliance-center" 35 | "Compliance Manager - Audit Actions" = "https://aka.ms/mcca-dod-aa-compliance-manager" 36 | } 37 | }else 38 | { 39 | $this.Links = @{ 40 | "How to search Audit Log" = "https://aka.ms/mcca-aa-docs-action-audit-log" 41 | "Advanced Audit" = "https://aka.ms/mcca-aa-docs-learn-more-audit" 42 | "Compliance Center - Audit Log search" = "https://aka.ms/mcca-aa-compliance-center" 43 | "Compliance Manager - Audit Actions" = "https://aka.ms/mcca-aa-compliance-manager" 44 | } 45 | } 46 | 47 | } 48 | 49 | <# 50 | 51 | RESULTS 52 | 53 | #> 54 | 55 | GetResults($Config) { 56 | if ($Config["GetAdminAuditLogConfig"] -eq "Error") { 57 | $this.Completed = $false 58 | } 59 | else { 60 | $ConfigObjectList = @() 61 | $Auditconfiguration = $Config["GetAdminAuditLogConfig"] 62 | $ConfigObject = [CAMPCheckConfig]::new() 63 | $ConfigObject.Object = "Configuration" 64 | $ConfigObject.ConfigItem = "Auditing in Office 365" 65 | 66 | # Determine if UnifiedAuditLogIngestionEnabled is true in Audit Configuration 67 | If ($($Auditconfiguration.UnifiedAuditLogIngestionEnabled) -eq $true) { 68 | $ConfigObject.ConfigData = "Enabled" 69 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Pass") 70 | } 71 | Else { 72 | $ConfigObject.ConfigData = "Disabled" 73 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Fail") 74 | $ConfigObject.RemediationAction = "Set-AdminAuditLogConfig -UnifiedAuditLogIngestionEnabled " + "$" + "true" 75 | Write-Host "$(Get-Date) Generating Remediation Action to enable Auditing" -ForegroundColor Yellow 76 | 77 | } 78 | 79 | $this.AddConfig($ConfigObject) 80 | $ConfigObjectList += $ConfigObject 81 | $hasRemediation = $this.Config | Where-Object { $_.RemediationAction -ne ''} 82 | if ($($hasremediation.count) -gt 0) 83 | { 84 | $this.CAMPRemediationInfo = New-Object -TypeName CAMPRemediationInfo -Property @{ 85 | RemediationAvailable = $True 86 | RemediationText = "You need to connect to Exchange Online Center PowerShell to execute the below commands. Please follow steps defined in Connect to Exchange Online Center PowerShell." 87 | } 88 | } 89 | $this.Completed = $True 90 | } 91 | 92 | } 93 | 94 | } -------------------------------------------------------------------------------- /Checks/check-eDiscovery102.ps1: -------------------------------------------------------------------------------- 1 | using module "..\CAMP.psm1" 2 | 3 | class eDiscovery102 : CAMPCheck { 4 | <# 5 | 6 | 7 | #> 8 | 9 | eDiscovery102() { 10 | $this.Control = "eDiscovery-102" 11 | $this.ParentArea = "Discovery & Response" 12 | $this.Area = "eDiscovery" 13 | $this.Name = "Use Advanced eDiscovery Cases to Support Legal Investigations" 14 | $this.PassText = "Your organization is using Advanced eDiscovery cases to support legal investigations" 15 | $this.FailRecommendation = "Your organization needs to review (or set up) Advanced eDiscovery cases" 16 | $this.Importance = "Your organization should use Advanced eDiscovery to manage the end-to-end workflow to preserve, collect, review, analyze, and export content that's responsive to your organization's internal and external investigations." 17 | $this.ExpandResults = $True 18 | $this.ItemName = "Case Name" 19 | $this.DataType = "Case Status" 20 | if($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovGCCHigh") 21 | { 22 | $this.Links = @{ 23 | "Get started with Advanced eDiscovery" = "https://aka.ms/mcca-aed-docs-action" 24 | "Compliance Center - Advanced eDiscovery" = "https://aka.ms/mcca-gcch-aed-compliance-center" 25 | "eDiscovery in Microsoft 365" = "https://aka.ms/mcca-aed-docs-learn-more" 26 | "Compliance Manager - eDiscovery" = "https://aka.ms/mcca-gcch-aed-compliance-manager" 27 | } 28 | }elseif ($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovDoD") 29 | { 30 | $this.Links = @{ 31 | "Get started with Advanced eDiscovery" = "https://aka.ms/mcca-aed-docs-action" 32 | "Compliance Center - Advanced eDiscovery" = "https://aka.ms/mcca-dod-aed-compliance-center" 33 | "eDiscovery in Microsoft 365" = "https://aka.ms/mcca-aed-docs-learn-more" 34 | "Compliance Manager - eDiscovery" = "https://aka.ms/mcca-dod-aed-compliance-manager" 35 | } 36 | }else 37 | { 38 | $this.Links = @{ 39 | "Get started with Advanced eDiscovery" = "https://aka.ms/mcca-aed-docs-action" 40 | "Compliance Center - Advanced eDiscovery" = "https://aka.ms/mcca-aed-compliance-center" 41 | "eDiscovery in Microsoft 365" = "https://aka.ms/mcca-aed-docs-learn-more" 42 | } 43 | } 44 | } 45 | 46 | <# 47 | 48 | RESULTS 49 | 50 | #> 51 | 52 | GetResults($Config) { 53 | if ($Config["GetComplianceCase"] -eq "Error") { 54 | $this.Completed = $false 55 | } 56 | else { 57 | $ConfigObjectList = @() 58 | 59 | $CasesPresent= $false 60 | $activecasepresent = $false 61 | ForEach ($CasesDefined in $Config["GetComplianceCase"]|Where-Object{$_.CaseType -eq "AdvancedEdiscovery"}) { 62 | $Cases = $CasesDefined 63 | $CasesPresent= $true 64 | 65 | if($($Cases.Status) -eq "Active") 66 | { 67 | $ConfigObject = [CAMPCheckConfig]::new() 68 | $ConfigObject.ConfigItem = "$($Cases.Name)" 69 | $ConfigObject.ConfigData = "$($Cases.Status)" 70 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Fail") 71 | $this.AddConfig($ConfigObject) 72 | $ConfigObjectList += $ConfigObject 73 | $activecasepresent= $true 74 | } 75 | $CasesPresent= $true 76 | } 77 | if(($activecasepresent -eq $false) -and ($CasesPresent -eq $true)) 78 | { 79 | $ConfigObject = [CAMPCheckConfig]::new() 80 | $ConfigObject.ConfigItem = "No active case" 81 | $ConfigObject.ConfigData = "" 82 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Pass") 83 | $this.AddConfig($ConfigObject) 84 | $ConfigObjectList += $ConfigObject 85 | } 86 | elseif($CasesPresent -eq $false) 87 | { 88 | $ConfigObject = [CAMPCheckConfig]::new() 89 | $ConfigObject.ConfigItem = "No eDiscovery cases found" 90 | $ConfigObject.ConfigData = "" 91 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Fail") 92 | $this.AddConfig($ConfigObject) 93 | $ConfigObjectList += $ConfigObject 94 | } 95 | 96 | $hasRemediation = $this.Config | Where-Object { $_.RemediationAction -ne ''} 97 | if ($($hasremediation.count) -gt 0) 98 | { 99 | $this.CAMPRemediationInfo = New-Object -TypeName CAMPRemediationInfo -Property @{ 100 | RemediationAvailable = $True 101 | RemediationText = "You need to connect to Security & Compliance Center PowerShell to execute the below commands. Please follow steps defined in Connect to Security & Compliance Center PowerShell." 102 | } 103 | } 104 | $this.Completed = $True 105 | } 106 | }} 107 | -------------------------------------------------------------------------------- /Checks/check-CC103.ps1: -------------------------------------------------------------------------------- 1 | using module "..\CAMP.psm1" 2 | 3 | class CC103 : CAMPCheck { 4 | <# 5 | 6 | 7 | #> 8 | 9 | CC103() { 10 | $this.Control = "CC-103" 11 | $this.ParentArea = "Insider Risk" 12 | $this.Area = "Communication Compliance" 13 | $this.Name = "Remediate Corporate Policy Violation" 14 | $this.PassText = "Your organization currently has no corporate policy violations" 15 | $this.FailRecommendation = "Your organization needs to remediate corporate policy violations" 16 | $this.Importance = "Your organization should use communication compliance to scan internal and external communications for policy matches so they can be examined by designated reviewers. Reviewers can investigate scanned communications and take appropriate remediation actions." 17 | $this.ExpandResults = $True 18 | $this.ItemName = "Communication Compliance Remediation" 19 | $this.DataType = "Items pending Review" 20 | if($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovGCCHigh") 21 | { 22 | $this.Links = @{ 23 | "Communication compliance in Microsoft 365" = "https://aka.ms/mcca-cc-docs-learn-more" 24 | "Compliance Center - Communication Compliance" = "https://aka.ms/mcca-gcch-cc-compliance-center" 25 | "Compliance Manager - CC Actions" = "https://aka.ms/mcca-gcch-cc-compliance-manager" 26 | } 27 | }elseif ($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovDoD") 28 | { 29 | $this.Links = @{ 30 | "Communication compliance in Microsoft 365" = "https://aka.ms/mcca-cc-docs-learn-more" 31 | "Compliance Center - Communication Compliance" = "https://aka.ms/mcca-dod-cc-compliance-center" 32 | "Compliance Manager - CC Actions" = "https://aka.ms/mcca-dod-cc-compliance-manager" 33 | } 34 | }else 35 | { 36 | $this.Links = @{ 37 | "Communication compliance in Microsoft 365" = "https://aka.ms/mcca-cc-docs-learn-more" 38 | "Compliance Center - Communication Compliance" = "https://aka.ms/mcca-cc-compliance-center" 39 | "Compliance Manager - CC Actions" = "https://aka.ms/mcca-cc-compliance-manager" 40 | 41 | } 42 | } 43 | } 44 | 45 | <# 46 | 47 | RESULTS CC Admin, CC Analyst, CC Investigator and CC Viewer 48 | #> 49 | 50 | GetResults($Config) { 51 | if (($Config["GetSupervisoryReviewOverallProgressReport"] -eq "Error") -or ($Config["GetSupervisoryReviewPolicyV2"] -eq "Error")) { 52 | $this.Completed = $false 53 | } 54 | else { 55 | $ConfigObjectList = @() 56 | $SupervisoryReviewOverallProgressReport = $Config["GetSupervisoryReviewOverallProgressReport"] 57 | if ( $null -eq $SupervisoryReviewOverallProgressReport) { 58 | $ConfigObject = [CAMPCheckConfig]::new() 59 | $ConfigObject.ConfigItem = "Communication Compliance Policy Matches" 60 | 61 | $supervisory = $Config["GetSupervisoryReviewPolicyV2"] 62 | 63 | if ($($supervisory.count) -eq 0) { 64 | $ConfigObject.ConfigData = "No communication Policy defined" 65 | } 66 | else { 67 | $ConfigObject.ConfigData = "User does not have access to policy review" 68 | } 69 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Fail") 70 | $ConfigObjectList += $ConfigObject 71 | $this.AddConfig($ConfigObject) 72 | 73 | } 74 | elseif ($($SupervisoryReviewOverallProgressReport.Pending) -eq 0) { 75 | $ConfigObject = [CAMPCheckConfig]::new() 76 | $ConfigObject.ConfigItem = "Communication Compliance Policy Matches" 77 | $ConfigObject.ConfigData = "None" 78 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Pass") 79 | $ConfigObjectList += $ConfigObject 80 | $this.AddConfig($ConfigObject) 81 | 82 | } 83 | 84 | else { 85 | $ConfigObject = [CAMPCheckConfig]::new() 86 | $ConfigObject.ConfigItem = "Communication Compliance Policy Matches" 87 | $ConfigObject.ConfigData = "$($SupervisoryReviewOverallProgressReport.Pending)" 88 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Fail") 89 | $ConfigObjectList += $ConfigObject 90 | $this.AddConfig($ConfigObject) 91 | 92 | } 93 | 94 | $hasRemediation = $this.Config | Where-Object { $_.RemediationAction -ne ''} 95 | if ($($hasremediation.count) -gt 0) 96 | { 97 | $this.CAMPRemediationInfo = New-Object -TypeName CAMPRemediationInfo -Property @{ 98 | RemediationAvailable = $True 99 | RemediationText = "You need to connect to Security & Compliance Center PowerShell to execute the below commands. Please follow steps defined in Connect to Security & Compliance Center PowerShell." 100 | } 101 | } 102 | $this.Completed = $True 103 | } 104 | } 105 | 106 | } -------------------------------------------------------------------------------- /Checks/check-eDiscovery101.ps1: -------------------------------------------------------------------------------- 1 | using module "..\CAMP.psm1" 2 | 3 | class eDiscovery101 : CAMPCheck { 4 | <# 5 | 6 | 7 | #> 8 | 9 | eDiscovery101() { 10 | $this.Control = "eDiscovery-101" 11 | $this.ParentArea = "Discovery & Response" 12 | $this.Area = "eDiscovery" 13 | $this.Name = "Use Core eDiscovery Cases to Support Legal Investigations" 14 | $this.PassText = "Your organization is using Core eDiscovery cases to support legal investigations" 15 | $this.FailRecommendation = "Your organization needs to review (or set up) Core eDiscovery cases" 16 | $this.Importance = "Your organization should use Core eDiscovery cases to identify, hold, and export content found in Exchange Online mailboxes, Microsoft 365 Groups, Microsoft Teams, SharePoint Online and OneDrive for Business sites, and Skype for Business conversations, and Yammer teams." 17 | $this.ExpandResults = $True 18 | $this.ItemName = "Case Name" 19 | $this.DataType = "Case Status" 20 | if($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovGCCHigh") 21 | { 22 | $this.Links = @{ 23 | "Get started with Core eDiscovery" = "https://aka.ms/mcca-ced-docs-action" 24 | "Compliance Center - Core eDiscovery" = "https://aka.ms/mcca-gcch-ced-compliance-center" 25 | "eDiscovery in Microsoft 365" = "https://aka.ms/mcca-aed-docs-learn-more" 26 | "Compliance Manager - eDiscovery" = "https://aka.ms/mcca-gcch-aed-compliance-manager" 27 | } 28 | }elseif ($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovDoD") 29 | { 30 | $this.Links = @{ 31 | "Get started with Core eDiscovery" = "https://aka.ms/mcca-ced-docs-action" 32 | "Compliance Center - Core eDiscovery" = "https://aka.ms/mcca-dod-ced-compliance-center" 33 | "eDiscovery in Microsoft 365" = "https://aka.ms/mcca-aed-docs-learn-more" 34 | "Compliance Manager - eDiscovery" = "https://aka.ms/mcca-dod-aed-compliance-manager" 35 | } 36 | }else 37 | { 38 | $this.Links = @{ 39 | "Get started with Core eDiscovery" = "https://aka.ms/mcca-ced-docs-action" 40 | "Compliance Center - Core eDiscovery" = "https://aka.ms/mcca-ced-compliance-center" 41 | "eDiscovery in Microsoft 365" = "https://aka.ms/mcca-aed-docs-learn-more" 42 | } 43 | } 44 | } 45 | 46 | <# 47 | 48 | RESULTS 49 | 50 | #> 51 | 52 | GetResults($Config) { 53 | if ($Config["GetComplianceCaseCore"] -eq "Error") { 54 | $this.Completed = $false 55 | } 56 | else { 57 | $ConfigObjectList = @() 58 | 59 | $CasesPresent= $false 60 | $activecasepresent = $false 61 | ForEach ($CasesDefined in $Config["GetComplianceCaseCore"]) { 62 | $Cases = $CasesDefined 63 | $CasesPresent= $true 64 | 65 | if($($Cases.Status) -eq "Active") 66 | { 67 | $ConfigObject = [CAMPCheckConfig]::new() 68 | $ConfigObject.ConfigItem = "$($Cases.Name)" 69 | $ConfigObject.ConfigData = "$($Cases.Status)" 70 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Fail") 71 | $this.AddConfig($ConfigObject) 72 | $ConfigObjectList += $ConfigObject 73 | $activecasepresent= $true 74 | } 75 | $CasesPresent= $true 76 | } 77 | if(($activecasepresent -eq $false) -and ($CasesPresent -eq $true)) 78 | { 79 | $ConfigObject = [CAMPCheckConfig]::new() 80 | $ConfigObject.ConfigItem = "No active case" 81 | $ConfigObject.ConfigData = "" 82 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Pass") 83 | $this.AddConfig($ConfigObject) 84 | $ConfigObjectList += $ConfigObject 85 | } 86 | elseif($CasesPresent -eq $false) 87 | { 88 | $ConfigObject = [CAMPCheckConfig]::new() 89 | $ConfigObject.ConfigItem = "No eDiscovery cases found" 90 | $ConfigObject.ConfigData = "" 91 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Fail") 92 | $this.AddConfig($ConfigObject) 93 | $ConfigObjectList += $ConfigObject 94 | } 95 | 96 | $hasRemediation = $this.Config | Where-Object { $_.RemediationAction -ne ''} 97 | if ($($hasremediation.count) -gt 0) 98 | { 99 | $this.CAMPRemediationInfo = New-Object -TypeName CAMPRemediationInfo -Property @{ 100 | RemediationAvailable = $True 101 | RemediationText = "You need to connect to Security & Compliance Center PowerShell to execute the below commands. Please follow steps defined in Connect to Security & Compliance Center PowerShell." 102 | } 103 | } 104 | $this.Completed = $True 105 | } 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /Checks/check-Audit102.ps1: -------------------------------------------------------------------------------- 1 | using module "..\CAMP.psm1" 2 | 3 | class Audit102 : CAMPCheck { 4 | <# 5 | this is to valide if tenant has high serverity alert policies or not 6 | 7 | #> 8 | 9 | Audit102() { 10 | $this.Control = "Audit-102" 11 | $this.ParentArea = "Discovery & Response" 12 | $this.Area = "Audit" 13 | $this.Name = "Configure Alert Policies" 14 | $this.PassText = "Your organization has configured alert policies" 15 | $this.FailRecommendation = "Your organization should configure alert policies" 16 | $this.Importance = "Your organization should configure alert policies to send notifications on activities that are indicators of a potential security issue or data breach. Office 365 provides built-in alert policies that are turned on by default." 17 | $this.CheckType = [CheckType]::ObjectPropertyValue 18 | $this.ExpandResults = $True 19 | $this.ObjectType = "Alert Policy" 20 | $this.ItemName = "Severity" 21 | $this.DataType = "Email notifications" 22 | if($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovGCCHigh") 23 | { 24 | $this.Links = @{ 25 | "Turn on audit log search" = "https://aka.ms/mcca-aa-docs-action-turn-on" 26 | "Security & Compliance Console : Alert Policies" = "https://aka.ms/mcca-gcch-aa-2-compliance-center" 27 | "Learn more about alert policies" = "https://aka.ms/mcca-aa-docs-learn-more" 28 | "Compliance Manager - Audit Actions" = "https://aka.ms/mcca-gcch-aa-compliance-manager" 29 | } 30 | }elseif ($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovDoD") 31 | { 32 | $this.Links = @{ 33 | "Turn on audit log search" = "https://aka.ms/mcca-aa-docs-action-turn-on" 34 | "Security & Compliance Console : Alert Policies" = "https://aka.ms/mcca-dod-aa-2-compliance-center" 35 | "Learn more about alert policies" = "https://aka.ms/mcca-aa-docs-learn-more" 36 | "Compliance Manager - Audit Actions" = "https://aka.ms/mcca-dod-aa-compliance-manager" 37 | } 38 | }else 39 | { 40 | $this.Links = @{ 41 | "Turn on audit log search" = "https://aka.ms/mcca-aa-docs-action-turn-on" 42 | "Security & Compliance Console : Alert Policies" = "https://aka.ms/mcca-aa-2-compliance-center" 43 | "Learn more about alert policies" = "https://aka.ms/mcca-aa-docs-learn-more" 44 | "Compliance Manager - Audit Actions" = "https://aka.ms/mcca-aa-compliance-manager" 45 | } 46 | } 47 | } 48 | 49 | <# 50 | 51 | RESULTS 52 | 53 | #> 54 | 55 | GetResults($Config) { 56 | if ($Config["GetProtectionAlert"] -eq "Error") { 57 | $this.Completed = $false 58 | } 59 | else { 60 | $ConfigObjectList = @() 61 | $PoliciesExist = $false 62 | ForEach ($AlertPolicy in $Config["GetProtectionAlert"]) { 63 | 64 | $ConfigObject = [CAMPCheckConfig]::new() 65 | $ConfigObject.Object = "$($AlertPolicy.Name)" 66 | $ConfigObject.ConfigItem = "$($AlertPolicy.Severity)" 67 | if($($AlertPolicy.Disabled) -eq $false) 68 | { 69 | $PoliciesExist = $True 70 | if($($AlertPolicy.NotificationEnabled) -eq $True) 71 | { 72 | $ConfigObject.ConfigData = $($AlertPolicy.NotifyUser) 73 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Pass") 74 | $this.AddConfig($ConfigObject) 75 | 76 | }else{ 77 | $ConfigObject.ConfigData = "Email notifications not enabled" 78 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Fail") 79 | $this.AddConfig($ConfigObject) 80 | 81 | } 82 | 83 | }else{ 84 | $ConfigObject.ConfigData = "Alert policy not enabled" 85 | $ConfigObject.SetResult([CAMPConfigLevel]::Informational, "Pass") 86 | $this.AddConfig($ConfigObject) 87 | 88 | 89 | } 90 | } 91 | If ($PoliciesExist -eq $False) { 92 | $ConfigObject = [CAMPCheckConfig]::new() 93 | $ConfigObject.Object = "No active high severity policies were found" 94 | $ConfigObject.ConfigItem = "No active high severity policies" 95 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Fail") 96 | $ConfigObjectList += $ConfigObject 97 | $this.AddConfig($ConfigObject) 98 | } 99 | 100 | $hasRemediation = $this.Config | Where-Object { $_.RemediationAction -ne ''} 101 | if ($($hasremediation.count) -gt 0) 102 | { 103 | $this.CAMPRemediationInfo = New-Object -TypeName CAMPRemediationInfo -Property @{ 104 | RemediationAvailable = $True 105 | RemediationText = "You need to connect to Security & Compliance Center PowerShell to execute the below commands. Please follow steps defined in Connect to Security & Compliance Center PowerShell." 106 | } 107 | } 108 | $this.Completed = $True 109 | } 110 | 111 | } 112 | 113 | } -------------------------------------------------------------------------------- /Checks/check-IP102.ps1: -------------------------------------------------------------------------------- 1 | using module "..\CAMP.psm1" 2 | 3 | class IP102 : CAMPCheck { 4 | <# 5 | 6 | 7 | #> 8 | 9 | IP102() { 10 | $this.Control = "IP-102" 11 | $this.ParentArea = "Microsoft Information Protection" 12 | $this.Area = "Information Protection" 13 | $this.Name = "Auto-apply client side sensitivity labels" 14 | $this.PassText = "Your organization is using auto-apply client side sensitivity labels" 15 | $this.FailRecommendation = "Your organization should use client side sensitivity labels" 16 | $this.Importance = "Your organization should automatically apply client side sensitivity labels based on sensitive information types or other criteria. Microsoft recommends that automatic labeling be implemented to decrease reliance on users for correct classification." 17 | $this.ExpandResults = $True 18 | $this.ItemName = "Labels" 19 | $this.DataType = "Remarks" 20 | if($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovGCCHigh") 21 | { 22 | $this.Links = @{ 23 | "Overview of sensitivity labels " = "https://aka.ms/mcca-ip-docs-sensitivity-labels" 24 | "How to apply a sensitivity label to content automatically" = "https://aka.ms/mcca-ip-docs-action-apply-sensitivity-labels" 25 | "Compliance Center - Information Protection" = "https://aka.ms/mcca-gcch-ip-compliance-center" 26 | "Compliance Manager - IP Actions" = "https://aka.ms/mcca-gcch-ip-compliance-manager" 27 | } 28 | }elseif ($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovDoD") 29 | { 30 | $this.Links = @{ 31 | "Overview of sensitivity labels " = "https://aka.ms/mcca-ip-docs-sensitivity-labels" 32 | "How to apply a sensitivity label to content automatically" = "https://aka.ms/mcca-ip-docs-action-apply-sensitivity-labels" 33 | "Compliance Center - Information Protection" = "https://aka.ms/mcca-dod-ip-compliance-center" 34 | "Compliance Manager - IP Actions" = "https://aka.ms/mcca-dod-ip-compliance-manager" 35 | } 36 | }else 37 | { 38 | $this.Links = @{ 39 | "Overview of sensitivity labels " = "https://aka.ms/mcca-ip-docs-sensitivity-labels" 40 | "How to apply a sensitivity label to content automatically" = "https://aka.ms/mcca-ip-docs-action-apply-sensitivity-labels" 41 | "Compliance Center - Information Protection" = "https://aka.ms/mcca-ip-compliance-center" 42 | "Compliance Manager - IP Actions" = "https://aka.ms/mcca-ip-compliance-manager" 43 | } 44 | } 45 | } 46 | 47 | <# 48 | 49 | RESULTS 50 | 51 | #> 52 | 53 | GetResults($Config) { 54 | if ($Config["GetLabel"] -eq "Error") { 55 | $this.Completed = $false 56 | } 57 | else { 58 | $ConfigObjectList = @() 59 | $AutoApplyExist = $false 60 | 61 | ForEach ($LabelsDefined in $Config["GetLabel"]) { 62 | $Labels = $LabelsDefined 63 | 64 | if ($($Labels.Conditions)) { 65 | if ($($Labels.Disabled) -eq $false) { 66 | $Workload = $Labels.Workload 67 | 68 | if ((((@($Workload) -like 'Exchange').Count -lt 1)) -and (((@($Workload) -like 'SharePoint').Count -lt 1))) { 69 | $ConfigObject = [CAMPCheckConfig]::new() 70 | $ConfigObject.ConfigItem = "$($Labels.DisplayName)" 71 | $ConfigObject.ConfigData = "Enabled Workloads: Office Apps" 72 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Pass") 73 | $ConfigObjectList += $ConfigObject 74 | $AutoApplyExist = $true 75 | $this.AddConfig($ConfigObject) 76 | 77 | 78 | } 79 | else { 80 | $ConfigObject = [CAMPCheckConfig]::new() 81 | $ConfigObject.ConfigItem = "$($Labels.DisplayName)" 82 | $ConfigObject.ConfigData = "Only Enabled Workload: $($Labels.Workload)" 83 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Fail") 84 | $ConfigObjectList += $ConfigObject 85 | $this.AddConfig($ConfigObject) 86 | 87 | } 88 | } 89 | else { 90 | $ConfigObject = [CAMPCheckConfig]::new() 91 | $ConfigObject.ConfigItem = "$($Labels.DisplayName)" 92 | $ConfigObject.ConfigData = "Label is not enabled" 93 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Fail") 94 | $ConfigObjectList += $ConfigObject 95 | $this.AddConfig($ConfigObject) 96 | 97 | } 98 | 99 | } 100 | 101 | } 102 | 103 | 104 | If ($AutoApplyExist -eq $False) { 105 | $ConfigObject = [CAMPCheckConfig]::new() 106 | $ConfigObject.Object = "No Active Policy defined" 107 | $ConfigObject.ConfigItem = "No Auto Apply Policy" 108 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Fail") 109 | $ConfigObjectList += $ConfigObject 110 | $this.AddConfig($ConfigObject) 111 | } 112 | 113 | 114 | $hasRemediation = $this.Config | Where-Object { $_.RemediationAction -ne ''} 115 | if ($($hasremediation.count) -gt 0) 116 | { 117 | $this.CAMPRemediationInfo = New-Object -TypeName CAMPRemediationInfo -Property @{ 118 | RemediationAvailable = $True 119 | RemediationText = "You need to connect to Security & Compliance Center PowerShell to execute the below commands. Please follow steps defined in Connect to Security & Compliance Center PowerShell." 120 | } 121 | } 122 | $this.Completed = $True 123 | } 124 | } 125 | 126 | } -------------------------------------------------------------------------------- /Checks/check-CC101.ps1: -------------------------------------------------------------------------------- 1 | using module "..\CAMP.psm1" 2 | 3 | class CC101 : CAMPCheck { 4 | <# 5 | 6 | 7 | #> 8 | 9 | CC101() { 10 | $this.Control = "CC-101" 11 | $this.ParentArea = "Insider Risk" 12 | $this.Area = "Communication Compliance" 13 | $this.Name = "Enable Communication Compliance in O365" 14 | $this.PassText = "Your organization has enabled Communication Compliance in O365" 15 | $this.FailRecommendation = "Your organization should enable Communication Compliance in O365" 16 | $this.Importance = "Your organization should use communication compliance to scan internal and external communications for policy matches so they can be examined by designated reviewers." 17 | $this.ExpandResults = $True 18 | $this.ItemName = "Role" 19 | $this.DataType = "Role Groups
( Having 1 or more members)" 20 | if($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovGCCHigh") 21 | { 22 | $this.Links = @{ 23 | "Communication compliance in Microsoft 365" = "https://aka.ms/mcca-cc-docs-learn-more" 24 | "Compliance Center - Communication Compliance" = "https://aka.ms/mcca-gcch-cc-compliance-center" 25 | "Compliance Manager - CC Actions" = "https://aka.ms/mcca-gcch-cc-compliance-manager" 26 | } 27 | }elseif ($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovDoD") 28 | { 29 | $this.Links = @{ 30 | "Communication compliance in Microsoft 365" = "https://aka.ms/mcca-cc-docs-learn-more" 31 | "Compliance Center - Communication Compliance" = "https://aka.ms/mcca-dod-cc-compliance-center" 32 | "Compliance Manager - CC Actions" = "https://aka.ms/mcca-dod-cc-compliance-manager" 33 | } 34 | }else 35 | { 36 | $this.Links = @{ 37 | "Communication compliance in Microsoft 365" = "https://aka.ms/mcca-cc-docs-learn-more" 38 | "Compliance Center - Communication Compliance" = "https://aka.ms/mcca-cc-compliance-center" 39 | "Compliance Manager - CC Actions" = "https://aka.ms/mcca-cc-compliance-manager" 40 | } 41 | } 42 | } 43 | 44 | <# 45 | 46 | RESULTS CC Admin, CC Analyst, CC Investigator and CC Viewer 47 | #> 48 | 49 | GetResults($Config) { 50 | 51 | try { 52 | $SreviewAdminRoleGroups = Get-RoleGroup -ErrorAction:SilentlyContinue | Where-Object { $_.Roles -Like "*Supervisory Review Administrator*" -and $null -ne $_.Members } 53 | $CaseManagementRoleGroups = Get-RoleGroup -ErrorAction:SilentlyContinue | Where-Object { $_.Roles -Like "*Case Management*" -and $null -ne $_.Members } 54 | $ComplianceAdministratorRoleGroups = Get-RoleGroup -ErrorAction:SilentlyContinue | Where-Object { $_.Roles -Like "*Compliance Administrator*" -and $null -ne $_.Members } 55 | 56 | } 57 | catch { 58 | $SreviewAdminRoleGroups = "Error" 59 | $CaseManagementRoleGroups = "Error" 60 | $ComplianceAdministratorRoleGroups = "Error" 61 | } 62 | if (($SreviewAdminRoleGroups -eq "Error") -or ($CaseManagementRoleGroups -eq "Error") -or ($ComplianceAdministratorRoleGroups -eq "Error")) { 63 | $this.Completed = $false 64 | } 65 | else { 66 | $UtilityFiles = Get-ChildItem "$PSScriptRoot\..\Utilities" 67 | 68 | ForEach ($UtilityFile in $UtilityFiles) { 69 | . $UtilityFile.FullName 70 | } 71 | $LogFile = $this.LogFile 72 | 73 | $ConfigObjectList = Get-RoleGroupwithMembers -RoleGroups $SreviewAdminRoleGroups -Role "Supervisory Review Administrator" -LogFile $LogFile 74 | Foreach ($ConfigObject in $ConfigObjectList) { 75 | $this.AddConfig($ConfigObject) 76 | } 77 | $ConfigObjectList = Get-RoleGroupwithMembers -RoleGroups $CaseManagementRoleGroups -Role "Case Management" -LogFile $LogFile 78 | Foreach ($ConfigObject in $ConfigObjectList) { 79 | $this.AddConfig($ConfigObject) 80 | } 81 | $ConfigObjectList = Get-RoleGroupwithMembers -RoleGroups $ComplianceAdministratorRoleGroups -Role "Compliance Administrator" -LogFile $LogFile 82 | Foreach ($ConfigObject in $ConfigObjectList) { 83 | $this.AddConfig($ConfigObject) 84 | } 85 | # New roles post CC july release 86 | #$CCAdminRoleGroups = Get-RoleGroup | Where-Object {$_.Roles -Like "*Communication Compliance Admin*" -and $_.Members -ne $null} 87 | #$CCAnalystRoleGroups = Get-RoleGroup | Where-Object {$_.Roles -Like "*Communication Compliance Analyst*" -and $_.Members -ne $null} 88 | #$CCInvesRoleGroups = Get-RoleGroup | Where-Object {$_.Roles -Like "*Communication Compliance Investigator*" -and $_.Members -ne $null} 89 | #$CCViewRoleGroups = Get-RoleGroup | Where-Object {$_.Roles -Like "*Communication Compliance Viewer*" -and $_.Members -ne $null} 90 | 91 | <# 92 | $ConfigObjectList = Get-RoleGroupwithMembers -RoleGroups $CCAdminRoleGroups -Role "Communication Compliance Admin" 93 | Foreach ($ConfigObject in $ConfigObjectList) 94 | { 95 | $this.AddConfig($ConfigObject) 96 | } 97 | $ConfigObjectList = Get-RoleGroupwithMembers -RoleGroups $CCAnalystRoleGroups -Role "Communication Compliance Analyst" 98 | Foreach ($ConfigObject in $ConfigObjectList) 99 | { 100 | $this.AddConfig($ConfigObject) 101 | } 102 | $ConfigObjectList = Get-RoleGroupwithMembers -RoleGroups $CCInvesRoleGroups -Role "Communication Compliance Investigator" 103 | Foreach ($ConfigObject in $ConfigObjectList) 104 | { 105 | $this.AddConfig($ConfigObject) 106 | } 107 | $ConfigObjectList = Get-RoleGroupwithMembers -RoleGroups $CCViewRoleGroups -Role "Communication Compliance Viewer" 108 | Foreach ($ConfigObject in $ConfigObjectList) 109 | { 110 | $this.AddConfig($ConfigObject) 111 | }#> 112 | 113 | $hasRemediation = $this.Config | Where-Object { $_.RemediationAction -ne '' } 114 | if ($($hasremediation.count) -gt 0) { 115 | $this.CAMPRemediationInfo = New-Object -TypeName CAMPRemediationInfo -Property @{ 116 | RemediationAvailable = $True 117 | RemediationText = "You need to connect to Security & Compliance Center PowerShell to execute the below commands. Please follow steps defined in Connect to Security & Compliance Center PowerShell." 118 | } 119 | } 120 | $this.Completed = $True 121 | } 122 | 123 | } 124 | 125 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | [Ll]ogs/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUnit 47 | *.VisualState.xml 48 | TestResult.xml 49 | nunit-*.xml 50 | 51 | # Build Results of an ATL Project 52 | [Dd]ebugPS/ 53 | [Rr]eleasePS/ 54 | dlldata.c 55 | 56 | # Benchmark Results 57 | BenchmarkDotNet.Artifacts/ 58 | 59 | # .NET Core 60 | project.lock.json 61 | project.fragment.lock.json 62 | artifacts/ 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_h.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *_wpftmp.csproj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # Visual Studio Trace Files 117 | *.e2e 118 | 119 | # TFS 2012 Local Workspace 120 | $tf/ 121 | 122 | # Guidance Automation Toolkit 123 | *.gpState 124 | 125 | # ReSharper is a .NET coding add-in 126 | _ReSharper*/ 127 | *.[Rr]e[Ss]harper 128 | *.DotSettings.user 129 | 130 | # TeamCity is a build add-in 131 | _TeamCity* 132 | 133 | # DotCover is a Code Coverage Tool 134 | *.dotCover 135 | 136 | # AxoCover is a Code Coverage Tool 137 | .axoCover/* 138 | !.axoCover/settings.json 139 | 140 | # Visual Studio code coverage results 141 | *.coverage 142 | *.coveragexml 143 | 144 | # NCrunch 145 | _NCrunch_* 146 | .*crunch*.local.xml 147 | nCrunchTemp_* 148 | 149 | # MightyMoose 150 | *.mm.* 151 | AutoTest.Net/ 152 | 153 | # Web workbench (sass) 154 | .sass-cache/ 155 | 156 | # Installshield output folder 157 | [Ee]xpress/ 158 | 159 | # DocProject is a documentation generator add-in 160 | DocProject/buildhelp/ 161 | DocProject/Help/*.HxT 162 | DocProject/Help/*.HxC 163 | DocProject/Help/*.hhc 164 | DocProject/Help/*.hhk 165 | DocProject/Help/*.hhp 166 | DocProject/Help/Html2 167 | DocProject/Help/html 168 | 169 | # Click-Once directory 170 | publish/ 171 | 172 | # Publish Web Output 173 | *.[Pp]ublish.xml 174 | *.azurePubxml 175 | # Note: Comment the next line if you want to checkin your web deploy settings, 176 | # but database connection strings (with potential passwords) will be unencrypted 177 | *.pubxml 178 | *.publishproj 179 | 180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 181 | # checkin your Azure Web App publish settings, but sensitive information contained 182 | # in these scripts will be unencrypted 183 | PublishScripts/ 184 | 185 | # NuGet Packages 186 | *.nupkg 187 | # NuGet Symbol Packages 188 | *.snupkg 189 | # The packages folder can be ignored because of Package Restore 190 | **/[Pp]ackages/* 191 | # except build/, which is used as an MSBuild target. 192 | !**/[Pp]ackages/build/ 193 | # Uncomment if necessary however generally it will be regenerated when needed 194 | #!**/[Pp]ackages/repositories.config 195 | # NuGet v3's project.json files produces more ignorable files 196 | *.nuget.props 197 | *.nuget.targets 198 | 199 | # Microsoft Azure Build Output 200 | csx/ 201 | *.build.csdef 202 | 203 | # Microsoft Azure Emulator 204 | ecf/ 205 | rcf/ 206 | 207 | # Windows Store app package directories and files 208 | AppPackages/ 209 | BundleArtifacts/ 210 | Package.StoreAssociation.xml 211 | _pkginfo.txt 212 | *.appx 213 | *.appxbundle 214 | *.appxupload 215 | 216 | # Visual Studio cache files 217 | # files ending in .cache can be ignored 218 | *.[Cc]ache 219 | # but keep track of directories ending in .cache 220 | !?*.[Cc]ache/ 221 | 222 | # Others 223 | ClientBin/ 224 | ~$* 225 | *~ 226 | *.dbmdl 227 | *.dbproj.schemaview 228 | *.jfm 229 | *.pfx 230 | *.publishsettings 231 | orleans.codegen.cs 232 | 233 | # Including strong name files can present a security risk 234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 235 | #*.snk 236 | 237 | # Since there are multiple workflows, uncomment next line to ignore bower_components 238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 239 | #bower_components/ 240 | 241 | # RIA/Silverlight projects 242 | Generated_Code/ 243 | 244 | # Backup & report files from converting an old project file 245 | # to a newer Visual Studio version. Backup files are not needed, 246 | # because we have git ;-) 247 | _UpgradeReport_Files/ 248 | Backup*/ 249 | UpgradeLog*.XML 250 | UpgradeLog*.htm 251 | ServiceFabricBackup/ 252 | *.rptproj.bak 253 | 254 | # SQL Server files 255 | *.mdf 256 | *.ldf 257 | *.ndf 258 | 259 | # Business Intelligence projects 260 | *.rdl.data 261 | *.bim.layout 262 | *.bim_*.settings 263 | *.rptproj.rsuser 264 | *- [Bb]ackup.rdl 265 | *- [Bb]ackup ([0-9]).rdl 266 | *- [Bb]ackup ([0-9][0-9]).rdl 267 | 268 | # Microsoft Fakes 269 | FakesAssemblies/ 270 | 271 | # GhostDoc plugin setting file 272 | *.GhostDoc.xml 273 | 274 | # Node.js Tools for Visual Studio 275 | .ntvs_analysis.dat 276 | node_modules/ 277 | 278 | # Visual Studio 6 build log 279 | *.plg 280 | 281 | # Visual Studio 6 workspace options file 282 | *.opt 283 | 284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 285 | *.vbw 286 | 287 | # Visual Studio LightSwitch build output 288 | **/*.HTMLClient/GeneratedArtifacts 289 | **/*.DesktopClient/GeneratedArtifacts 290 | **/*.DesktopClient/ModelManifest.xml 291 | **/*.Server/GeneratedArtifacts 292 | **/*.Server/ModelManifest.xml 293 | _Pvt_Extensions 294 | 295 | # Paket dependency manager 296 | .paket/paket.exe 297 | paket-files/ 298 | 299 | # FAKE - F# Make 300 | .fake/ 301 | 302 | # CodeRush personal settings 303 | .cr/personal 304 | 305 | # Python Tools for Visual Studio (PTVS) 306 | __pycache__/ 307 | *.pyc 308 | 309 | # Cake - Uncomment if you are using it 310 | # tools/** 311 | # !tools/packages.config 312 | 313 | # Tabs Studio 314 | *.tss 315 | 316 | # Telerik's JustMock configuration file 317 | *.jmconfig 318 | 319 | # BizTalk build output 320 | *.btp.cs 321 | *.btm.cs 322 | *.odx.cs 323 | *.xsd.cs 324 | 325 | # OpenCover UI analysis results 326 | OpenCover/ 327 | 328 | # Azure Stream Analytics local run output 329 | ASALocalRun/ 330 | 331 | # MSBuild Binary and Structured Log 332 | *.binlog 333 | 334 | # NVidia Nsight GPU debugger configuration file 335 | *.nvuser 336 | 337 | # MFractors (Xamarin productivity tool) working folder 338 | .mfractor/ 339 | 340 | # Local History for Visual Studio 341 | .localhistory/ 342 | 343 | # BeatPulse healthcheck temp database 344 | healthchecksdb 345 | 346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 347 | MigrationBackup/ 348 | 349 | # Ionide (cross platform F# VS Code tools) working folder 350 | .ionide/ 351 | -------------------------------------------------------------------------------- /Remediation/RemediationAction.ps1: -------------------------------------------------------------------------------- 1 | using module "..\CAMP.psm1" 2 | 3 | class Action : RemediationAction 4 | { 5 | 6 | $OutputDirectory=$null 7 | $DisplayReport=$True 8 | 9 | Action() 10 | { 11 | $this.Name="Action" 12 | } 13 | 14 | RunOutput($Checks,$Collection) 15 | { 16 | <# 17 | 18 | OUTPUT GENERATION / Header 19 | 20 | #> 21 | 22 | # Obtain the tenant domain and date for the report 23 | #$TenantDomain = ($Collection["AcceptedDomains"] | Where-Object {$_.InitialDomain -eq $True}).DomainName 24 | 25 | # Misc 26 | $ReportTitle = "Configuration Analyzer for Microsoft Purview Remediation Report" 27 | 28 | 29 | 30 | 31 | # Output start 32 | $output = " 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 90 | $($ReportTitle) 91 | 92 | 93 | 94 | 95 | 106 |
107 |


108 |

 $($ReportTitle)

109 |

 This report details recommended remediations based on your CAMP report.

110 |
" 111 | <# 112 | 113 | OUTPUT GENERATION / Summary 114 | 115 | #> 116 | $Output += "
" 117 | [int] $count = 1 118 | ForEach ($Area in ($Checks | Where-Object {$_.CAMPRemediationInfo.RemediationAvailable -eq $True}| Group-Object Area )) 119 | { 120 | $Output += 121 | " 122 |
123 |
124 | $($Area.Name)
125 | 126 |
127 | " 128 | # Each check 129 | ForEach ($Check in ($Area.Group | Sort-Object Result -Descending)) 130 | { 131 | ForEach($o in $Check.Config) 132 | { 133 | if($($o.RemediationAction)) 134 | { 135 | # div identifier for each remediation script 136 | $divid = "div"+ $count.ToString() 137 | $Output += " 138 | 139 |
$($Check.Name)
140 |    $($Check.CAMPRemediationInfo.RemediationText)

" 141 | 142 | 143 | # We should expand the results by showing a table of Config Data and Items 144 | $Output += " 145 | " 155 | $Output += "" 156 | $Output += "
146 |
147 |
148 |
PowerShell
149 |
150 | 151 |
152 |
153 |
154 |

$($o.RemediationAction)


" 157 | } 158 | # Object, property, value checks need three columns 159 | } 160 | $count = $count + 1 161 | } 162 | 163 | $Output += "
" 164 | 165 | } 166 | $Output += "
" 167 | <# 168 | 169 | OUTPUT GENERATION / Footer 170 | 171 | #> 172 | 173 | $Output += " 174 | 175 | 176 |
177 |
178 |

    Disclaimer: Recommendations from CAMP should not be interpreted as a guarantee of compliance. 179 | It is up to you to evaluate and validate the effectiveness of customer controls per your regulatory environment.
180 |

181 |
182 |
183 | 192 | 193 | " 194 | 195 | 196 | # Write to file 197 | 198 | if($null -eq $this.OutputDirectory) 199 | { 200 | $OutputDir = $this.DefaultOutputDirectory 201 | } 202 | else 203 | { 204 | $OutputDir = $this.OutputDirectory 205 | } 206 | 207 | #$Tenant = $(($Collection["AcceptedDomains"] | Where-Object {$_.InitialDomain -eq $True}).DomainName -split '\.')[0] 208 | $ReportFileName = "CAMP-$(Get-Date -Format 'yyyyMMddHHmm')-Remediation.html" 209 | 210 | $OutputFile = "$OutputDir\$ReportFileName" 211 | 212 | $Output | Out-File -FilePath $OutputFile 213 | $this.Completed = $True 214 | $this.Result = $OutputFile 215 | 216 | } 217 | 218 | } -------------------------------------------------------------------------------- /Utilities/RMValidationUtility.ps1: -------------------------------------------------------------------------------- 1 | using module "..\CAMP.psm1" 2 | $ExchangePresent = "Exchange" 3 | $SharePointPresent = "SharePoint" 4 | $OneDrivePresent = "OneDrive" 5 | 6 | 7 | Function Get-RMPolicyValidation { 8 | param ( 9 | $LogFile, 10 | $Mode 11 | ) 12 | $ConfigObjectList = @() 13 | try { 14 | 15 | $ConfigObjectList=@() 16 | $RecordLabelPolicy =$false 17 | $PolicyDisabled = $false 18 | $AnyPolicyEnabled = $false 19 | $RetentionComplianceRules = $Config["GetRetentionComplianceRule"] 20 | $RetentionCompliancePolicies = $Config["GetRetentionCompliancePolicy"] 21 | $GetComplianceTag = $Config["GetComplianceTag"] 22 | 23 | $PartialWorkloadsStatus = @{} 24 | $PartialWorkloadsStatus[$ExchangePresent] = $false 25 | $PartialWorkloadsStatus[$SharePointPresent] = $false 26 | $PartialWorkloadsStatus[$OneDrivePresent] = $false 27 | 28 | foreach ( $RetentionCompliancePolicy in $RetentionCompliancePolicies) { 29 | 30 | $PolicyName = $($RetentionCompliancePolicy.Name) 31 | $ConfigObject = [CAMPCheckConfig]::new() 32 | $ConfigObject.Object = "$PolicyName" 33 | $PolicyConfigData = $null 34 | #Publishing a Record Label 35 | if($Mode -eq "Publish") 36 | { 37 | $RetentionCompliancePolicyRules = $RetentionComplianceRules | Where-Object {($_.Policy -ieq $($RetentionCompliancePolicy.ExchangeObjectId)) -and ($_.Disabled -eq $false) -and($_.PublishComplianceTag -ne "")} 38 | foreach( $RetentionCompliancePolicyRule in $RetentionCompliancePolicyRules ) 39 | { 40 | $PublishComplianceTag = $RetentionCompliancePolicyRule.PublishComplianceTag 41 | $PublishComplianceTag = $($PublishComplianceTag.Split(","))[1] 42 | 43 | $GetRecordLabel= $GetComplianceTag | Where-Object{ ($_.Name -eq $PublishComplianceTag) -and ($_.IsRecordLabel -ne $false)} 44 | if($null -ne $GetRecordLabel) 45 | { 46 | 47 | $RecordLabelPolicy =$true 48 | if ($null -eq $PolicyConfigData ) { 49 | $PolicyConfigData += "Labels : $PublishComplianceTag" 50 | } 51 | else { 52 | $PolicyConfigData += ", $PublishComplianceTag" 53 | } 54 | } 55 | } 56 | } 57 | #automatically apply record labels 58 | elseif($Mode -eq "Auto") 59 | { 60 | $RetentionCompliancePolicyRules = $RetentionComplianceRules | Where-Object {($_.Policy -ieq $($RetentionCompliancePolicy.ExchangeObjectId)) -and ($_.Disabled -eq $false) -and($_.ApplyComplianceTag -ne "")} 61 | foreach( $RetentionCompliancePolicyRule in $RetentionCompliancePolicyRules ) 62 | { 63 | $ApplyComplianceTag = $RetentionCompliancePolicyRule.ApplyComplianceTag 64 | 65 | 66 | $GetRecordLabel= $GetComplianceTag | Where-Object{ ($_.ExchangeObjectId -eq $ApplyComplianceTag) -and ($_.IsRecordLabel -ne $false)} 67 | if($null -ne $GetRecordLabel) 68 | { 69 | 70 | $RecordLabelPolicy =$true 71 | if ($null -eq $PolicyConfigData ) { 72 | $PolicyConfigData += "Labels : $($GetRecordLabel.Name)" 73 | } 74 | else { 75 | $PolicyConfigData += ", $($GetRecordLabel.Name)" 76 | } 77 | } 78 | } 79 | } 80 | $ExchangeLocation = $RetentionCompliancePolicy.ExchangeLocation 81 | $SharePointLocation = $RetentionCompliancePolicy.SharePointLocation 82 | $OneDriveLocation = $RetentionCompliancePolicy.OneDriveLocation 83 | $ModernGroupLocation = $RetentionCompliancePolicy.ModernGroupLocation 84 | $PublicFolderLocation = $RetentionCompliancePolicy.PublicFolderLocation 85 | $SkypeLocation = $RetentionCompliancePolicy.SkypeLocation 86 | 87 | 88 | $WorkloadsStatus= "" 89 | if(($RetentionCompliancePolicy.Enabled -eq $true) -and ($null -ne $PolicyConfigData )) 90 | { 91 | if(($ExchangeLocation -ne "") ) 92 | { 93 | $WorkloadsStatus+= "Exchange, " 94 | $PartialWorkloadsStatus[$ExchangePresent] = $true 95 | } 96 | if(($SharePointLocation -ne "") ) 97 | { 98 | $WorkloadsStatus += "SharePoint, " 99 | $PartialWorkloadsStatus[$SharePointPresent] = $true 100 | } 101 | if(($OneDriveLocation -ne "") ) 102 | { 103 | $WorkloadsStatus+= "OneDrive, " 104 | $PartialWorkloadsStatus[$OneDrivePresent] = $true 105 | } 106 | if(($ModernGroupLocation -ne "") ) 107 | { 108 | $WorkloadsStatus += "ModernGroup, " 109 | } 110 | if(($PublicFolderLocation -ne "") ) 111 | { 112 | $WorkloadsStatus += "ExchangePublicFolders, " 113 | } 114 | if(($SkypeLocation -ne "") ) 115 | { 116 | $WorkloadsStatus += "Skype, " 117 | } 118 | 119 | } 120 | $workloadpresent ="Workloads: $WorkloadsStatus" 121 | $workloadpresent=$workloadpresent.TrimEnd(", ") 122 | 123 | if ($RetentionCompliancePolicy.Enabled -eq $true ) { 124 | if (($null -ne $PolicyConfigData) -and ($RecordLabelPolicy -eq $true) ) { 125 | $AnyPolicyEnabled =$true 126 | $Workload= $workloadpresent 127 | $ConfigObject.ConfigData = "$Workload" 128 | $ConfigObject.ConfigItem = "$PolicyConfigData" 129 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Pass") 130 | $ConfigObjectList += $ConfigObject 131 | } 132 | } 133 | elseif(($null -ne $PolicyConfigData) -and ($RetentionCompliancePolicy.Enabled -ne $true) ) { 134 | $PolicyDisabled =$true 135 | $ConfigObject.ConfigData = "Policy is not enabled" 136 | $ConfigObject.ConfigItem = "$PolicyConfigData" 137 | $ConfigObject.SetResult([CAMPConfigLevel]::Informational, "Pass") 138 | $ConfigObjectList += $ConfigObject 139 | } 140 | } 141 | 142 | if ($RecordLabelPolicy -eq $false) { 143 | $ConfigObject = [CAMPCheckConfig]::new() 144 | $ConfigObject.Object = "No record label policy defined" 145 | $ConfigObject.ConfigItem = "" 146 | $ConfigObject.ConfigData = "Affected workloads: Exchange, SharePoint, OneDrive" 147 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Fail") 148 | $ConfigObjectList += $ConfigObject 149 | 150 | } 151 | 152 | $PartialLocation="" 153 | foreach ($Workload in ($PartialWorkloadsStatus.Keys | Sort-Object -CaseSensitive) ) { 154 | 155 | if ($PartialWorkloadsStatus[$Workload] -eq $false) { 156 | if ( $PartialLocation -eq "") { 157 | $PartialLocation += "$($Workload)" 158 | }else { 159 | $PartialLocation += ", $($Workload)" 160 | } 161 | } 162 | } 163 | 164 | if(($PartialLocation -ne "") -and (($PolicyDisabled -eq $true) -or ($AnyPolicyEnabled -eq $true))) 165 | { 166 | $ConfigObject = [CAMPCheckConfig]::new() 167 | $ConfigObject.Object = "No policy defined for 1 or more workloads" 168 | $ConfigObject.ConfigItem = "" 169 | $ConfigObject.ConfigData = "Affected workloads: $PartialLocation" 170 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Fail") 171 | $ConfigObjectList += $ConfigObject 172 | } 173 | } 174 | catch { 175 | Write-Host "Error:$(Get-Date) There was an issue while running CAMP. Please try running the tool again after some time." -ForegroundColor:Red 176 | $ErrorMessage = $_.ToString() 177 | $StackTraceInfo = $_.ScriptStackTrace 178 | Write-Log -IsError -ErrorMessage $ErrorMessage -StackTraceInfo $StackTraceInfo -LogFile $LogFile -ErrorAction:SilentlyContinue 179 | } 180 | return $ConfigObjectList 181 | } 182 | -------------------------------------------------------------------------------- /Checks/check-IP104.ps1: -------------------------------------------------------------------------------- 1 | using module "..\CAMP.psm1" 2 | 3 | class IP104 : CAMPCheck { 4 | <# 5 | 6 | 7 | #> 8 | 9 | IP104() { 10 | $this.Control = "IP-104" 11 | $this.ParentArea = "Microsoft Information Protection" 12 | $this.Area = "Information Protection" 13 | $this.Name = "Create service side labelling policies" 14 | $this.PassText = "Your organization is using service side labeling policies" 15 | $this.FailRecommendation = "Your organization should use service side labeling policies" 16 | $this.Importance = "Your organization should setup and create service side labelling policies . This will help categorize your most important data so that you can effectively protect it from illicit access, and will help make it easier to investigate discovered breaches." 17 | $this.ExpandResults = $True 18 | $this.CheckType = [CheckType]::ObjectPropertyValue 19 | $this.ObjectType = "Auto Labelling Policy" 20 | $this.ItemName = "Label" 21 | $this.DataType = "Remarks" 22 | if($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovGCCHigh") 23 | { 24 | $this.Links = @{ 25 | "Learn more about configuring classifications for SharePoint Online" = "https://aka.ms/mcca-ip-docs-learn-more" 26 | "Compliance Center - Information Protection" = "https://aka.ms/mcca-gcch-ip-compliance-center" 27 | "Compliance Manager - IP Actions" = "https://aka.ms/mcca-gcch-ip-compliance-manager" 28 | } 29 | }elseif ($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovDoD") 30 | { 31 | $this.Links = @{ 32 | "Learn more about configuring classifications for SharePoint Online" = "https://aka.ms/mcca-ip-docs-learn-more" 33 | "Compliance Center - Information Protection" = "https://aka.ms/mcca-dod-ip-compliance-center" 34 | "Compliance Manager - IP Actions" = "https://aka.ms/mcca-dod-ip-compliance-manager" 35 | } 36 | }else 37 | { 38 | $this.Links = @{ 39 | "Learn more about configuring classifications for SharePoint Online" = "https://aka.ms/mcca-ip-docs-learn-more" 40 | "Compliance Center - Information Protection" = "https://aka.ms/mcca-ip-compliance-center" 41 | "Compliance Manager - IP Actions" = "https://aka.ms/mcca-ip-compliance-manager" 42 | } 43 | } 44 | } 45 | 46 | <# 47 | 48 | RESULTS 49 | 50 | #> 51 | 52 | GetResults($Config) { 53 | 54 | if ($Config["GetAutoSensitivityLabelPolicy"] -eq "Error") { 55 | $this.Completed = $false 56 | } 57 | else { 58 | $AutoApplyExist = $false 59 | $isExchangeCovered = $false 60 | $isSharePointCovered = $false 61 | $isOneDriveCovered = $false 62 | ForEach ($AutoPolicyDefined in $Config["GetAutoSensitivityLabelPolicy"]) { 63 | $AutoPolicy = $AutoPolicyDefined 64 | $AutoApplyExist = $true 65 | #Validate if Auto labelling policies are enabled across all workloads 66 | 67 | if ($($AutoPolicy.Mode) -eq "Disable") { 68 | $ConfigObject = [CAMPCheckConfig]::new() 69 | $ConfigObject.Object = "$($AutoPolicy.Name)" 70 | $ConfigObject.ConfigItem = "$($AutoPolicy.ApplySensitivityLabel)" 71 | $ConfigObject.ConfigData = "Policy is not enabled " 72 | $ConfigObject.SetResult([CAMPConfigLevel]::Informational, "Pass") 73 | $this.AddConfig($ConfigObject) 74 | } 75 | else { 76 | $ConfigObject = [CAMPCheckConfig]::new() 77 | $ConfigObject.Object = "$($AutoPolicy.Name)" 78 | $ConfigObject.ConfigItem = "$($AutoPolicy.ApplySensitivityLabel)" 79 | $ConfigData = $null 80 | if ( ($null -ne $($AutoPolicy.ExchangeLocation) ) -and ($null -ne $($AutoPolicy.SharePointLocation) ) -and ($null -ne $($AutoPolicy.OneDriveLocation) )) { 81 | $ConfigData = "Exchange User/Groups: $($AutoPolicy.ExchangeLocation)
" 82 | $ConfigData += "SharePoint Sites: $($AutoPolicy.SharePointLocation)
" 83 | $ConfigData += "OneDrive Accounts: $($AutoPolicy.OneDriveLocation)
" 84 | $ConfigObject.ConfigData = $ConfigData 85 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Pass") 86 | $this.AddConfig($ConfigObject) 87 | $isExchangeCovered = $true 88 | $isSharePointCovered = $true 89 | $isOneDriveCovered = $true 90 | 91 | } 92 | else { 93 | $ConfigObject = [CAMPCheckConfig]::new() 94 | $ConfigObject.Object = "$($AutoPolicy.Name)" 95 | $ConfigObject.ConfigItem = "$($AutoPolicy.ApplySensitivityLabel)" 96 | $ConfigData = $null 97 | if ( ($null -ne $($AutoPolicy.ExchangeLocation) ) -and ($null -ne $($AutoPolicy.SharePointLocation) ) -and ($null -ne $($AutoPolicy.OneDriveLocation) )) { 98 | $ConfigData = "Exchange User/Groups: $($AutoPolicy.ExchangeLocation)
" 99 | $isExchangeCovered = $true 100 | } 101 | else { 102 | $ConfigData = "Exchange User/Groups: Not Enabled
" 103 | } 104 | if ($null -ne $($AutoPolicy.SharePointLocation) ) { 105 | $ConfigData += "SharePoint Sites: $($AutoPolicy.SharePointLocation)
" 106 | $isSharePointCovered = $true 107 | } 108 | else { 109 | $ConfigData += "SharePoint Sites: Not Enabled
" 110 | } 111 | if ($null -ne $($AutoPolicy.OneDriveLocation) ) { 112 | $ConfigData += "OneDrive Accounts: $($AutoPolicy.OneDriveLocation)
" 113 | $isOneDriveCovered = $true 114 | } 115 | else { 116 | $ConfigData += "OneDrive Accounts: Not Enabled
" 117 | 118 | } 119 | $ConfigObject.ConfigData = $ConfigData 120 | $ConfigObject.SetResult([CAMPConfigLevel]::Informational, "Pass") 121 | $this.AddConfig($ConfigObject) 122 | } 123 | 124 | } 125 | } 126 | $PartialWorkload = "" 127 | If ($isExchangeCovered -eq $false) { 128 | if ($PartialWorkload -eq "") { 129 | $PartialWorkload += "Exchange" 130 | } 131 | else { 132 | $PartialWorkload += ",Exchange" 133 | } 134 | } 135 | 136 | If ($isSharePointCovered -eq $false) { 137 | if ($PartialWorkload -eq "") { 138 | $PartialWorkload += "SharePoint" 139 | } 140 | else { 141 | $PartialWorkload += ",SharePoint" 142 | } 143 | } 144 | 145 | If ($isOneDriveCovered -eq $false) { 146 | if ($PartialWorkload -eq "") { 147 | $PartialWorkload += "OneDrive" 148 | } 149 | else { 150 | $PartialWorkload += ",OneDrive" 151 | } 152 | } 153 | #policy not defined on one or more workload 154 | If (($PartialWorkload -ne "") -and ($AutoApplyExist -eq $true) ){ 155 | $ConfigObject = [CAMPCheckConfig]::new() 156 | $ConfigObject.Object = "All workload not covered" 157 | #$ConfigObject.ConfigItem = $PartialLabel 158 | $ConfigData = "Affected Workloads:$PartialWorkload
" 159 | $ConfigObject.ConfigData = $ConfigData 160 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Fail") 161 | $this.AddConfig($ConfigObject) 162 | } 163 | If ($AutoApplyExist -eq $False) { 164 | $ConfigObject = [CAMPCheckConfig]::new() 165 | $ConfigObject.Object = "No Auto Labeling Policy Defined" 166 | $ConfigObject.ConfigItem = "" 167 | $ConfigData = "Affected Workloads:Exchange, SharePoint, OneDrive" 168 | $ConfigObject.ConfigData = $ConfigData 169 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Fail") 170 | $this.AddConfig($ConfigObject) 171 | } 172 | $hasRemediation = $this.Config | Where-Object { $_.RemediationAction -ne '' } 173 | if ($($hasremediation.count) -gt 0) { 174 | $this.CAMPRemediationInfo = New-Object -TypeName CAMPRemediationInfo -Property @{ 175 | RemediationAvailable = $True 176 | RemediationText = "You need to connect to Security & Compliance Center PowerShell to execute the below commands. Please follow steps defined in Connect to Security & Compliance Center PowerShell." 177 | } 178 | } 179 | $this.Completed = $True 180 | } 181 | } 182 | 183 | } -------------------------------------------------------------------------------- /Utilities/IGValidationUtility.ps1: -------------------------------------------------------------------------------- 1 | using module "..\CAMP.psm1" 2 | $ExchangePresent = "Exchange" 3 | $SharePointPresent = "SharePoint" 4 | $OneDrivePresent = "OneDrive" 5 | 6 | 7 | Function Get-RetentionPolicyValidation { 8 | param ( 9 | $LogFile, 10 | $Mode 11 | ) 12 | $ConfigObjectList = @() 13 | try { 14 | 15 | $ConfigObjectList=@() 16 | $LabelPolicy =$false 17 | $PolicyDisabled = $false 18 | $AnyPolicyEnabled = $false 19 | $RetentionComplianceRules = $Config["GetRetentionComplianceRule"] 20 | $RetentionCompliancePolicies = $Config["GetRetentionCompliancePolicy"] 21 | $GetComplianceTag = $Config["GetComplianceTag"] 22 | 23 | $PartialWorkloadsStatus = @{} 24 | $PartialWorkloadsStatus[$ExchangePresent] = $false 25 | $PartialWorkloadsStatus[$SharePointPresent] = $false 26 | $PartialWorkloadsStatus[$OneDrivePresent] = $false 27 | 28 | foreach ( $RetentionCompliancePolicy in $RetentionCompliancePolicies) { 29 | 30 | $PolicyName = $($RetentionCompliancePolicy.Name) 31 | $ConfigObject = [CAMPCheckConfig]::new() 32 | $ConfigObject.Object = "$PolicyName" 33 | $PolicyConfigData = $null 34 | 35 | if($Mode -eq "Publish") 36 | { 37 | $RetentionCompliancePolicyRules = $RetentionComplianceRules | Where-Object {($_.Policy -ieq $($RetentionCompliancePolicy.ExchangeObjectId)) -and ($_.Disabled -eq $false) -and($_.PublishComplianceTag -ne "")} 38 | foreach( $RetentionCompliancePolicyRule in $RetentionCompliancePolicyRules ) 39 | { $PublishComplianceTag = $RetentionCompliancePolicyRule.PublishComplianceTag 40 | $PublishComplianceTag = $($PublishComplianceTag.Split(","))[1] 41 | 42 | $GetLabel= $GetComplianceTag | Where-Object{ ($_.Name -eq $PublishComplianceTag) } 43 | if( -not (($GetLabel.HasRetentionAction -eq $true) -and ($GetLabel.RetentionDuration -eq "Unlimited"))) 44 | {if($null -ne $GetLabel) 45 | { 46 | $LabelPolicy =$true 47 | if ($null -eq $PolicyConfigData ) { 48 | $PolicyConfigData += "Labels : $($GetLabel.Name)" 49 | } 50 | else { 51 | $PolicyConfigData += ", $($GetLabel.Name)" 52 | } 53 | } } 54 | } 55 | } 56 | elseif($Mode -eq "Auto") 57 | { 58 | $RetentionCompliancePolicyRules = $RetentionComplianceRules | Where-Object {($_.Policy -ieq $($RetentionCompliancePolicy.ExchangeObjectId)) -and ($_.Disabled -eq $false) -and($_.ApplyComplianceTag -ne "")} 59 | foreach( $RetentionCompliancePolicyRule in $RetentionCompliancePolicyRules ) 60 | { 61 | $ApplyComplianceTag = $RetentionCompliancePolicyRule.ApplyComplianceTag 62 | 63 | 64 | $GetLabel= $GetComplianceTag | Where-Object{ ($_.ExchangeObjectId -eq $ApplyComplianceTag)} 65 | if( -not (($GetLabel.HasRetentionAction -eq $true) -and ($GetLabel.RetentionDuration -eq "Unlimited"))) 66 | {if($null -ne $GetLabel) 67 | { 68 | 69 | $LabelPolicy =$true 70 | if ($null -eq $PolicyConfigData ) { 71 | $PolicyConfigData += "Labels : $($GetLabel.Name)" 72 | } 73 | else { 74 | $PolicyConfigData += ", $($GetLabel.Name)" 75 | } 76 | } } 77 | } 78 | } 79 | $ExchangeLocation = $RetentionCompliancePolicy.ExchangeLocation 80 | $SharePointLocation = $RetentionCompliancePolicy.SharePointLocation 81 | $OneDriveLocation = $RetentionCompliancePolicy.OneDriveLocation 82 | $ModernGroupLocation = $RetentionCompliancePolicy.ModernGroupLocation 83 | $PublicFolderLocation = $RetentionCompliancePolicy.PublicFolderLocation 84 | $SkypeLocation = $RetentionCompliancePolicy.SkypeLocation 85 | 86 | $WorkloadsStatus= "" 87 | if(($RetentionCompliancePolicy.Enabled -eq $true) -and ($null -ne $PolicyConfigData )) 88 | { 89 | if(($ExchangeLocation -ne "") ) 90 | { 91 | $WorkloadsStatus+= "Exchange, " 92 | $PartialWorkloadsStatus[$ExchangePresent] = $true 93 | } 94 | if(($SharePointLocation -ne "") ) 95 | { 96 | $WorkloadsStatus += "SharePoint, " 97 | $PartialWorkloadsStatus[$SharePointPresent] = $true 98 | } 99 | if(($OneDriveLocation -ne "") ) 100 | { 101 | $WorkloadsStatus+= "OneDrive, " 102 | $PartialWorkloadsStatus[$OneDrivePresent] = $true 103 | } 104 | if(($ModernGroupLocation -ne "") ) 105 | { 106 | $WorkloadsStatus += "ModernGroup, " 107 | } 108 | if(($PublicFolderLocation -ne "") ) 109 | { 110 | $WorkloadsStatus += "ExchangePublicFolders, " 111 | } 112 | if(($SkypeLocation -ne "") ) 113 | { 114 | $WorkloadsStatus += "Skype, " 115 | } 116 | 117 | } 118 | $workloadpresent ="Workloads: $WorkloadsStatus" 119 | $workloadpresent=$workloadpresent.TrimEnd(", ") 120 | 121 | if (($WorkloadsStatus -ne "") -and ($null -ne $PolicyConfigData ) -and ($RetentionCompliancePolicy.Enabled -eq $true) ) { 122 | if ( ($LabelPolicy -eq $true) ) { 123 | $AnyPolicyEnabled =$true 124 | $Workload= $workloadpresent 125 | $ConfigObject.ConfigData = "$Workload" 126 | $ConfigObject.ConfigItem = "$PolicyConfigData" 127 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Pass") 128 | $ConfigObjectList += $ConfigObject 129 | } 130 | } 131 | elseif(($null -ne $PolicyConfigData) -and ($RetentionCompliancePolicy.Enabled -eq $true) ) { 132 | $AnyPolicyEnabled =$true 133 | $ConfigObject.ConfigData = "No workload covered" 134 | $ConfigObject.ConfigItem = "$PolicyConfigData" 135 | $ConfigObject.SetResult([CAMPConfigLevel]::Informational, "Pass") 136 | $ConfigObjectList += $ConfigObject 137 | } 138 | elseif(($null -ne $PolicyConfigData) -and ($RetentionCompliancePolicy.Enabled -ne $true) ) { 139 | $PolicyDisabled =$true 140 | $ConfigObject.ConfigData = "Policy is not enabled" 141 | $ConfigObject.ConfigItem = "$PolicyConfigData" 142 | $ConfigObject.SetResult([CAMPConfigLevel]::Informational, "Pass") 143 | $ConfigObjectList += $ConfigObject 144 | } 145 | } 146 | 147 | if (($LabelPolicy -eq $false)-and ($PolicyDisabled -eq $false)) { 148 | $ConfigObject = [CAMPCheckConfig]::new() 149 | $ConfigObject.Object = "No active policy or label defined" 150 | $ConfigObject.ConfigItem = "" 151 | $ConfigObject.ConfigData = "Affected workloads: Exchange, SharePoint, OneDrive" 152 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Fail") 153 | $ConfigObjectList += $ConfigObject 154 | 155 | } 156 | 157 | $PartialLocation="" 158 | foreach ($Workload in ($PartialWorkloadsStatus.Keys | Sort-Object -CaseSensitive) ) { 159 | 160 | if ($PartialWorkloadsStatus[$Workload] -eq $false) { 161 | if ( $PartialLocation -eq "") { 162 | $PartialLocation += "$($Workload)" 163 | }else { 164 | $PartialLocation += ", $($Workload)" 165 | } 166 | } 167 | } 168 | 169 | if(($PartialLocation -ne "") -and (($PolicyDisabled -eq $true) -or ($AnyPolicyEnabled -eq $true))) 170 | { 171 | $ConfigObject = [CAMPCheckConfig]::new() 172 | $ConfigObject.Object = "No policy defined for 1 or more workloads" 173 | $ConfigObject.ConfigItem = "" 174 | $ConfigObject.ConfigData = "Affected workloads: $PartialLocation" 175 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Fail") 176 | $ConfigObjectList += $ConfigObject 177 | } 178 | } 179 | catch { 180 | Write-Host "Error:$(Get-Date) There was an issue while running CAMP. Please try running the tool again after some time." -ForegroundColor:Red 181 | $ErrorMessage = $_.ToString() 182 | $StackTraceInfo = $_.ScriptStackTrace 183 | Write-Log -IsError -ErrorMessage $ErrorMessage -StackTraceInfo $StackTraceInfo -LogFile $LogFile -ErrorAction:SilentlyContinue 184 | } 185 | return $ConfigObjectList 186 | } 187 | -------------------------------------------------------------------------------- /Checks/check-IP101.ps1: -------------------------------------------------------------------------------- 1 | using module "..\CAMP.psm1" 2 | 3 | class IP101 : CAMPCheck { 4 | <# 5 | 6 | 7 | #> 8 | 9 | IP101() { 10 | $this.Control = "IP-101" 11 | $this.ParentArea = "Microsoft Information Protection" 12 | $this.Area = "Information Protection" 13 | $this.Name = "Create Sensitivity Labels for Sensitive or Critical Data" 14 | $this.PassText = "Your organization is using sensitivity labels to classify your information" 15 | $this.FailRecommendation = "Your organization should be using sensitivity labels to classify your information" 16 | $this.Importance = "Your organization should use sensitivity labels and policies to classify your information in SharePoint Online, OneDrive for Business, and Exchange Online. This helps categorize your most important data and effectively protect it from illicit access; it can also make it easier to investigate discovered breaches." 17 | $this.ExpandResults = $True 18 | $this.CheckType = [CheckType]::ObjectPropertyValue 19 | $this.ObjectType = "Label Policy" 20 | $this.ItemName = "Labels" 21 | $this.DataType = "Remarks" 22 | if($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovGCCHigh") 23 | { 24 | $this.Links = @{ 25 | "Overview of sensitivity labels " = "https://aka.ms/mcca-ip-docs-sensitivity-labels" 26 | "How to configure classifications for your Microsoft 365 environment" = "https://aka.ms/mcca-ip-docs-action-how-to-classification" 27 | "Compliance Center - Information Protection" = "https://aka.ms/mcca-gcch-ip-compliance-center" 28 | "Compliance Manager - IP Actions" = "https://aka.ms/mcca-gcch-ip-compliance-manager" 29 | } 30 | }elseif ($this.ExchangeEnvironmentNameForCheck -ieq "O365USGovDoD") 31 | { 32 | $this.Links = @{ 33 | "Overview of sensitivity labels " = "https://aka.ms/mcca-ip-docs-sensitivity-labels" 34 | "How to configure classifications for your Microsoft 365 environment" = "https://aka.ms/mcca-ip-docs-action-how-to-classification" 35 | "Compliance Center - Information Protection" = "https://aka.ms/mcca-dod-ip-compliance-center" 36 | "Compliance Manager - IP Actions" = "https://aka.ms/mcca-dod-ip-compliance-manager" 37 | } 38 | }else 39 | { 40 | $this.Links = @{ 41 | "Overview of sensitivity labels " = "https://aka.ms/mcca-ip-docs-sensitivity-labels" 42 | "How to configure classifications for your Microsoft 365 environment" = "https://aka.ms/mcca-ip-docs-action-how-to-classification" 43 | "Compliance Center - Information Protection" = "https://aka.ms/mcca-ip-compliance-center" 44 | "Compliance Manager - IP Actions" = "https://aka.ms/mcca-ip-compliance-manager" 45 | } 46 | } 47 | } 48 | 49 | <# 50 | 51 | RESULTS 52 | 53 | #> 54 | 55 | GetResults($Config) { 56 | if (($Config["GetLabel"] -eq "Error") -or ($Config["GetLabelPolicy"] -eq "Error")) { 57 | $this.Completed = $false 58 | } 59 | else { 60 | $ConfigObjectList = @() 61 | 62 | $LabelPolicyExists = $False 63 | 64 | $UtilityFiles = Get-ChildItem "$PSScriptRoot\..\Utilities" 65 | 66 | ForEach ($UtilityFile in $UtilityFiles) { 67 | . $UtilityFile.FullName 68 | } 69 | $LogFile = $this.LogFile 70 | $LabelAssociation = Get-LabelClassification -LogFile $LogFile 71 | $SubLabels = $LabelAssociation.sublabels 72 | $ParentLabels = $LabelAssociation.parentlabels 73 | $ParentSubLabelAssociation = $LabelAssociation.parentsublabelassociation 74 | $ParentNameForSubLabelAssociation = $LabelAssociation.parentnameforsublabelassociation 75 | 76 | $AllGlobalPolicy = 0 77 | $ScopedGlobalPolicy = 0 78 | ForEach ($Policies in $Config["GetLabelPolicy"]) { 79 | $LabelPolicy = $Policies 80 | $ConfigObject = [CAMPCheckConfig]::new() 81 | $PolicyParentLabelCount = 0 82 | $PolicySubLabelCount = 0 83 | $ParentLabelsDefinedinPolicy = "None" 84 | $SubLabelsDefinedinPolicy = "None" 85 | if ($LabelPolicy.Enabled -eq $true) { 86 | foreach ($LabelConfigured in $LabelPolicy.Labels) { 87 | if ($SubLabels.containsKey($LabelConfigured)) { 88 | $PolicySubLabelCount++ 89 | if ($SubLabelsDefinedinPolicy -eq "None") { 90 | $SubLabelsDefinedinPolicy = $LabelConfigured 91 | } 92 | else { 93 | $SubLabelsDefinedinPolicy += ", $LabelConfigured" 94 | } 95 | } 96 | if ($ParentLabels.containsKey($LabelConfigured)) { 97 | $PolicyParentLabelCount++ 98 | if ($ParentLabelsDefinedinPolicy -eq "None") { 99 | $ParentLabelsDefinedinPolicy = $LabelConfigured 100 | } 101 | else { 102 | $ParentLabelsDefinedinPolicy += ", $LabelConfigured" 103 | } 104 | } 105 | 106 | } 107 | $ExchangeLocation = $($LabelPolicy.ExchangeLocation) 108 | if ((@($ExchangeLocation) -like 'All').Count -gt 0) { 109 | $AllGlobalPolicy++ 110 | } 111 | else { 112 | $ScopedGlobalPolicy++ 113 | } 114 | if ($PolicyParentLabelCount -le 9) { 115 | $ConfigObject.Object = $LabelPolicy.Name 116 | $ConfigObject.ConfigItem = "Parent Labels : $ParentLabelsDefinedinPolicy
Sub Labels : $SubLabelsDefinedinPolicy" 117 | $ConfigObject.ConfigData = "Enabled Workload: $($LabelPolicy.ExchangeLocation) $($LabelPolicy.ModernGroupLocation)" 118 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Pass") 119 | $ConfigObjectList += $ConfigObject 120 | } 121 | else { 122 | $ConfigObject.Object = "$($LabelPolicy.Name)" 123 | $ConfigObject.ConfigItem = "Parent Labels : $ParentLabelsDefinedinPolicy
Sub Labels : $SubLabelsDefinedinPolicy" 124 | $ConfigObject.ConfigData = "No of parent Labels is more than 8." 125 | $ConfigObject.InfoText = "You currently have $($PolicyParentLabelCount) Global policies defined. We have found 8 parent labels to be optimal for most organizations" 126 | $ConfigObject.SetResult([CAMPConfigLevel]::Recommendation, "Fail") 127 | $ConfigObjectList += $ConfigObject 128 | 129 | } 130 | $LabelPolicyExists = $true 131 | } 132 | else { 133 | $ConfigObject.Object = "$($LabelPolicy.Name)" 134 | $ConfigObject.ConfigItem = "$($LabelPolicy.Labels)" 135 | $ConfigObject.ConfigData = " Policy is not enabled " 136 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Fail") 137 | $ConfigObjectList += $ConfigObject 138 | } 139 | $this.AddConfig($ConfigObject) 140 | $LabelPolicyExists = $true 141 | 142 | 143 | } 144 | 145 | if ($AllGlobalPolicy -gt 5) { 146 | $ConfigObject = [CAMPCheckConfig]::new() 147 | $ConfigObject.Object = "High Number of Global policies defined" 148 | $ConfigObject.ConfigItem = "No of policies : $AllGlobalPolicy " 149 | $ConfigObject.ConfigData = "No of Global policies defined is more than 5." 150 | $ConfigObject.InfoText = "You currently have $($AllGlobalPolicy) Global policies defined. We have found 5 Global Policy to be optimal for most organizations. Please consider reducing your current global policies count." 151 | $ConfigObject.SetResult([CAMPConfigLevel]::Recommendation, "Fail") 152 | $ConfigObjectList += $ConfigObject 153 | $this.AddConfig($ConfigObject) 154 | } 155 | elseif ($AllGlobalPolicy -gt 10 ) { 156 | $ConfigObject = [CAMPCheckConfig]::new() 157 | $ConfigObject.Object = "High Number of Global policies defined" 158 | $ConfigObject.ConfigItem = "No of policies : $AllGlobalPolicy " 159 | $ConfigObject.ConfigData = "You currently have $($AllGlobalPolicy) Global policies defined. We have found 5 Global Policy to be optimal for most organizations" 160 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Fail") 161 | $ConfigObjectList += $ConfigObject 162 | $this.AddConfig($ConfigObject) 163 | 164 | } 165 | if ($ScopedGlobalPolicy -gt 10 -and $ScopedGlobalPolicy -lt 30 ) { 166 | $ConfigObject = [CAMPCheckConfig]::new() 167 | $ConfigObject.Object = "High Number of Scoped policies defined" 168 | $ConfigObject.InfoText = "You currently have $($ScopedGlobalPolicy) Scoped policies defined. We have found 10 Scoped Policy to be optimal for most organizations. Please consider reducing your current scoped policies count." 169 | $ConfigObject.ConfigItem = "No of policies : $ScopedGlobalPolicy " 170 | $ConfigObject.ConfigData = "No of parent Labels defined is more than 10." 171 | $ConfigObject.SetResult([CAMPConfigLevel]::Recommendation, "Fail") 172 | $ConfigObjectList += $ConfigObject 173 | $this.AddConfig($ConfigObject) 174 | } 175 | elseif ($ScopedGlobalPolicy -gt 29 ) { 176 | $ConfigObject = [CAMPCheckConfig]::new() 177 | $ConfigObject.Object = "High Number of Scoped policies defined" 178 | $ConfigObject.ConfigItem = "No of policies : $ScopedGlobalPolicy " 179 | $ConfigObject.ConfigData = "You currently have $($ScopedGlobalPolicy) Scoped policies defined. We have found 10 Scoped Policy to be optimal for most organizations." 180 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Fail") 181 | $ConfigObjectList += $ConfigObject 182 | $this.AddConfig($ConfigObject) 183 | 184 | } 185 | if ($ParentLabels.count -gt 5) { 186 | $ConfigObject = [CAMPCheckConfig]::new() 187 | $ConfigObject.Object = "High number of parent labels defined" 188 | $ParentLabelsString = $null 189 | foreach ($ParentLabelkey in $ParentLabels.Keys) { 190 | if ($null -ne $ParentLabelsString) { 191 | $ParentLabelsString += ", $ParentLabelkey" 192 | } 193 | else { 194 | $ParentLabelsString += "$ParentLabelkey" 195 | } 196 | } 197 | $ConfigObject.ConfigItem = "Parent Labels : $($ParentLabelsString)" 198 | $ConfigObject.ConfigData = "No. of parent labels defined is more than 5." 199 | $ConfigObject.InfoText = "You currently have $($ParentLabels.count) parent labels defined. We have found 5 parent labels to be optimal for most organizations. Please consider reducing your current label count. " 200 | $ConfigObject.SetResult([CAMPConfigLevel]::Recommendation, "Pass") 201 | $ConfigObjectList += $ConfigObject 202 | $this.AddConfig($ConfigObject) 203 | 204 | } 205 | elseif ($ParentLabels.count -gt 10 ) { 206 | $ConfigObject = [CAMPCheckConfig]::new() 207 | $ConfigObject.Object = "High number of parent labels defined" 208 | $ParentLabelsString = $null 209 | foreach ($ParentLabelkey in $ParentLabels.Keys) { 210 | if ($null -ne $ParentLabelsString) { 211 | $ParentLabelsString += ", $ParentLabelkey" 212 | } 213 | else { 214 | $ParentLabelsString += "$ParentLabelkey" 215 | } 216 | } 217 | $ConfigObject.ConfigItem = "Parent Labels : $($ParentLabelsString)" 218 | $ConfigObject.ConfigData = "You currently have $($ParentLabels.count) parent labels defined. We have found 5 parent labels to be optimal for most organizations." 219 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Fail") 220 | $ConfigObjectList += $ConfigObject 221 | $this.AddConfig($ConfigObject) 222 | 223 | } 224 | 225 | # For >5 sublabel count 226 | 227 | if ($($($ParentSubLabelAssociation.Keys).count) -gt 0) { 228 | $ParentLabelsWithHighSublabelCountString = $null 229 | foreach ($ParentLabelID in $($ParentSubLabelAssociation.Keys)) { 230 | $AllSubLabels = $ParentSubLabelAssociation[$ParentLabelID] #all sublabels within a parent label 231 | 232 | if ($($AllSubLabels.count) -gt 5) { 233 | if ($null -ne $ParentLabelsWithHighSublabelCountString) { 234 | $ParentLabelsWithHighSublabelCountString += ", $($ParentNameForSubLabelAssociation[$ParentLabelID])" 235 | } 236 | else { 237 | $ParentLabelsWithHighSublabelCountString += "$($ParentNameForSubLabelAssociation[$ParentLabelID])" 238 | } 239 | } 240 | 241 | } 242 | if ($null -ne $ParentLabelsWithHighSublabelCountString) { 243 | $ConfigObject = [CAMPCheckConfig]::new() 244 | $ConfigObject.Object = "High number of sub-labels defined" 245 | $ConfigObject.ConfigItem = "Parent Labels : $($ParentLabelsWithHighSublabelCountString)" 246 | $ConfigObject.ConfigData = "No. of sub-labels defined is more than 5." 247 | $ConfigObject.InfoText = "You currently have more than 5 sub-labels defined for 1 or more parent labels. We have found 5 sub-labels to be optimal for most organizations. Please consider reducing your current sub-label count." 248 | $ConfigObject.SetResult([CAMPConfigLevel]::Recommendation, "Pass") 249 | $ConfigObjectList += $ConfigObject 250 | $this.AddConfig($ConfigObject) 251 | } 252 | } 253 | 254 | 255 | If ($LabelPolicyExists -eq $False) { 256 | $ConfigObject = [CAMPCheckConfig]::new() 257 | $ConfigObject.Object = "No Active Policy defined" 258 | $ConfigObject.ConfigItem = "No Active Policy defined" 259 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Fail") 260 | $ConfigObjectList += $ConfigObject 261 | $this.AddConfig($ConfigObject) 262 | } 263 | 264 | $hasRemediation = $this.Config | Where-Object { $_.RemediationAction -ne ''} 265 | if ($($hasremediation.count) -gt 0) 266 | { 267 | $this.CAMPRemediationInfo = New-Object -TypeName CAMPRemediationInfo -Property @{ 268 | RemediationAvailable = $True 269 | RemediationText = "You need to connect to Security & Compliance Center PowerShell to execute the below commands. Please follow steps defined in Connect to Security & Compliance Center PowerShell." 270 | } 271 | } 272 | $this.Completed = $True 273 | } 274 | } 275 | 276 | } 277 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | Configuration Analyzer for Microsoft Purview (CAMP) is a tool which, on execution, generates a report highlighting known issues in your compliance configurations in achieving data protection guidelines and recommends best practices to follow. 4 | 5 | # What is Configuration Analyzer for Microsoft Purview (CAMP)? 6 | 7 | It is a PowerShell-based utility that will fetch your tenant’s current configurations & validate these configurations against Microsoft 365 recommended best practices. These best practices are based on a set of controls that include key regulations and standards for data protection and general data governance. CAMP then provides you with an actionable status report for improving your compliance posture. 8 | 9 | # Why should I use it? 10 | 11 | Often tenants face challenges in diagnosing their compliance posture & ensuring that they have the right configurations in place to protect their environment completely. These are largely manual processes which tend to be time consuming & allow for human error. Furthermore, with the evolving compliance landscape the risk of blind spots also increases. 12 | CAMP is a diagnostic tool that will report the status of your current configurations. This allows you to focus efforts more on making the right configurations. 13 | 14 | # What is in scope? 15 | 16 | This version will provide you recommendations for the M365 Compliance solutions listed below. We will keep adding more solutions & richer recommendations in future versions of this tool. 17 | 18 | 1. Microsoft Information Protection 19 | a. Data Loss Prevention 20 | b. Information Protection 21 | 2. Microsoft Information Governance 22 | a. Information Governance 23 | b. Records Management 24 | 3. Insider Risk 25 | a. Communication Compliance 26 | b. Insider Risk Management 27 | 4. Discovery & Response 28 | a. Audit 29 | b. eDiscovery 30 | 31 | # That is awesome! How do I run it? 32 | 33 | # Pre-Requisites 34 | 35 | Before running the tool, you should confirm your Microsoft 365 subscription and any add-ons. To access and use CAMP, your organization must have one of the following subscriptions or add-ons: 36 | 37 | • Microsoft 365 E5 subscription (paid or trial version) 38 | • Microsoft 365 E3 subscription + the Microsoft 365 E5 Compliance add-on 39 | 40 | You will be able to run this tool without an E5 subscription or M365 E5 Compliance add-on, but CAMP will still report statuses for E5 workloads & capabilities. 41 | 42 | For running the tool: 43 | 44 | 45 | 1. You must have PowerShell version 5.1 or above to run this tool. 46 | 47 | 2. You must have Exchange Online PowerShell module (You can follow 48 | either of the following 2 methods to download the same) 49 | 50 | * Exchange Online PowerShell V2 module that is available via the 51 | PowerShell gallery: 52 | 53 | > Install-Module -Name ExchangeOnlineManagement 54 | 55 | * Exchange Online PowerShell module () 56 | 57 | 3. You must have appropriate role/user permissions to be able to run 58 | this tool. The following table provides details of which roles will 59 | have access to which sections of the report. 60 | 61 | Other roles within the organisation (not listed in the table below) may 62 | not be able to run the tool or they may be able to run the tool with 63 | limited information in the final report. 64 | 65 | 66 | |User Role |MIP | | MIG | |Insider Risk | |Discovery & Response | | 67 | |------------------------------------|---------|------------|--------------|----------------------|---------|--------|-----------|---------------- | 68 | | |**DLP** |**IP** |**IG** |**RM** |**IRM** |**CC** |**Audit** |**eDiscovery** | 69 | |Azure Information Protection admin |No |No1 |No |No |No |No |No 4 |No | 70 | |Compliance admin |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes | 71 | |Compliance Data Admin |Yes |Yes2 |Yes |Yes |Yes |Yes3 |Yes5 |No | 72 | |Customer Lockbox access approver |No |No |No |No |No |No |No |No | 73 | |Exchange Admin |No |No1 |No |No |No |No |No4 |No | 74 | |Global admin |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes | 75 | |Global reader |Yes |Yes |Yes |Yes |No |No |Yes |No | 76 | |Helpdesk admin |No |No1 |No |No |No |No |No4 |No | 77 | |Non-Admin User |No |No |No |No |No |No |No |No | 78 | |Reports reader |No |No |No |No |No |No |No |No | 79 | |Security admin |Yes |Yes2 |No |No |No |No |Yes5 |No | 80 | |Security operator |Yes |No |No |No |No |No |Yes5 |No | 81 | |Security reader |Yes |Yes2 |No |No |No |No |Yes5 |No | 82 | |Service support admin |No |No |No |No |No |No |No |No | 83 | |SharePoint admin |No |No |No |No |No |No |No |No | 84 | |Teams service admin |No |No |No |No |No |No |No |No | 85 | |User admin |No |No |No |No |No |No |No |No | 86 | 87 | Exceptions: 88 | 89 | 1 User will not be able generate report for IP apart from "Use IRM for Exchange Online" section. 90 | 91 | 2 User will be able generate report for IP apart from "Use IRM for Exchange Online" section. 92 | 93 | 3 User will be able generate report for IP apart from "Enable Communication Compliance in O365" section. 94 | 95 | 4 User will not be able generate report for IP apart from "Enable Auditing in Office 365" section. 96 | 97 | 5 User will be able generate report for IP apart from "Enable Auditing in Office 365" section. 98 | 99 | # Install Guide 100 | 101 | Step 1: Open PowerShell in administrator mode 102 | 103 | Step 2: Install CAMP 104 | 105 | Install-Module -Name CAMP 106 | 107 | Step 3: Generate CAMP Report 108 | 109 | Use the following cmdlet to generate the CAMP report. 110 | Get-CAMPReport 111 | 112 | This will generate a report based on the geolocation of your tenant. If an error occurs while fetching your tenant’s geolocation, you will get a report covering all supported geolocations. 113 | 114 | You can learn more about this cmdlet by running the following. 115 | 116 | Get-Help Get-CAMPReport 117 | 118 | Input Parameters 119 | You can also get a tailored report based on specific input parameters listed below. 120 | 121 | 1. Geolocation 122 | 123 | Get-CAMPReport -Geo @(1,7) 124 | This will generate a report based on the geolocations entered by you.You need to input appropriate numbers from the following list corresponding to the regions. 125 | Input Region 126 | 1 Asia-Pacific 127 | 2 Australia 128 | 3 Canada 129 | 4 Europe (excl. France) / Middle East / Africa 130 | 5 France 131 | 6 India 132 | 7 Japan 133 | 8 Korea 134 | 9 North America (excl. Canada) 135 | 10 South America 136 | 11 South Africa 137 | 12 Switzerland 138 | 13 United Arab Emirates 139 | 14 United Kingdom 140 | 141 | Note: As an add-on, the report will always include CAMP supported international sensitive information types like SWIFT Code, Credit Card Number etc. 142 | 143 | 2. Solutions 144 | 145 | Get-CAMPReport -Solution @(1,7) 146 | This will generate a report only for the solutions entered by you. You need to input appropriate numbers from the following list corresponding to the solution. 147 | Input Solution 148 | 1 Data Loss Prevention 149 | 2 Information Protection 150 | 3 Information Governance 151 | 4 Records Management 152 | 5 Communication Compliance 153 | 6 Insider Risk Management 154 | 7 Audit 155 | 8 eDiscovery 156 | 157 | 3. Multiple Parameters 158 | 159 | Get-CAMPReport -Solution @(1,7) -Geo @(9) 160 | 161 | This will generate a report only on for the solutions entered by you and based on the regions you have selected. 162 | In either of the cases, there will be a prompt to enter your credentials. Once you enter your credentials, CAMP will run for a while and an HTML report will be generated. 163 | 164 | 4. ExchangeEnvironmentName 165 | 166 | This will generate CAMP report for Security & Compliance Center PowerShell in a Microsoft 365 DoD organization or Microsoft GCC High organization 167 | 168 | O365USGovDoD 169 | This will generate CAMP report for Security & Compliance Center PowerShell in a Microsoft 365 DoD organization. 170 | 171 | Get-CAMPReport -ExchangeEnvironmentName O365USGovDoD 172 | 173 | O365USGovGCCHigh 174 | This will generate CAMP report for Security & Compliance Center PowerShell in a Microsoft GCC High organization. 175 | 176 | Get-CAMPReport -ExchangeEnvironmentName O365USGovGCCHigh 177 | 178 | 5. TurnOffDataCollection 179 | 180 | Get-CAMPReport -TurnOffDataCollection 181 | 182 | If you wish to switch off data collection use this parameter. 183 | 184 | # License 185 | We use the following open source components in order to generate the report: 186 | • Bootstrap, MIT License - https://getbootstrap.com/docs/4.0/about/license/ 187 | • Fontawesome, CC BY 4.0 License - https://fontawesome.com/license/free 188 | • clipboard.js v1.5.3, MIT License - https://cdn.jsdelivr.net/clipboard.js/1.5.3/clipboard.min.js 189 | 190 | 191 | ## Frequently Asked Questions (FAQ) 192 | 193 | ### Will this tool make any changes to my existing settings, policies, etc.? 194 | 195 | CAMP is a diagnostic tool that is "read-only". It fetches information 196 | about your current configurations to generate a report but will not 197 | alter any of your existing configurations. 198 | 199 | ### What different sections do I see in my report? 200 | 201 | The report provides you with: 202 | 203 | * Solutions summary: It provides a break-down of statuses at a 204 | solution level. Each solution has counters that tell you how many 205 | recommendations are informational, require improvement and are OK. 206 | 207 | * Solution drill-down: Following solutions summary, each solution has 208 | a separate section that provides detailed information about 209 | configurations & their status. 210 | 211 | * Each solution may have 1 or more improvement actions which will 212 | further be broken down into finer configurations. CAMP will 213 | provide you a status both at an improvement action level & also 214 | for finer configurations. 215 | 216 | ### Can I generate report for specific sections within the report? 217 | 218 | Yes, you can generate report for specific sections within the report. 219 | You can use the solution input parameter `--solution ` to generate the report for a specific solution from the 221 | following list: 222 | 223 | |Input |Solution | 224 | |-------|-------------------------- | 225 | |1 |Data Loss Prevention | 226 | |2 |Information Protection | 227 | |3 |Information Governance | 228 | |4 |Records Management | 229 | |5 |Communication Compliance | 230 | |6 |Insider Risk Management | 231 | |7 |Audit | 232 | |8 |eDiscovery | 233 | 234 | For e.g. If you wanted to create report for the DLP solution only then 235 | you can run the following command: 236 | 237 | ```powershell 238 | Get-CAMPReport --solution @(1) 239 | ``` 240 | 241 | You can learn more about this input parameter in the Input Parameters 242 | section within the Install Guide above. 243 | 244 | ### What does Recommendation, Informational, Improvement & OK messages mean? 245 | 246 | All recommendations provided by CAMP report are categorized in 3 types 247 | of status: 248 | 249 | * Recommendations: These are best practices that your tenant 250 | should follow.\ 251 | *Note: The support for these messages is limited in the current 252 | version so you may not see any recommendations in your report.* 253 | 254 | * Informational: These messages/statuses represent information 255 | in your current environment & are non-actionable in nature. 256 | 257 | * Improvement: These messages/statuses highlight areas that 258 | need your attention & are actionable. Sections which are marked as 259 | "Improvement" would generally have 1 or more configurations marked 260 | as "Improvement". 261 | 262 | * OK: These messages/statuses indicate that a given area is configured efficiently to meet data protection baselines. 263 | 264 | ### Why don't I see my tenant's name on the report? 265 | 266 | Due to a technical error, the tool would not have been able to fetch 267 | your tenant's name. In the event of such error, you may not see your 268 | tenant name on the report. Please try running the tool again after some 269 | time. If the issue persists, please reach out to us at 270 | [MCCAhelp\@microsoft.com](mailto:mecahelp@microsoft.com) and/or contact 271 | your Microsoft partner. 272 | 273 | ### Why do I see "No active policy defined" when I already have policies defined? 274 | 275 | The policies created by you may be protecting a subset of information, 276 | workloads, user groups and/or other criteria. "No active policy defined" 277 | highlights the areas that are not protected by your current policies and 278 | need an action on your part. 279 | 280 | We provide "Remediation Scripts" which you can run from your PowerShell 281 | console & the required policies will automatically be set up. 282 | 283 | Please refer to "Remarks" section in your report to understand why you 284 | are seeing "Improvement". If you still have concerns, please reach out 285 | to us at [MCCAhelp\@microsoft.com](mailto:mecahelp@microsoft.com) or 286 | contact your Microsoft partner. 287 | 288 | ### Why do I see "Policy defined but not protected on 1 or more workloads" when I already have policies defined? 289 | 290 | Often there is a case where a given area (sensitive information, 291 | workloads, user groups and/or other criteria) may be protected in 1 or 292 | more policies in your environment but would not be protected across your 293 | entire environment. 294 | 295 | E.g. Your current policy configurations may U.S. / U.K. Passport Number 296 | on SharePoint & Exchange but not on OneDrive & Teams. This puts you at 297 | risk. 298 | 299 | To avoid such cases, CAMP will highlight all the affected areas. You 300 | will need to review these and either tweak your current policies and/or 301 | create new ones to accommodate these areas. 302 | 303 | ### What are remediation scripts? 304 | 305 | When CAMP identifies if your current policies have zero coverage for 306 | certain sensitive information types, it provides you with "Remediation 307 | Scripts" to help you avoid the hassle of manually setting up these 308 | policies. These policies will be created in *Test* mode and you will 309 | still have review & enable it manually. 310 | 311 | You should review script parameters & then run these scripts from your *Windows PowerShell ISE* console. 312 | You would need to connect to [Connect to Security & Compliance Center PowerShell](https://docs.microsoft.com/en-us/powershell/exchange/connect-to-scc-powershell?view=exchange-ps) or [Connect to Exchange Online Center PowerShell](https://docs.microsoft.com/en-us/powershell/exchange/connect-to-exchange-online-powershell?view=exchange-ps) to execute these scripts. On successful execution of the scripts, the 313 | required policies will automatically be set up. 314 | 315 | Note: These scripts are pre-configured and may need tweaking to achieve 316 | best results for your organization. We are working on improving these 317 | scripts in future versions of this tool. 318 | 319 | ### Why is the report asking me to protect Sensitive Information Types which I do not have in my environment? 320 | 321 | This version of the tool aims to protect all possible sensitive 322 | information types across multiple geographies and/or industries. 323 | 324 | Future versions of this tool will provide recommendations to you based 325 | on the nature of information you have in your environment. 326 | 327 | ### Can I generate the report to get recommendations for Sensitive Information Types applicable to my tenant's geographic regions? 328 | 329 | Yes, you can generate the report for specific geographic regions. 330 | 331 | By default, the tool will generate a report based on the geolocation for 332 | your tenant. If you wish to run the report for specific geos then while 333 | running the `Get-CAMPReport` cmdlet, you can input an extra parameter by 334 | `--Geo` followed by 1 or more region numbers supported by CAMP. 335 | 336 | Please refer the *Install Guide* section above for more detailed steps. 337 | 338 | ### How can I add my organization's Logo in the report? 339 | 340 | You can quickly add your organization's logo in the report by replacing the image file present in the Image folder with your logo's image with same name and file extension (i.e. logo.jpg). Please note that your logo image should be able to accurately fit within the width of 250px and height of 150px respectively. 341 | 342 | ### How do I save my report? 343 | 344 | Please use the "Print" button provided on top right corner of the report 345 | to export a PDF (subject to your browser and/or system support for 346 | printing as a PDF) or print a physical copy of your report. 347 | 348 | # This tool is awesome! How do I provide feedback and suggestions for future versions? 349 | Please share your feedback & suggestions with us using this [form](https://forms.office.com/Pages/ResponsePage.aspx?id=v4j5cvGGr0GRqy180BHbR-ItstQd6pNMqw0W9LKA5vxUOFNGUFgxRDJFTkg3VE5NQTQwTUVVVDNVMi4u). We are dying to hear from you. :) 350 | 351 | # Contributing 352 | 353 | This project welcomes contributions and suggestions. Most contributions require you to agree to a 354 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us 355 | the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com. 356 | 357 | When you submit a pull request, a CLA bot will automatically determine whether you need to provide 358 | a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions 359 | provided by the bot. You will only need to do this once across all repos using our CLA. 360 | 361 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 362 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or 363 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 364 | 365 | # Trademark 366 | 367 | Trademarks This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft's Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party's policies. 368 | -------------------------------------------------------------------------------- /Utilities/DLPValidationUtility.ps1: -------------------------------------------------------------------------------- 1 | 2 | using module "..\CAMP.psm1" 3 | $ExchangeString = "Exchange" 4 | $SharePointString = "SharePoint" 5 | $OneDriveString = "OneDrive" 6 | $TeamsString = "Teams" 7 | $DevicesString = "Devices" 8 | 9 | Function Get-DLPPolicyValidation { 10 | Param 11 | ( 12 | $SensitiveTypes, 13 | $Config, 14 | $LogFile, 15 | $Name 16 | ) 17 | $ConfigObjectList = @() 18 | try { 19 | $SensitiveTypesWorkloadMapping = @() 20 | foreach ($SIT in $SensitiveTypes.keys) { 21 | 22 | $SensitiveTypesWorkloadMapping += New-Object -TypeName PSObject @{ 23 | Name = $SIT 24 | $ExchangeString = $false 25 | $SharePointString = $false 26 | $OneDriveString = $false 27 | $TeamsString = $false 28 | $DevicesString = $false 29 | 30 | } 31 | } 32 | #Getting Custom SIT 33 | if($($Config["GetDLPCustomSIT"]) -ne "Error") 34 | { 35 | $CustomSIT = $($Config["GetDLPCustomSIT"]).Name 36 | $CustomSITHashTable = @{} 37 | foreach($SIT in $CustomSIT) 38 | { 39 | $CustomSITHashTable[$SIT] = $null 40 | } 41 | 42 | } 43 | 44 | ForEach ($CompliancePolicy in $Config["GetDlpCompliancePolicy"]) { 45 | $PolicySensitiveType = New-Object System.Collections.Generic.HashSet[String] 46 | $PolicySensitiveType = Get-PolicySensitiveType -Config $Config -CompliancePolicy $CompliancePolicy -SensitiveTypes $SensitiveTypes 47 | if($($Config["GetDLPCustomSIT"]) -ne "Error") 48 | { 49 | $CustomSensitiveType = Get-PolicySensitiveType -Config $Config -CompliancePolicy $CompliancePolicy -SensitiveTypes $CustomSITHashTable 50 | $CustomSensitiveTypeText = $null 51 | foreach ($SIT in $CustomSensitiveType) { 52 | if ($null -ne $CustomSensitiveTypeText) { 53 | $CustomSensitiveTypeText += ", $SIT" 54 | } 55 | else { 56 | $CustomSensitiveTypeText += "$SIT" 57 | } 58 | } 59 | } 60 | if (($CompliancePolicy.Mode -ieq "enable") ) { 61 | $WorkloadsStatus = Get-AllLocationenabled -CompliancePolicy $CompliancePolicy 62 | $EnabledWorkload = $null 63 | $DisabledWorkload = "" 64 | $PolicySensitiveTypeText = $null 65 | foreach ($Workload in ($WorkloadsStatus.Keys | Sort-Object -CaseSensitive)) { 66 | if ($WorkloadsStatus[$Workload] -eq $true) { 67 | if ( $null -ne $EnabledWorkload) { 68 | $EnabledWorkload += ", $($Workload)" 69 | } 70 | else { 71 | $EnabledWorkload += "$($Workload)" 72 | } 73 | foreach ($SIT in $PolicySensitiveType) { 74 | if ($SITToChange = $SensitiveTypesWorkloadMapping | Where-Object { $_.Name -eq $SIT }) { 75 | $SITToChange.$($Workload) = $true 76 | } 77 | } 78 | 79 | } 80 | else { 81 | $DisabledWorkload += "$($Workload) " 82 | } 83 | } 84 | 85 | foreach ($SIT in $PolicySensitiveType) { 86 | if ($null -ne $PolicySensitiveTypeText) { 87 | $PolicySensitiveTypeText += ", $SIT" 88 | } 89 | else { 90 | $PolicySensitiveTypeText += "$SIT" 91 | } 92 | } 93 | 94 | 95 | If ($PolicySensitiveType.Count -ne 0 ) { 96 | $ConfigObject = [CAMPCheckConfig]::new() 97 | $Workload = $CompliancePolicy.Workload 98 | $ConfigObject.Object = "$($CompliancePolicy.Name)" 99 | if($null -eq $CustomSensitiveTypeText) 100 | { 101 | $ConfigObject.ConfigItem = "$PolicySensitiveTypeText" 102 | 103 | } 104 | else 105 | { 106 | $ConfigObject.ConfigItem = "$PolicySensitiveTypeText
Custom SIT : $CustomSensitiveTypeText" 107 | } 108 | $ConfigData = "" 109 | $ConfigObjectResult = @{} 110 | $ConfigObjectResult = Set-ExchangeNotAllLocationEnabledConfigObject -ConfigObjectResult $ConfigObjectResult -CompliancePolicy $CompliancePolicy 111 | $ConfigObjectResult = Set-SharePointNotAllLocationEnabledConfigObject -ConfigObjectResult $ConfigObjectResult -CompliancePolicy $CompliancePolicy 112 | $ConfigObjectResult = Set-OneDriveNotAllLocationEnabledConfigObject -ConfigObjectResult $ConfigObjectResult -CompliancePolicy $CompliancePolicy 113 | $ConfigObjectResult = Set-TeamsNotAllLocationEnabledConfigObject -ConfigObjectResult $ConfigObjectResult -CompliancePolicy $CompliancePolicy 114 | $ConfigObjectResult = Set-DevicesNotAllLocationEnabledConfigObject -ConfigObjectResult $ConfigObjectResult -CompliancePolicy $CompliancePolicy 115 | $ConfigData = "Enabled Workloads : $($EnabledWorkload)
" 116 | foreach ($ConfigResult in $ConfigObjectResult.keys) { 117 | $ConfigData += "$ConfigResult : $($ConfigObjectResult[$ConfigResult])
" 118 | 119 | } 120 | $NotInOrganizationAccessScope = $Config["GetDlpComplianceRule"] | Where-Object {$_.AccessScope -eq "NotInOrganization" -and $_.ParentPolicyName -eq "$($CompliancePolicy.Name)"} 121 | if($null -ne $NotInOrganizationAccessScope) 122 | { 123 | $ConfigData += "Access Scope: For users outside organization
" 124 | 125 | }else{ 126 | $ConfigData += "Access Scope: For users inside organization
" 127 | } 128 | $ConfigObject.ConfigData = "$ConfigData" 129 | $ConfigObject.SetResult([CAMPConfigLevel]::Informational, "Pass") 130 | $ConfigObjectList += $ConfigObject 131 | 132 | } 133 | 134 | } 135 | else { 136 | If ($PolicySensitiveType.Count -ne 0 ) { 137 | $ConfigObject = [CAMPCheckConfig]::new() 138 | $Workload = $CompliancePolicy.Workload 139 | $ConfigObject.Object = "$($CompliancePolicy.Name)" 140 | $PolicySensitiveTypeText = $null 141 | foreach ($SIT in $PolicySensitiveType) { 142 | if ($null -ne $PolicySensitiveTypeText) { 143 | $PolicySensitiveTypeText += ", $SIT" 144 | } 145 | else { 146 | $PolicySensitiveTypeText += "$SIT" 147 | } 148 | } 149 | if($null -eq $CustomSensitiveTypeText) 150 | { 151 | $ConfigObject.ConfigItem = "$PolicySensitiveTypeText" 152 | 153 | } 154 | else 155 | { 156 | $ConfigObject.ConfigItem = "$PolicySensitiveTypeText
Custom SIT : $CustomSensitiveTypeText" 157 | } 158 | $Mode = $($CompliancePolicy.Mode) 159 | if ( $Mode -eq "TestWithoutNotifications") { 160 | $Mode = "test without notifications" 161 | } 162 | elseif ($Mode -eq "Disable") { 163 | $Mode = "disabled" 164 | } 165 | elseif ( $Mode -eq "TestWithNotifications") { 166 | $Mode = "test with notifications" 167 | } 168 | 169 | $ConfigObject.ConfigData = "Policy is in $Mode state." 170 | $ConfigObject.SetResult([CAMPConfigLevel]::Informational, "Pass") 171 | 172 | $ConfigObjectList += $ConfigObject 173 | } 174 | } 175 | 176 | } 177 | $ConfigObjectList = Get-SensitiveTypesNotEnabled -SensitiveTypesWorkloadMapping $SensitiveTypesWorkloadMapping -ConfigObjectList $ConfigObjectList -LogFile $LogFile 178 | 179 | } 180 | catch { 181 | Write-Host "Error:$(Get-Date) There was an issue while running CAMP. Please try running the tool again after some time." -ForegroundColor:Red 182 | $ErrorMessage = $_.ToString() 183 | $StackTraceInfo = $_.ScriptStackTrace 184 | Write-Log -IsError -ErrorMessage $ErrorMessage -StackTraceInfo $StackTraceInfo -LogFile $LogFile -ErrorAction:SilentlyContinue 185 | 186 | } 187 | Return $ConfigObjectList 188 | } 189 | 190 | Function Get-NoPolicyRemediationAction { 191 | [CmdletBinding()] 192 | Param 193 | ( 194 | $Name, 195 | $PendingSensitiveTypes 196 | 197 | ) 198 | $RemediationActionScript = "" 199 | 200 | $PendingSensitiveTypesList = $PendingSensitiveTypes.split(",") 201 | $LowCountSenstiveinfodetails = "" 202 | $HighCountSenstiveinfodetails = "" 203 | 204 | foreach ($PendingSensitiveType in $PendingSensitiveTypesList) { 205 | $PendingSensitiveTypetrim = $PendingSensitiveType.trim() 206 | if ( $LowCountSenstiveinfodetails -eq "") { 207 | $LowCountSenstiveinfodetails += "@{Name =" + [char]34 208 | $HighCountSenstiveinfodetails += "@{Name =" + [char]34 209 | 210 | } 211 | else { 212 | $LowCountSenstiveinfodetails += ",@{Name =" + [char]34 213 | $HighCountSenstiveinfodetails += ",@{Name =" + [char]34 214 | 215 | } 216 | $LowCountSenstiveinfodetails += $PendingSensitiveTypetrim + [char]34 217 | $LowCountSenstiveinfodetails += ";minCount = ""1""" 218 | $LowCountSenstiveinfodetails += ";maxCount = ""5""}" 219 | $HighCountSenstiveinfodetails += $PendingSensitiveTypetrim + [char]34 220 | $HighCountSenstiveinfodetails += ";minCount = ""6""}" 221 | } 222 | 223 | 224 | $NewPolicyTemplateData = Get-Content "$PSScriptRoot\..\Templates\NewDLPPolicyTemplate.txt" 225 | if ($null -eq $NewPolicyTemplateData -or $NewPolicyTemplateData -eq "") { 226 | Write-Host "$(Get-Date) Template file does not exist/is corrupt in $PSScriptRoot\..\Templates\NewDLPPolicyTemplate.txt. Remediation wont be generated" -ForegroundColor Orange 227 | } 228 | else { 229 | $NewPolicyTemplateData = $NewPolicyTemplateData.Replace("", "$Name") 230 | $NewPolicyTemplateData = $NewPolicyTemplateData.Replace("", "$HighCountSenstiveinfodetails") 231 | $NewPolicyTemplateData = $NewPolicyTemplateData.Replace("", "$LowCountSenstiveinfodetails") 232 | $LowRuleName = "Low Volume $Name" 233 | if ($LowRuleName.length -gt 60) { $LowRuleName = $LowRuleName.substring(0, 60) } 234 | $HighRuleName = "High Volume $Name" 235 | if ($HighRuleName.length -gt 60) { $HighRuleName = $HighRuleName.substring(0, 60) } 236 | $NewPolicyTemplateData = $NewPolicyTemplateData.Replace("", "$HighRuleName") 237 | $NewPolicyTemplateData = $NewPolicyTemplateData.Replace("", "$LowRuleName") 238 | 239 | $RemediationActionScript += $NewPolicyTemplateData 240 | Write-Host "$(Get-Date) Generating Remediation Action for $Name" -ForegroundColor Yellow 241 | } 242 | 243 | Return $RemediationActionScript 244 | } 245 | Function Get-PolicySensitiveType { 246 | Param 247 | ( 248 | $Config, 249 | $CompliancePolicy, 250 | $SensitiveTypes 251 | ) 252 | $PolicySensitiveTypes = New-Object System.Collections.Generic.HashSet[String] 253 | foreach ($ComplianceRule in $Config["GetDlpComplianceRule"]) { 254 | 255 | if ($ComplianceRule.Mode -ieq "enforce" -and $CompliancePolicy.name -eq $($ComplianceRule.ParentPolicyName) ) { 256 | $SensitiveInformationContent = $ComplianceRule.ContentContainsSensitiveInformation 257 | 258 | foreach ($SensitiveType in $($SensitiveTypes.keys)) { 259 | if ($SensitiveInformationContent.Values -contains $SensitiveType) { 260 | if (!$PolicySensitiveTypes.Contains($SensitiveType)) { 261 | $PolicySensitiveTypes.Add("$SensitiveType") | Out-Null 262 | 263 | } 264 | 265 | } 266 | if ($($SensitiveInformationContent.keys) -contains "groups") { 267 | foreach ($SensitiveInformationGroupList in $SensitiveInformationContent) { 268 | $SensitiveInformationGroups = $SensitiveInformationGroupList["groups"] 269 | foreach ($SensitiveInformationGroupDefined in $SensitiveInformationGroups) { 270 | $SensitiveInformationGroupDefinedValues = $SensitiveInformationGroupDefined.Values 271 | foreach ($SensitiveInformationGroupValue in $SensitiveInformationGroupDefinedValues) { 272 | foreach ($SensitiveInformationGroupVal in $SensitiveInformationGroupValue) { 273 | if ($SensitiveInformationGroupVal.Values -contains $SensitiveType ) { 274 | if (!$PolicySensitiveTypes.Contains($SensitiveType)) { 275 | $PolicySensitiveTypes.Add("$SensitiveType") | Out-Null 276 | 277 | } 278 | } 279 | 280 | } 281 | 282 | } 283 | } 284 | } 285 | 286 | } 287 | } 288 | 289 | 290 | 291 | } 292 | } 293 | 294 | Return $PolicySensitiveTypes 295 | } 296 | 297 | Function Get-SensitiveTypesNotEnabled { 298 | Param 299 | ( 300 | $SensitiveTypesWorkloadMapping, 301 | $LogFile, 302 | $ConfigObjectList 303 | ) 304 | 305 | 306 | $PendingSensitiveType = $null 307 | $PartialCoveredSIT = $null 308 | $PartialCoveredWorkload = $null 309 | foreach ($SensitiveTypes in $SensitiveTypesWorkloadMapping) { 310 | if (($SensitiveTypes.$ExchangeString -eq $false ) -and ($SensitiveTypes.$SharePointString -eq $false ) -and 311 | ($SensitiveTypes.$TeamsString -eq $false ) -and ($SensitiveTypes.$OneDriveString -eq $false ) -and ($SensitiveTypes.$DevicesString -eq $false ) ) { 312 | $PendingSensitiveType = Get-PartialSIT -PartialCoveredSIT $PendingSensitiveType -SensitiveTypesName $($SensitiveTypes.Name) 313 | 314 | } 315 | else { 316 | 317 | if ($SensitiveTypes.$ExchangeString -eq $false ) { 318 | $PartialCoveredSIT = Get-PartialSIT -PartialCoveredSIT $PartialCoveredSIT -SensitiveTypesName $($SensitiveTypes.Name) 319 | $PartialCoveredWorkload = Get-PartialSITWorkLoad -PartialCoveredWorkload $PartialCoveredWorkload -WorkloadName $ExchangeString 320 | } 321 | 322 | if ($SensitiveTypes.$SharePointString -eq $false ) { 323 | $PartialCoveredSIT = Get-PartialSIT -PartialCoveredSIT $PartialCoveredSIT -SensitiveTypesName $($SensitiveTypes.Name) 324 | $PartialCoveredWorkload = Get-PartialSITWorkLoad -PartialCoveredWorkload $PartialCoveredWorkload -WorkloadName $SharePointString 325 | 326 | } 327 | if ($SensitiveTypes.$OneDriveString -eq $false ) { 328 | $PartialCoveredSIT = Get-PartialSIT -PartialCoveredSIT $PartialCoveredSIT -SensitiveTypesName $($SensitiveTypes.Name) 329 | $PartialCoveredWorkload = Get-PartialSITWorkLoad -PartialCoveredWorkload $PartialCoveredWorkload -WorkloadName $OneDriveString 330 | } 331 | if ($SensitiveTypes.$TeamsString -eq $false ) { 332 | $PartialCoveredSIT = Get-PartialSIT -PartialCoveredSIT $PartialCoveredSIT -SensitiveTypesName $($SensitiveTypes.Name) 333 | $PartialCoveredWorkload = Get-PartialSITWorkLoad -PartialCoveredWorkload $PartialCoveredWorkload -WorkloadName $TeamsString 334 | } 335 | if ($SensitiveTypes.$DevicesString -eq $false ) { 336 | $PartialCoveredSIT = Get-PartialSIT -PartialCoveredSIT $PartialCoveredSIT -SensitiveTypesName $($SensitiveTypes.Name) 337 | $PartialCoveredWorkload = Get-PartialSITWorkLoad -PartialCoveredWorkload $PartialCoveredWorkload -WorkloadName $DevicesString 338 | } 339 | 340 | } 341 | 342 | 343 | 344 | 345 | } 346 | 347 | 348 | 349 | if ($null -ne $PartialCoveredSIT) { 350 | $ConfigObject = [CAMPCheckConfig]::new() 351 | $ConfigObject.Object = "Policy defined but not protected on 1 or more workloads" 352 | $ConfigObject.ConfigItem = "$PartialCoveredSIT" 353 | $ConfigObject.ConfigData = "Affected Workloads : $PartialCoveredWorkload" 354 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Fail") 355 | $ConfigObjectList += $ConfigObject 356 | } 357 | if ($null -ne $PendingSensitiveType) { 358 | 359 | $ConfigObject = [CAMPCheckConfig]::new() 360 | $ConfigObject.Object = "No active policy defined" 361 | $ConfigObject.ConfigItem = "$PendingSensitiveType" 362 | $ConfigObject.ConfigData = "Affected Workloads : $ExchangeString, $SharePointString, $TeamsString, $OneDriveString, $DevicesString" 363 | $ConfigObject.InfoText ="It is recommended that you set up DLP policies that block access for users external to your organization for all Sensitive Information Types on all workloads." 364 | try { 365 | $ConfigObject.RemediationAction = Get-NoPolicyRemediationAction -Name $Name -PendingSensitiveTypes $PendingSensitiveType -ErrorAction:SilentlyContinue 366 | } 367 | catch { 368 | Write-Host "Warning:$(Get-Date) There was an issue in generating remediation script. Please review the script closely before running the same." -ForegroundColor:Yellow 369 | $ErrorMessage = $_.ToString() 370 | $StackTraceInfo = $_.ScriptStackTrace 371 | Write-Log -IsError -ErrorMessage $ErrorMessage -StackTraceInfo $StackTraceInfo -LogFile $LogFile -ErrorAction:SilentlyContinue 372 | } 373 | $ConfigObject.SetResult([CAMPConfigLevel]::Ok, "Fail") 374 | $ConfigObjectList += $ConfigObject 375 | } 376 | 377 | Return $ConfigObjectList 378 | } 379 | function Get-PartialSIT { 380 | Param 381 | ( 382 | $PartialCoveredSIT, 383 | $SensitiveTypesName 384 | 385 | ) 386 | if ((@($PartialCoveredSIT) -like "*$SensitiveTypesName*").Count -le 0) { 387 | if ($null -eq $PartialCoveredSIT) { 388 | $PartialCoveredSIT += "$SensitiveTypesName" 389 | 390 | } 391 | else { 392 | $PartialCoveredSIT += ", $SensitiveTypesName" 393 | } 394 | } 395 | return $PartialCoveredSIT 396 | } 397 | function Get-PartialSITWorkLoad { 398 | Param 399 | ( 400 | $PartialCoveredWorkload, 401 | $WorkloadName 402 | 403 | ) 404 | if ((@($PartialCoveredWorkload) -like "*$WorkloadName*").Count -le 0) { 405 | if ($null -eq $PartialCoveredWorkload) { 406 | $PartialCoveredWorkload += $WorkloadName 407 | 408 | } 409 | else { 410 | $PartialCoveredWorkload += ", $WorkloadName" 411 | } 412 | } 413 | return $PartialCoveredWorkload 414 | } 415 | 416 | 417 | Function Get-AllLocationenabled { 418 | Param 419 | ( 420 | $CompliancePolicy 421 | ) 422 | $ExchangeLocation = $CompliancePolicy.ExchangeLocation 423 | $SharePointLocation = $CompliancePolicy.SharePointLocation 424 | $OneDriveLocation = $CompliancePolicy.OneDriveLocation 425 | $TeamsLocation = $CompliancePolicy.TeamsLocation 426 | $EndpointDlpLocation = $CompliancePolicy.EndpointDlpLocation 427 | $WorkloadsStatus = @{} 428 | $WorkloadsStatus[$ExchangeString] = $false 429 | $WorkloadsStatus[$SharePointString] = $false 430 | $WorkloadsStatus[$OneDriveString] = $false 431 | $WorkloadsStatus[$TeamsString] = $false 432 | $WorkloadsStatus[$DevicesString] = $false 433 | if ((@($ExchangeLocation) -like 'All').Count -gt 0) { 434 | $WorkloadsStatus[$ExchangeString] = $true 435 | } 436 | if ((@($SharePointLocation) -like 'All').Count -gt 0) { 437 | $WorkloadsStatus[$SharePointString] = $true 438 | } 439 | if ((@($OneDriveLocation) -like 'All').Count -gt 0) { 440 | $WorkloadsStatus[$OneDriveString] = $true 441 | } 442 | if ((@($TeamsLocation) -like 'All').Count -gt 0) { 443 | $WorkloadsStatus[$TeamsString] = $true 444 | } 445 | if ((@($EndpointDlpLocation) -like 'All').Count -gt 0) { 446 | $WorkloadsStatus[$DevicesString] = $true 447 | } 448 | 449 | Return $WorkloadsStatus 450 | 451 | 452 | } 453 | 454 | 455 | Function Set-ExchangeNotAllLocationEnabledConfigObject { 456 | Param 457 | ( 458 | 459 | $ConfigObjectResult, 460 | $CompliancePolicy 461 | ) 462 | 463 | $ExchangeLocation = $CompliancePolicy.ExchangeLocation 464 | $ExchangeSenderException = $CompliancePolicy.ExchangeSenderException 465 | $ExchangeSenderMemberOf = $CompliancePolicy.ExchangeSenderMemberOf 466 | $ExchangeSenderMemberOfException = $CompliancePolicy.ExchangeSenderMemberOfException 467 | 468 | if (((@($ExchangeLocation) -like 'All').Count -lt 1)) { 469 | if (@($ExchangeLocation).count -ne 0) { 470 | 471 | $ConfigObjectResult["Included Exchange Groups"] += "$ExchangeLocation " 472 | 473 | } 474 | } 475 | 476 | if ($ExchangeSenderMemberOf.count -ne 0) { 477 | 478 | if ($ConfigObjectResult.contains("Included Exchange Groups")) { 479 | $ConfigObjectResult["Included Exchange Groups"] += ", $ExchangeSenderMemberOf " 480 | } 481 | else { 482 | $ConfigObjectResult["Included Exchange Groups"] = "$ExchangeSenderMemberOf " 483 | 484 | } 485 | 486 | } 487 | if (($ExchangeSenderMemberOfException.count -ne 0) -or ($ExchangeSenderException.count -ne 0) ) { 488 | 489 | $ConfigObjectResult["Excluded Exchange Groups"] += "$ExchangeSenderMemberOfException $ExchangeSenderException " 490 | 491 | } 492 | Return $ConfigObjectResult 493 | 494 | } 495 | 496 | function Set-SharePointNotAllLocationEnabledConfigObject { 497 | Param 498 | ( 499 | $ConfigObjectResult, 500 | $CompliancePolicy 501 | 502 | ) 503 | $SharePointLocation = $CompliancePolicy.SharePointLocation 504 | $SharePointLocationException = $CompliancePolicy.SharePointLocationException 505 | $SharePointOnPremisesLocationException = $CompliancePolicy.SharePointOnPremisesLocationException 506 | 507 | if (((@($SharePointLocation) -like 'All').Count -lt 1)) { 508 | if (@($SharePointLocation).count -ne 0) { 509 | 510 | $ConfigObjectResult["Included SP Sites"] += "$SharePointLocation " 511 | } 512 | } 513 | 514 | if (($SharePointLocationException.count -ne 0) -or ($SharePointOnPremisesLocationException.count -ne 0)) { 515 | 516 | $ConfigObjectResult["Excluded SP Sites"] += "$SharePointLocationException $SharePointOnPremisesLocationException " 517 | } 518 | 519 | Return $ConfigObjectResult 520 | 521 | } 522 | 523 | function Set-TeamsNotAllLocationEnabledConfigObject { 524 | Param 525 | ( 526 | $ConfigObjectResult, 527 | $CompliancePolicy 528 | ) 529 | 530 | $TeamsLocation = $CompliancePolicy.TeamsLocation 531 | $TeamsLocationException = $CompliancePolicy.TeamsLocationException 532 | 533 | if (((@($TeamsLocation) -like 'All').Count -lt 1)) { 534 | if (@($TeamsLocation).count -ne 0) { 535 | 536 | $ConfigObjectResult["Included Teams Account"] += "$TeamsLocation" 537 | } 538 | } 539 | 540 | if (($TeamsLocationException.count -ne 0)) { 541 | 542 | $ConfigObjectResult["Excluded Teams Account"] += "$TeamsLocationException" 543 | } 544 | Return $ConfigObjectResult 545 | 546 | } 547 | function Set-OneDriveNotAllLocationEnabledConfigObject { 548 | Param 549 | ( 550 | $ConfigObject, 551 | $PolicySensitiveType, 552 | $CompliancePolicy 553 | 554 | ) 555 | $OneDriveLocation = $CompliancePolicy.OneDriveLocation 556 | $OneDriveLocationException = $CompliancePolicy.OneDriveLocationException 557 | $ExceptIfOneDriveSharedByMemberOf = $CompliancePolicy.ExceptIfOneDriveSharedByMemberOf 558 | 559 | if (((@($OneDriveLocation) -like 'All').Count -lt 1)) { 560 | if (@($OneDriveLocation).count -ne 0) { 561 | 562 | $ConfigObjectResult["Included OneDrive Account"] += "$OneDriveLocation" 563 | } 564 | 565 | } 566 | 567 | if (($OneDriveLocationException.count -ne 0) -or ($ExceptIfOneDriveSharedByMemberOf.count -ne 0)) { 568 | 569 | $ConfigObjectResult["Excluded OneDrive Account"] += "$OneDriveLocationException $ExceptIfOneDriveSharedByMemberOf" 570 | 571 | } 572 | Return $ConfigObjectResult 573 | 574 | } 575 | function Set-DevicesNotAllLocationEnabledConfigObject { 576 | Param 577 | ( 578 | $ConfigObject, 579 | $PolicySensitiveType, 580 | $CompliancePolicy 581 | 582 | ) 583 | $EndpointDlpLocation = $CompliancePolicy.EndpointDlpLocation 584 | $EndpointDlpLocationException = $CompliancePolicy.EndpointDlpLocationException 585 | 586 | if (((@($EndpointDlpLocation) -like 'All').Count -lt 1)) { 587 | if (@($EndpointDlpLocation).count -ne 0) { 588 | 589 | $ConfigObjectResult["Included Devices User/Groups"] += "$EndpointDlpLocation" 590 | } 591 | 592 | } 593 | 594 | if (($EndpointDlpLocationException.count -ne 0)) { 595 | 596 | $ConfigObjectResult["Excluded Devices User/Groups"] += "$EndpointDlpLocationException" 597 | 598 | } 599 | Return $ConfigObjectResult 600 | 601 | } --------------------------------------------------------------------------------