From 9cc8c87af763e0cf48baa8457a170cc64a873032 Mon Sep 17 00:00:00 2001 From: alexandair Date: Mon, 22 Dec 2025 22:31:48 +0000 Subject: [PATCH] 35003 - Add test for sensitivity label configuration and reporting --- .../Test-Assessment.35003.Tests.ps1 | 108 ++++++++++++++++++ src/powershell/tests/Test-Assessment.35003.md | 20 ++++ .../tests/Test-Assessment.35003.ps1 | 106 +++++++++++++++++ 3 files changed, 234 insertions(+) create mode 100644 code-tests/test-assessments/Test-Assessment.35003.Tests.ps1 create mode 100644 src/powershell/tests/Test-Assessment.35003.md create mode 100644 src/powershell/tests/Test-Assessment.35003.ps1 diff --git a/code-tests/test-assessments/Test-Assessment.35003.Tests.ps1 b/code-tests/test-assessments/Test-Assessment.35003.Tests.ps1 new file mode 100644 index 000000000..a0bce71ab --- /dev/null +++ b/code-tests/test-assessments/Test-Assessment.35003.Tests.ps1 @@ -0,0 +1,108 @@ +Describe "Test-Assessment-35003" { + BeforeAll { + $here = $PSScriptRoot + $srcRoot = Join-Path $here "../../src/powershell" + + # Mock external module dependencies + if (-not (Get-Command Write-PSFMessage -ErrorAction SilentlyContinue)) { + function Write-PSFMessage {} + } + + # Define Get-Label if it doesn't exist (required for mocking in some environments) + if (-not (Get-Command Get-Label -ErrorAction SilentlyContinue)) { + function Get-Label {} + } + + # Load the class + $classPath = Join-Path $srcRoot "classes/ZtTest.ps1" + if (-not ("ZtTest" -as [type])) { + . $classPath + } + + # Load the SUT + $sut = Join-Path $srcRoot "tests/Test-Assessment.35003.ps1" + . $sut + + # Setup output file + $script:outputFile = Join-Path $here "../TestResults/Report-Test-Assessment.35003.md" + $outputDir = Split-Path $script:outputFile + if (-not (Test-Path $outputDir)) { New-Item -ItemType Directory -Path $outputDir | Out-Null } + "# Test Results for 35003`n" | Set-Content $script:outputFile + } + + BeforeEach { + Mock Write-PSFMessage {} + Mock Write-ZtProgress {} + Mock Get-SafeMarkdown { param($Text) return $Text } + } + + Context "When labels exist" { + It "Should pass when at least one label exists" { + Mock Get-Label { + return @( + [PSCustomObject]@{ + DisplayName = "Confidential" + Priority = 1 + ParentId = $null + ParentLabelDisplayName = $null + }, + [PSCustomObject]@{ + DisplayName = "Public" + Priority = 0 + ParentId = $null + ParentLabelDisplayName = $null + } + ) + } + + Mock Add-ZtTestResultDetail { + param($TestId, $Title, $Status, $Result) + "## Scenario: Labels Exist`n`n$Result`n" | Add-Content $script:outputFile + } + + Test-Assessment-35003 + + Should -Invoke Add-ZtTestResultDetail -ParameterFilter { + $Status -eq $true -and $Result -match "At least one sensitivity label is configured" + } + } + } + + Context "When no labels exist" { + It "Should fail when no labels are returned" { + Mock Get-Label { return @() } + + Mock Add-ZtTestResultDetail { + param($TestId, $Title, $Status, $Result) + "## Scenario: No Labels`n`n$Result`n" | Add-Content $script:outputFile + } + + Test-Assessment-35003 + + Should -Invoke Add-ZtTestResultDetail -ParameterFilter { + $Status -eq $false -and $Result -match "No sensitivity labels are configured" + } + } + } + + Context "Error Handling" { + It "Should handle errors gracefully" { + Mock Get-Label { throw "Connection Error" } + + $script:capturedResult = $null + Mock Add-ZtTestResultDetail { + param($TestId, $Title, $Status, $Result) + $script:capturedResult = $Result + "## Scenario: Error Handling`n`n$Result`n" | Add-Content $script:outputFile + } + + Test-Assessment-35003 + + Should -Invoke Add-ZtTestResultDetail -ParameterFilter { + $Status -eq $false + } + $script:capturedResult | Should -Match "Unable to query sensitivity labels" + $script:capturedResult | Should -Match "Connection Error" + } + } +} diff --git a/src/powershell/tests/Test-Assessment.35003.md b/src/powershell/tests/Test-Assessment.35003.md new file mode 100644 index 000000000..c77ccbed3 --- /dev/null +++ b/src/powershell/tests/Test-Assessment.35003.md @@ -0,0 +1,20 @@ +Sensitivity labels are the foundation of Microsoft Information Protection, enabling organizations to classify and protect sensitive data across Microsoft 365 services, on-premises locations, and third-party applications. Without sensitivity labels configured, organizations have no standardized way to identify, classify, or protect sensitive information, leaving confidential data vulnerable to unauthorized access, sharing, or exfiltration. Conversely, too many labels presented to the end user overwhelm and reduce effectiveness. + +**Remediation action** + +To create sensitivity labels: +1. Navigate to [Microsoft Purview compliance portal > Information Protection > Labels](https://compliance.microsoft.com/informationprotection/labels) +2. Select "Create a label" +3. Configure label settings including: + - Name and description + - Scope (Files & emails, Meetings, Schematized data assets, etc.) + - Protection settings (encryption, content marking, auto-labeling) +4. Save the label +5. Publish the label via a label policy to make it available to users + +- [Learn about sensitivity labels](https://learn.microsoft.com/microsoft-365/compliance/sensitivity-labels) +- [Create and configure sensitivity labels](https://learn.microsoft.com/microsoft-365/compliance/create-sensitivity-labels) +- [Get started with sensitivity labels](https://learn.microsoft.com/microsoft-365/compliance/get-started-with-sensitivity-labels) + + +%TestResult% diff --git a/src/powershell/tests/Test-Assessment.35003.ps1 b/src/powershell/tests/Test-Assessment.35003.ps1 new file mode 100644 index 000000000..2cec00a11 --- /dev/null +++ b/src/powershell/tests/Test-Assessment.35003.ps1 @@ -0,0 +1,106 @@ +<# +.SYNOPSIS + Total Sensitivity Labels Configured + +.DESCRIPTION + This test checks if there is at least one sensitivity label configured in the tenant. + Sensitivity labels are the foundation of Microsoft Information Protection. + +.NOTES + Test ID: 35003 + Pillar: Data + Risk Level: High +#> + +function Test-Assessment-35003 { + [ZtTest( + Category = 'sensitivity-labels', + ImplementationCost = 'Medium', + MinimumLicense = ('MIP_P1'), + Pillar = 'Data', + RiskLevel = 'High', + SfiPillar = '', + TenantType = ('Workforce'), + TestId = 35003, + Title = 'Total Sensitivity Labels Configured', + UserImpact = 'Low' + )] + [CmdletBinding()] + param() + + #region Data Collection + Write-PSFMessage '🟦 Start' -Tag Test -Level VeryVerbose + + $activity = 'Checking Sensitivity Labels' + Write-ZtProgress -Activity $activity -Status 'Getting Sensitivity Labels' + + $labels = @() + $errorMsg = $null + + try { + # Query: Get all sensitivity labels + $labels = Get-Label -ErrorAction Stop + } + catch { + $errorMsg = $_ + Write-PSFMessage "Error querying Sensitivity Labels: $_" -Level Error + } + #endregion Data Collection + + #region Assessment Logic + if ($errorMsg) { + $passed = $false + } + else { + $passed = $labels.Count -gt 0 + } + #endregion Assessment Logic + + #region Report Generation + if ($errorMsg) { + $testResultMarkdown = "### Investigate`n`n" + $testResultMarkdown += "Unable to query sensitivity labels due to error: $errorMsg" + } + else { + if ($passed) { + $testResultMarkdown = "✅ At least one sensitivity label is configured in the tenant.`n`n" + } + else { + $testResultMarkdown = "❌ No sensitivity labels are configured.`n`n" + } + + $testResultMarkdown += "### Sensitivity Label Configuration Summary`n`n" + $testResultMarkdown += "**Label Statistics:**`n" + $testResultMarkdown += "* Total Label Count: $($labels.Count)`n" + + $topLevelCount = ($labels | Where-Object { [string]::IsNullOrEmpty($_.ParentId) }).Count + $subLabelCount = ($labels | Where-Object { -not [string]::IsNullOrEmpty($_.ParentId) }).Count + + $testResultMarkdown += "* Top-Level Labels Count: $topLevelCount`n" + $testResultMarkdown += "* Sub-Labels Count: $subLabelCount`n`n" + + if ($labels.Count -gt 0) { + $testResultMarkdown += "**Sample Labels** (up to 5):`n" + $testResultMarkdown += "| Label Name | Priority | Parent Label |`n" + $testResultMarkdown += "|:---|:---|:---|`n" + + foreach ($label in ($labels | Select-Object -First 5)) { + $parentName = if (-not [string]::IsNullOrEmpty($label.ParentLabelDisplayName)) { $label.ParentLabelDisplayName } else { "None" } + $labelName = Get-SafeMarkdown -Text $label.DisplayName + $parentName = Get-SafeMarkdown -Text $parentName + $testResultMarkdown += "| $labelName | $($label.Priority) | $parentName |`n" + } + } + + $testResultMarkdown += "`n[Manage Sensitivity Labels in Microsoft Purview](https://purview.microsoft.com/informationprotection/informationprotectionlabels/sensitivitylabels)`n" + } + #endregion Report Generation + + $testResultDetail = @{ + TestId = '35003' + Title = 'Total Sensitivity Labels Configured' + Status = $passed + Result = $testResultMarkdown + } + Add-ZtTestResultDetail @testResultDetail +}