Back to script library
Entra / Microsoft 365 · Groups

Report container management labels

Create a report about container management labels and highlight Microsoft 365 groups without a label or without owners.

Connect & set up

Run these once per session. All scopes are read-only unless the script makes changes.

Connect-MgGraph -Scopes Directory.Read.All

Run it

The main script. Copy it, or download the .ps1 and run it from your console.

Connect-MgGraph -Scopes Directory.Read.All
$Version = "2.0"
$Organization = Get-MgOrganization
Write-Host "Finding Microsoft 365 Groups to process..."
[array]$Groups = Get-MgGroup -Filter "groupTypes/any(c:c eq 'unified')" -PageSize 500 -All `
-ExpandProperty "Owners(`$Select=displayName)" -Property Id, Owners, displayName, Visibility, CreatedDateTime, assignedLabels
If (!($Groups)) {
Write-Host "Whoops - can't find any Microsoft 365 Groups"
break
}
Write-Host ("Found {0} groups - now checking container management labels" -f $Groups.count)
$Groups = $Groups | Sort-Object DisplayName
$Report = [System.Collections.Generic.List[Object]]::new()
ForEach ($Group in $Groups) {
$LabelId = $Null; $LabelName = $Null; $GroupOwnerNames = $Null; $Status = $Null
$LabelName = $Group.assignedLabels.displayName
$LabelId = $Group.assignedLabels.labelId
If ($Group.Owners.additionalProperties.displayName) {
[string]$GroupOwnerNames = $Group.Owners.additionalProperties.displayName -join ", "
}
# Issue warning if no label found
If (!($LabelName)) {
Write-Host ("The {0} group has no label. Owner(s) {1}" -f $Group.displayName, $GroupOwnerNames) -foregroundcolor Red
$Status = "*** Check Label ***"
}
# Issue warning if no group owners found
If (!($GroupOwnerNames)) {
Write-Host ("The {0} group has no owners." -f $Group.displayName) -foregroundcolor Red
$Status = $Status + "*** No Group Owners ***"
}
$ReportLine = [PSCustomObject][Ordered]@{
Id = $Group.Id
Name = $Group.DisplayName
Owners = $GroupOwnerNames
Label = $LabelName
LabelId = $LabelId
Status = $Status }
$Report.Add($ReportLine)
} # End processing groups
# Generate the report files
$HtmlHeading ="<html>
<style>
BODY{font-family: Arial; font-size: 8pt;}
H1{font-size: 36px; font-family: 'Segoe UI Light','Segoe UI','Lucida Grande',Verdana,Arial,Helvetica,sans-serif;}
H2{font-size: 24px; 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 Groups and Container Management Labels Report</h1></p>
<p><h3>Generated: " + (Get-Date -format 'dd-MMM-yyyy hh:mm tt') + "</h3></p></div>"
$HtmlData = $Report | ConvertTo-Html -Fragment
$HtmlReport = $HtmlHeading + $HtmlData
# Figure out labels used
$LabelData = [System.Collections.Generic.List[Object]]::new()
[array]$LabelUnique = $Report | Where-Object {$_.Label -ne $Null} | Select-Object Label | Sort-Object Label -Unique
ForEach ($SingleLabel in $LabelUnique) {
[array]$LData = $Report | Where-Object {$_.Label -eq $SingleLabel.Label}
$LabelInfo = [PSCustomObject][Ordered]@{
Label = $SingleLabel.Label
Count = $LData.Count }
$LabelData.Add($LabelInfo)
}
$HtmlHeading = "<p><h3>Container Management Label Assignment Summary</h3>"
$HtmlData = $LabelData | ConvertTo-Html -Fragment
$HtmlReport = "<p>" + $HtmlReport + "<p>" + $HtmlHeading + $HtmlData
# Add a section about groups missing labels if there are any
[array]$MissingLabels = $Report | Where-Object {$_.LabelId -eq $Null}
If ($MissingLabels) {
$HtmlHeading = "<p><h3>Microsoft 365 Groups without a Sensitivity Label</h3>"
$HtmlData = $MissingLabels | ConvertTo-Html -Fragment
$HtmlReport = $HtmlReport + $HtmlHeading + $HtmlData
}
# Add section about missing owners (if any)
[array]$MissingOwners = $Report | Where-Object {$_.Owners -eq $Null -or $_.Owners.length -eq 0}
If ($MissingOwners) {
$HtmlHeading = "<p><h3>Microsoft 365 Groups without owners</h3>"
$HtmlData = $MissingOwners | ConvertTo-Html -Fragment
$HtmlReport = $HtmlReport + $HtmlHeading + $HtmlData
}
# Create the HTML report
$Htmltail = "<p>Report created for: " + ($Organization.DisplayName) + "</p><p>" +
"<p>Number of Microsoft 365 Group: " + $Groups.count + "</p>" +
"<p>Number of labels used: " + $LabelUnique.count + "</p>" +
"<p>Number of groups without a label: " + $MissingLabels.count + "</p>" +
"<p>Number of groups without owners: " + $MissingOwners.count + "</p>" +
"<p>-----------------------------------------------------------------------------------------------------------------------------" +
"<p>Microsoft 365 Groups and Container Management Labels <b>" + $Version + "</b>"
$HtmlReport = $HtmlHead + $HtmlReport + $HtmlTail
Write-Host ""
Write-Host "All done"
Write-Host ""
Write-Host ("{0} Microsoft 365 Groups found" -f $Groups.count)
Write-Host ("{0} Groups found without a label" -f $MissingLabels.count)
Write-Host ("{0} Groups found without owners" -f $MissingOwners.count)
Write-Host ""
$HtmlReportFile = ((New-Object -ComObject Shell.Application).Namespace('shell:Downloads').Self.Path) + "\Container Management Report.html"
$HtmlReport | Out-File $HtmlReportFile -Encoding UTF8
# Generate the report in either Excel worksheet or CSV format, depending on if the ImportExcel module is available
If (Get-Module ImportExcel -ListAvailable) {
$ExcelGenerated = $True
Import-Module ImportExcel -ErrorAction SilentlyContinue
$ExcelOutputFile = ((New-Object -ComObject Shell.Application).Namespace('shell:Downloads').Self.Path) + "\Container Management Report.xlsx"
$Report | Export-Excel -Path $ExcelOutputFile -WorksheetName "Container Management Labels" -Title ("Labels assigned to Groups {0}" -f (Get-Date -format 'dd-MMM-yyyy')) -TitleBold -TableName "ContainerManagement"
} Else {
$CSVOutputFile = ((New-Object -ComObject Shell.Application).Namespace('shell:Downloads').Self.Path) + "\Container Management Report.CSV"
$Report | Export-Csv -Path $CSVOutputFile -NoTypeInformation -Encoding Utf8
}
If ($ExcelGenerated -eq $true) {
Write-Host ("Container management report is available in Excel workbook {0}" -f $ExcelOutputFile) -ForegroundColor Green
} Else {
Write-Host ("Container management report is available in CSV file {0}" -f $CSVOutputFile) -ForegroundColor Green
}
Write-Host ("HTML report of Microsoft 365 groups is available at {0}" -f $HTMLReportFile) -ForegroundColor Green
Attribution