Skip to content

Commit 631c2cc

Browse files
committed
41060
1 parent 12983c2 commit 631c2cc

2 files changed

Lines changed: 168 additions & 19 deletions

File tree

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
Describe "Test-Assessment-41060" {
2+
BeforeAll {
3+
$here = $PSScriptRoot
4+
$srcRoot = Join-Path $here "../../src/powershell"
5+
6+
# Mock external module dependencies that may not be loaded in the test host
7+
if (-not (Get-Command Write-PSFMessage -ErrorAction SilentlyContinue)) {
8+
function Write-PSFMessage {
9+
}
10+
}
11+
if (-not (Get-Command Write-ZtProgress -ErrorAction SilentlyContinue)) {
12+
function Write-ZtProgress {
13+
}
14+
}
15+
if (-not (Get-Command Invoke-ZtGraphRequest -ErrorAction SilentlyContinue)) {
16+
function Invoke-ZtGraphRequest {
17+
param($RelativeUri, $Filter, $ApiVersion, $Top, [switch]$DisablePaging)
18+
}
19+
}
20+
if (-not (Get-Command Add-ZtTestResultDetail -ErrorAction SilentlyContinue)) {
21+
function Add-ZtTestResultDetail {
22+
}
23+
}
24+
if (-not (Get-Command Get-SafeMarkdown -ErrorAction SilentlyContinue)) {
25+
function Get-SafeMarkdown {
26+
param($Text) return $Text
27+
}
28+
}
29+
if (-not (Get-Command Get-FormattedDate -ErrorAction SilentlyContinue)) {
30+
function Get-FormattedDate {
31+
param($DateString) return $DateString
32+
}
33+
}
34+
35+
# Load the class
36+
$classPath = Join-Path $srcRoot "classes/ZtTest.ps1"
37+
if (-not ("ZtTest" -as [type])) {
38+
. $classPath
39+
}
40+
41+
# Load the SUT
42+
$sut = Join-Path $srcRoot "tests/Test-Assessment.41060.ps1"
43+
. $sut
44+
45+
# Setup output file
46+
$script:outputFile = Join-Path $here "../TestResults/Report-Test-Assessment.41060.md"
47+
$outputDir = Split-Path $script:outputFile
48+
if (-not (Test-Path $outputDir)) {
49+
New-Item -ItemType Directory -Path $outputDir | Out-Null
50+
}
51+
"# Test Results for 41060`n" | Set-Content $script:outputFile
52+
}
53+
54+
BeforeEach {
55+
Mock Write-PSFMessage {}
56+
Mock Write-ZtProgress {}
57+
Mock Get-SafeMarkdown { param($Text) return $Text }
58+
Mock Get-FormattedDate { param($DateString) return $DateString }
59+
}
60+
61+
Context "When all pinned cloud-protection controls are fully scored" {
62+
It "Should pass" {
63+
# Q1a: the three pinned MDATP Secure Score control profiles, each with a maxScore.
64+
# Q1b: the latest Secure Score snapshot whose controlScores meet or exceed each maxScore.
65+
# The mock branches on $RelativeUri to mirror the two Graph calls the test makes.
66+
Mock Invoke-ZtGraphRequest {
67+
if ($RelativeUri -eq 'security/secureScoreControlProfiles') {
68+
return @(
69+
[PSCustomObject]@{
70+
id = 'scid_2016'
71+
title = 'Turn on cloud-delivered protection in Microsoft Defender Antivirus'
72+
maxScore = 10
73+
lastModifiedDateTime = '2026-06-26T00:00:00Z'
74+
controlStateUpdates = @()
75+
},
76+
[PSCustomObject]@{
77+
id = 'scid_5094'
78+
title = 'Set cloud-delivered protection to advanced'
79+
maxScore = 8
80+
lastModifiedDateTime = '2026-06-26T00:00:00Z'
81+
controlStateUpdates = @()
82+
},
83+
[PSCustomObject]@{
84+
id = 'scid_6094'
85+
title = 'Enable cloud protection sample submission'
86+
maxScore = 9
87+
lastModifiedDateTime = '2026-06-26T00:00:00Z'
88+
controlStateUpdates = @()
89+
}
90+
)
91+
}
92+
elseif ($RelativeUri -eq 'security/secureScores') {
93+
# Shaped like GET /v1.0/security/secureScores?$top=1 (response wrapper with .value).
94+
return [PSCustomObject]@{
95+
'@odata.context' = 'https://graph.microsoft.com/v1.0/$metadata#security/secureScores'
96+
value = @(
97+
[PSCustomObject]@{
98+
id = '536279f6-15cc-45f2-be2d-61e352b51eef_2026-06-26'
99+
azureTenantId = '536279f6-15cc-45f2-be2d-61e352b51eef'
100+
createdDateTime = '2026-06-26T00:00:00Z'
101+
currentScore = 1032.09
102+
maxScore = 1717
103+
controlScores = @(
104+
[PSCustomObject]@{
105+
controlCategory = 'Device'
106+
controlName = 'scid_2016'
107+
score = 10
108+
scoreInPercentage = 100
109+
},
110+
[PSCustomObject]@{
111+
controlCategory = 'Device'
112+
controlName = 'scid_5094'
113+
score = 8
114+
scoreInPercentage = 100
115+
},
116+
[PSCustomObject]@{
117+
controlCategory = 'Device'
118+
controlName = 'scid_6094'
119+
score = 9
120+
scoreInPercentage = 100
121+
}
122+
)
123+
}
124+
)
125+
}
126+
}
127+
}
128+
129+
$script:capturedStatus = $null
130+
$script:capturedResult = $null
131+
Mock Add-ZtTestResultDetail {
132+
param($TestId, $Title, $Status, $Result, $CustomStatus)
133+
$script:capturedStatus = $Status
134+
$script:capturedResult = $Result
135+
"## Scenario: All pinned controls fully scored`n`n$Result`n" | Add-Content $script:outputFile
136+
}
137+
138+
Test-Assessment-41060
139+
140+
Should -Invoke Add-ZtTestResultDetail -Times 1 -Exactly -ParameterFilter {
141+
$Status -eq $true
142+
}
143+
$script:capturedResult | Should -Match 'Cloud-delivered protection is enabled'
144+
$script:capturedResult | Should -Match 'scid_2016'
145+
$script:capturedResult | Should -Match 'scid_5094'
146+
$script:capturedResult | Should -Match 'scid_6094'
147+
$script:capturedResult | Should -Match '✅ Pass'
148+
$script:capturedResult | Should -Not -Match '❌ Fail'
149+
}
150+
}
151+
}

src/powershell/tests/Test-Assessment.41060.ps1

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
1313
.NOTES
1414
Test ID: 41060
15+
Workshop Task Id: SECOPS-060
1516
Category: Endpoint threat protection
1617
Pillar: SecOps
1718
Required Module: Microsoft.Graph.Authentication
@@ -50,9 +51,9 @@ function Test-Assessment-41060 {
5051
$controlProfiles = @()
5152
try {
5253
$filter = "service eq 'MDATP' and (id eq 'scid_2016' or id eq 'scid_5094' or id eq 'scid_6094')"
53-
$encodedFilter = [uri]::EscapeDataString($filter)
5454
$controlProfiles = @(Invoke-ZtGraphRequest `
55-
-RelativeUri "security/secureScoreControlProfiles?`$filter=$encodedFilter" `
55+
-RelativeUri "security/secureScoreControlProfiles" `
56+
-Filter $filter `
5657
-ApiVersion v1.0 `
5758
-ErrorAction Stop)
5859
Write-PSFMessage "Q1a returned $($controlProfiles.Count) MDATP control profile(s)" -Tag Test -Level VeryVerbose
@@ -67,14 +68,20 @@ function Test-Assessment-41060 {
6768

6869
$latestSecureScore = $null
6970
try {
70-
$secureScores = @(Invoke-ZtGraphRequest `
71-
-RelativeUri 'security/secureScores?$top=1' `
71+
# -DisablePaging returns the raw Graph response wrapper (avoids paging the full score
72+
# history that $top=1 would otherwise trigger via the nextLink). Unwrap .value to get the
73+
# actual secureScore snapshot(s).
74+
$secureScoresResponse = Invoke-ZtGraphRequest `
75+
-RelativeUri 'security/secureScores' `
7276
-ApiVersion v1.0 `
73-
-ErrorAction Stop)
77+
-Top 1 `
78+
-ErrorAction Stop `
79+
-DisablePaging
80+
$secureScores = @($secureScoresResponse.value)
7481
if ($secureScores.Count -gt 0) {
7582
$latestSecureScore = $secureScores[0]
7683
}
77-
Write-PSFMessage "Q1b returned $($secureScores.Count) Secure Score snapshot(s)" -Tag Test -Level VeryVerbose
84+
Write-PSFMessage "Q1b returned $($secureScores.Count) Secure Score snapshot(s)" -Tag Test -Level Debug
7885
}
7986
catch {
8087
$scoreQueryFailed = $true
@@ -176,14 +183,8 @@ function Test-Assessment-41060 {
176183
{2}
177184
'@
178185

179-
$maxDisplay = 10
180-
# Surface non-passing controls first so failures are visible within the truncation window.
186+
# Surface non-passing controls first so failures are listed at the top.
181187
$displayResults = @($evaluationResults | Sort-Object RowPassed, Title)
182-
$hasMoreItems = $false
183-
if ($evaluationResults.Count -gt $maxDisplay) {
184-
$displayResults = @($displayResults | Select-Object -First $maxDisplay)
185-
$hasMoreItems = $true
186-
}
187188

188189
$tableRows = ''
189190
foreach ($result in $displayResults) {
@@ -192,17 +193,14 @@ function Test-Assessment-41060 {
192193
$tableRows += "| $(Get-SafeMarkdown $result.Title) | $($result.ControlId) | $($result.Score) | $($result.MaxScore) | $($result.Ignored) | $lastModifiedDisplay | $statusDisplay |`n"
193194
}
194195

195-
if ($hasMoreItems) {
196-
$remainingCount = $evaluationResults.Count - $maxDisplay
197-
$tableRows += "| ... | | | | | | |`n"
198-
$tableRows += "`nShowing $maxDisplay of $($evaluationResults.Count) items. [View all in Microsoft Secure Score]($portalLink)`n"
199-
}
200-
201196
$mdInfo = $formatTemplate -f $tableTitle, $portalLink, $tableRows
202197

203198
$testResultMarkdown = $testResultMarkdown -replace '%TestResult%', $mdInfo
204199
#endregion Report Generation
205200

201+
$passedCount = @($evaluationResults | Where-Object RowPassed).Count
202+
Write-PSFMessage "Emitted $($evaluationResults.Count) control results: $passedCount passed, $($failedItems.Count) failed" -Tag Test -Level VeryVerbose
203+
206204
Add-ZtTestResultDetail -TestId '41060' `
207205
-Title 'Cloud-delivered protection is enabled in Microsoft Defender Antivirus' `
208206
-Status $passed -Result $testResultMarkdown

0 commit comments

Comments
 (0)