Entra / Microsoft 365 · Compliance & audit
Report sensitivity label settings
A script to report the settings of sensitivity labels.
Connect & set up
Run these once per session. All scopes are read-only unless the script makes changes.
Connect-ExchangeOnline -ShowBanner:$False -SkipLoadingCmdletHelp# Connect to compliance endpointConnect-IPPSSession -ShowBanner:$False
Run it
The main script. Copy it, or download the .ps1 and run it from your console.
Function CheckRightsIdentity {[cmdletbinding()]Param([string]$RightsIdentity)$RightsCheck = $falseIf ($RightsIdentity -eq "AuthenticatedUsers") {$RightsCheck = $trueReturn $RightsCheck}If ($RightsIdentity -like "*@*") {$Domain = $RightsIdentity.Split("@")[1].toLower()If ($Domain -in $Domains) { # It's an email address belonging to our tenant$CheckUser = Get-ExoRecipient -Identity $RightsIdentity -ErrorAction SilentlyContinueIf (!($CheckUser)) {$RightsCheck = $False; Return $RightsCheck} Else {$RightsCheck = $True; Return $RightsCheck}}}# Check a domain name https://learn.microsoft.com/en-gb/archive/blogs/tip_of_the_day/cloud-tip-of-the-day-use-powershell-to-check-domain-availability-for-office-365-and-azure# Don't bother for Outlook.com or microsoft.com - always Unmanaged for some reasonSwitch ($RightsIdentity) {"outlook.com" {$RightsCheck = $True$Global:CheckMessage = "consumer domain"break}"microsoft.com" {$RightsCheck = $Truebreak}"gmail.com" {$RightsCheck = $True$Global:CheckMessage = "consumer domain"break}"google.com" {$RightsCheck = $True$Global:CheckMessage = "consumer domain"break}"yandex.com" {$RightsCheck = $True$Global:CheckMessage = "consumer domain"break}default {$Uri = ('https://login.microsoftonline.com/getuserrealm.srf?login=user@{0}&xml=1' -f $RightsIdentity)$CheckDomain = Invoke-WebRequest -Uri $UriIf ($CheckDomain.StatusCode -eq 200) {$NamespaceType = ([xml]($CheckDomain.Content)).RealmInfo.NameSpaceTypeIf ($NameSpaceType -eq "Managed") { # Entra ID domain$ RightsCheck = $True; Return $RightsCheck} Else {$RightsCheck = $False; Return $RightsCheck }}}} #End SwitchReturn $RightsCheck}# End functions and start of processing$HtmlHead="<html><style>BODY{font-family: Arial; font-size: 8pt;}H1{font-size: 22px; font-family: 'Segoe UI Light','Segoe UI','Lucida Grande',Verdana,Arial,Helvetica,sans-serif;}H2{font-size: 18px; font-family: 'Segoe UI Light','Segoe UI','Lucida Grande',Verdana,Arial,Helvetica,sans-serif;}H3{font-size: 16px; font-family: 'Segoe UI Light','Segoe UI','Lucida Grande',Verdana,Arial,Helvetica,sans-serif;}TABLE{border: 1px solid black; border-collapse: collapse; font-size: 8pt;}TH{border: 1px solid #969595; background: #dddddd; padding: 5px; color: #000000;}TD{border: 1px solid #969595; padding: 5px; }td.pass{background: #B7EB83;}td.warn{background: #FFF275;}td.fail{background: #FF2626; color: #ffffff;}td.info{background: #85D4FF;}</style><body><div align=center><p><h1>Microsoft 365 Sensitivity Labels Settings Report</h1></p><p><h3>Generated: " + (Get-Date -format 'dd-MMM-yyyy hh:mm tt') + "</h3></p></div>"$Version = "1.0"$HtmlReportFile = "c:\temp\SenstivityLabelSettings.html"$CSVReportFile = "c:\temp\LabelInfo.CSV"$Modules = Get-Module | Select-Object -ExpandProperty NameIf ("ExchangeOnlineManagement" -notin $Modules) {Write-Host "Connecting to Exchange Online..."Connect-ExchangeOnline -ShowBanner:$False -SkipLoadingCmdletHelp# Connect to compliance endpointConnect-IPPSSession -ShowBanner:$False}[array]$Global:Domains = (Get-AcceptedDomain).DomainName# Get details of sensitivity labels[array]$Labels = Get-LabelIf (!($Labels)) { Write-Host "Can't get details of sensitivity labels - exiting" ; break }Write-Host ("Processing details for {0} sensitivity labels" -f $Labels.count)$LabelInfo = [System.Collections.Generic.List[Object]]::new()$LabelSettingsInfo = [System.Collections.Generic.List[Object]]::new()$NewLine = "`r`n"[int]$i = 0ForEach ($Label in $Labels) {$i++Write-Host ("Processing label: {0} ({1}/{2})" -f $Label.DisplayName, $i, $Labels.count)$LabelActions = (Get-Label -Identity $Label.ImmutableId).LabelActions | Convertfrom-JSONForEach ($Section in $LabelActions) {$SectionSettings = $Section.SettingsForEach ($Setting in $SectionSettings) {$Value = $Null; $DisplayName = $NullSwitch ($Setting.Key) {"rightsdefinitions" {[array]$Rights = $Setting.Value | ConvertFrom-Json[int]$r = 0ForEach ($Right in $Rights) {$r++$RightsCheck = $False; $CheckMessage = $Null$RightsCheck = CheckRightsIdentity($Right.Identity)$RightsFormat = ("{0} rights: {1}" -f $Right.Identity, $Right.Rights)If ($RightsCheck -eq $False) {$RightsFormat = $RightsFormat + " (Warning: Rights assigned to unverified holder)"}If ($CheckMessage) {$RightsFormat = ("{0} (Warning: {1})" -f $RightsFormat, $CheckMessage)}If ($r -lt $Rights.count) {$RightsFormat = $RightsFormat + $Newline}$Value += $RightsFormat}}"protectionlevel" {$Protection = $Setting.Value | ConvertFrom-Json$Value = ("Id {0} {1} ({2})" -f $Protection.Id, $Protection.DisplayName, $Protection.Description)}Default {$Value = $Setting.Value}}If ($Label.ParentLabelDisplayName) {$DisplayName = ("{0}/{1}" -f $Label.ParentLabelDisplayName, $Label.DisplayName)} Else {$DisplayName = $Label.DisplayName}$DataLine = [PSCustomObject] @{Label = $DisplayNameApplies = $Label.ContentTypePriority = $Label.PrioritySection = $Section.TypeSubtype = $Section.SubTypeKey = $Setting.KeyValue = $Value }$LabelInfo.Add($DataLine)} #End of processing the individual settings} #End of processng the label actions# Check overall label settings and extract values$LabelSettings = $Label.Settings$SettingsArray = $LabelSettings -split "`n"ForEach ($Setting in $SettingsArray) {$Key, $Value = $Setting -split ",", 2$Value = $Value.trim()$DataLine = [PSCustomObject]@{Label = $Label.DisplayNameKey = $Key.substring(1,$Key.length -1).trim()Value = $Value = $Value.Substring(0, $Value.length-1)}$LabelSettingsInfo.Add($DataLine)}} #End ForEach label$LabelInfo | Out-GridView$LabelInfo | Export-CSV -NoTypeInformation $CSVReportFile# Alternative $Labelinfo | Export-Excel LabelInfo.xlsx# Generate array of unique label names from the report[array]$LabelNames = $LabelInfo.Label | Sort-Object -Unique[string]$HtmlReport = $NullForEach ($L in $LabelNames) {$DataToReport = $LabelInfo | Where-Object {$_.Label -eq $L}$HtmlHeading = ("<p><h1>Settings for Sensitivity label <b>{0}</b></h1></p><p><h2>Label Scope: <i>{1}</i> Label Priority: <i>{2}</i></p></h2>" -f $L, $DataToReport[0].Applies, $DataToReport[0].Priority)If (($LabelSettingsInfo | Where-Object {$_.Label -eq $L -and $_.Key -eq 'blockcontentanalysisservices'} | Select-Object -ExpandProperty Value) -eq 'True') {$HtmlHeading = $HtmlHeading + "<p><h3><b>This label blocks access to content analysis services</b></h3></p>"}$DataToReport = $DataToReport | Select-Object Section, Subtype, Key, Value$HtmlData = $DataToReport | ConvertTo-Html -Fragment$HtmlReport = $HtmlReport + $HtmlHeading + $HtmlData}# Create the HTML report$Htmltail = "<p>Report created for: " + ((Get-OrganizationConfig).DisplayName) + "</p><p>" +"<p>Number of sensitivity labels: " + $Labels.count + "</p>" +"<p>-----------------------------------------------------------------------------------------------------------------------------" +"<p>Microsoft 365 Sensitivity Labels Settings Report <b>" + $Version + "</b>"$HtmlReport = $HtmlHead + $HtmlReport + $HtmlTail$HtmlReport | Out-File $HtmlReportFile -Encoding UTF8Write-Host ("The sensitivity Labels settings report files are available in {0} (HTML) and {1} (CSV)" -f $HtmlReportFile, $CSVReportFile)# Check if any warnings are found[array]$Warnings = $LabelInfo | Where-Object {$_.Value -like "*warning: rights*"} | Select-Object Label, Applies, Priority, ValueIf ($Warnings) {Write-Host ""Write-Host "You should check these warnings flagged for labels with rights assignments to unverified or consumer domains"$Warnings | Format-List}
Attribution
Author
Office365itpros