diff --git a/src/powershell/tests/Test-Assessment.35015.md b/src/powershell/tests/Test-Assessment.35015.md new file mode 100644 index 000000000..ec8f28a3e --- /dev/null +++ b/src/powershell/tests/Test-Assessment.35015.md @@ -0,0 +1,30 @@ +Sensitivity label policies control which labels are available to users and can be scoped to specific users, groups, or the entire organization. Publishing too many labels globally creates confusion and decision paralysis for end users, reducing adoption and increasing the likelihood of misclassification. When users are presented with an overwhelming number of label choices (typically more than 25 top-level and sub-labels), they struggle to identify the appropriate classification for their content, leading to either selecting incorrect labels or avoiding the feature entirely. + +Microsoft recommends publishing no more than 25 labels in globally-scoped policies, ideally organized as 5 parent labels with up to 5 sub-labels each. This creates a manageable hierarchy that users can understand and apply consistently. Organizations with complex classification needs should use scoped policies to publish specialized labels only to the departments or roles that require them, keeping the global label set lean and focused on the most common classification scenarios. + +**Remediation action** + +To reduce the number of globally-published labels: +1. Review which labels are truly needed by all users +2. Create scoped label policies for department-specific or role-specific labels +3. Remove less-commonly-used labels from global policies +4. Consolidate similar labels where possible +5. Use sub-labels to organize related labels under parent categories + +Best practices: +- Limit global policies to 5-7 top-level labels with 3-5 sub-labels each +- Use clear, business-friendly label names (not technical jargon) +- Publish specialized labels only to users who need them via scoped policies + +To manage label policies: +1. Navigate to [Microsoft Purview portal > Information Protection > Label policies](https://purview.microsoft.com/informationprotection/labelpolicies) +2. Review existing globally-scoped policies +3. Edit policies to remove unnecessary labels or change scope to specific users/groups +4. Create new scoped policies for specialized labels + +- [Sensitivity label policies best practices](https://learn.microsoft.com/purview/sensitivity-labels#what-label-policies-can-do) +- [Create and publish sensitivity labels](https://learn.microsoft.com/microsoft-365/compliance/create-sensitivity-labels) +- [Label policy priority and precedence](https://learn.microsoft.com/purview/sensitivity-labels-office-apps#label-policy-priority-order-matters) + + +%TestResult% diff --git a/src/powershell/tests/Test-Assessment.35015.ps1 b/src/powershell/tests/Test-Assessment.35015.ps1 new file mode 100644 index 000000000..0657cae88 --- /dev/null +++ b/src/powershell/tests/Test-Assessment.35015.ps1 @@ -0,0 +1,132 @@ +<# +.SYNOPSIS + Global Scope Label Count + +.DESCRIPTION + Sensitivity label policies control which labels are available to users and can be scoped to specific users, groups, or the entire organization. Publishing too many labels globally creates confusion and decision paralysis for end users. Microsoft recommends publishing no more than 25 labels in globally-scoped policies to maintain usability and reduce misclassification. + +.NOTES + Test ID: 35015 + Pillar: Data + Risk Level: Medium +#> + +function Test-Assessment-35015 { + [ZtTest( + Category = 'Information Protection', + ImplementationCost = 'Low', + MinimumLicense = ('Microsoft 365 E3'), + Pillar = 'Data', + RiskLevel = 'Medium', + SfiPillar = '', + TenantType = ('Workforce'), + TestId = 35015, + Title = 'Global Scope Label Count', + UserImpact = 'High' + )] + [CmdletBinding()] + param() + + #region Data Collection + Write-PSFMessage '🟦 Start' -Tag Test -Level VeryVerbose + + $activity = 'Checking Global Scope Label Count' + Write-ZtProgress -Activity $activity -Status 'Getting label policies' + + $errorMsg = $null + $maxRecommendedLabels = 25 + + try { + # Get all enabled label policies + $labelPolicies = Get-LabelPolicy -ErrorAction Stop | Where-Object { $_.Enabled -eq $true } + } + catch { + $errorMsg = $_ + Write-PSFMessage "Error querying label policies: $_" -Level Error + } + #endregion Data Collection + + #region Assessment Logic + $customStatus = $null + if ($errorMsg) { + $passed = $false + $customStatus = 'Investigate' + } + else { + # Identify globally-scoped policies by checking all location names + $globalPolicies = $labelPolicies | ForEach-Object { + $policy = $_ + $allLocationNames = @( + $policy.ExchangeLocation.Name + $policy.ModernGroupLocation.Name + $policy.SharePointLocation.Name + $policy.OneDriveLocation.Name + $policy.SkypeLocation.Name + $policy.PublicFolderLocation.Name + ) | Where-Object { $_ } + $isGlobal = $allLocationNames -contains 'All' + $scope = if ($isGlobal) { 'Global' } else { 'User/Group-Scoped' } + + $policy | Add-Member -MemberType NoteProperty -Name 'Scope' -Value $scope -PassThru + } | Where-Object { $_.Scope -eq 'Global' } + $uniqueLabels = $globalPolicies.Labels | Where-Object { $_ } | Select-Object -Unique + $totalUniqueLabels = @($uniqueLabels).Count + $passed = $totalUniqueLabels -le $maxRecommendedLabels + } + #endregion Assessment Logic + + #region Report Generation + if ($errorMsg) { + $testResultMarkdown = "### Investigate`n`n" + $testResultMarkdown += "Unable to determine global label count due to error: $errorMsg" + } + else { + $status = if ($passed) { '✅' } else { '❌' } + $statusText = if ($passed) { 'within' } else { 'exceeding' } + $testResultMarkdown = "$status $totalUniqueLabels sensitivity labels are published in globally-scoped policies, $statusText the recommended limit of $maxRecommendedLabels.`n`n" + + if ($globalPolicies) { + $testResultMarkdown += "### Global Label Policies`n`n" + $testResultMarkdown += "| Policy Name | Status | Scope | Labels Published | Sample Labels |`n" + $testResultMarkdown += "| :--- | :--- | :--- | :---: | :--- |`n" + + $policyLink = "https://purview.microsoft.com/informationprotection/labelpolicies" + + foreach ($policy in $globalPolicies) { + $policyName = Get-SafeMarkdown -Text $policy.Name + $scope = $policy.Scope + $labelCount = @($policy.Labels).Count + + # Get sample labels (up to 5) + $sampleLabels = if ($policy.Labels) { + $samples = @($policy.Labels | Select-Object -First 5) + $labelText = ($samples | ForEach-Object { Get-SafeMarkdown -Text $_ }) -join ', ' + if (@($policy.Labels).Count -gt 5) { $labelText += ', ...' } + $labelText + } else { 'None' } + + $testResultMarkdown += "| [$policyName]($policyLink) | Enabled | $scope | $labelCount | $sampleLabels |`n" + } + + $statusText = if ($passed) { 'Pass' } else { 'Fail' } + $testResultMarkdown += "`n### Summary`n`n" + $testResultMarkdown += "* **Total Unique Labels Published Globally:** $totalUniqueLabels`n" + $testResultMarkdown += "* **Recommended Maximum:** $maxRecommendedLabels`n" + $testResultMarkdown += "* **Status:** $statusText`n" + } else { + $testResultMarkdown += "No globally-scoped label policies found.`n" + } + } + #endregion Report Generation + + $params = @{ + TestId = '35015' + Title = 'Global Scope Label Count' + Status = $passed + Result = $testResultMarkdown + } + if ($customStatus) { + $params.CustomStatus = $customStatus + } + Add-ZtTestResultDetail @params +}