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-MgOrganizationWrite-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, assignedLabelsIf (!($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.labelIdIf ($Group.Owners.additionalProperties.displayName) {[string]$GroupOwnerNames = $Group.Owners.additionalProperties.displayName -join ", "}# Issue warning if no label foundIf (!($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 foundIf (!($GroupOwnerNames)) {Write-Host ("The {0} group has no owners." -f $Group.displayName) -foregroundcolor Red$Status = $Status + "*** No Group Owners ***"}$ReportLine = [PSCustomObject][Ordered]@{Id = $Group.IdName = $Group.DisplayNameOwners = $GroupOwnerNamesLabel = $LabelNameLabelId = $LabelIdStatus = $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 -UniqueForEach ($SingleLabel in $LabelUnique) {[array]$LData = $Report | Where-Object {$_.Label -eq $SingleLabel.Label}$LabelInfo = [PSCustomObject][Ordered]@{Label = $SingleLabel.LabelCount = $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 + $HtmlTailWrite-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 availableIf (Get-Module ImportExcel -ListAvailable) {$ExcelGenerated = $TrueImport-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
Author
Office365itpros