Skip to content

Commit 7ad2b53

Browse files
committed
Refreshed demo content
1 parent 4b13c3a commit 7ad2b53

2 files changed

Lines changed: 143 additions & 8 deletions

File tree

build/demo-report/New-DemoReport.ps1

Lines changed: 130 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,17 @@ param(
3030
[string]$InputJsonPath,
3131

3232
[Parameter(Mandatory = $true)]
33-
[string]$OutputHtmlPath
33+
[string]$OutputHtmlPath,
34+
35+
# Optional secondary report. When supplied, the Network and AI pillars (all
36+
# their tests + the matching summary counts) are overlaid from this report,
37+
# replacing that data in the primary -InputJsonPath. Everything else
38+
# (Identity / Devices / Data / SecOps, tenant identity, dashboard overview)
39+
# is kept from the primary report. Brought tests are fully scrubbed of the
40+
# source tenant's identifiers (emails, IPs, domain, brand, GUID).
41+
[Parameter(Mandatory = $false)]
42+
[ValidateScript({ Test-Path $_ -PathType Leaf })]
43+
[string]$SourceJsonPath
3444
)
3545

3646
# Set up paths
@@ -76,6 +86,125 @@ Write-Host "Loading JSON report from: $InputJsonPath" -ForegroundColor Cyan
7686
# Load the JSON report
7787
$jsonContent = Get-Content -Path $InputJsonPath -Raw | ConvertFrom-Json -Depth 100
7888

89+
# ---------------------------------------------------------------------------
90+
# Optional: overlay the Network + AI pillars from a secondary source report.
91+
# Real exports often have far richer Network (Global Secure Access / Internet
92+
# Access) and AI pillars than the curated demo input. When -SourceJsonPath is
93+
# supplied we drop the primary report's Network/AI tests, bring in every
94+
# Network/AI test from the source, and copy the matching summary counts. This
95+
# also drives the home-page SWG defense-layer graphic, which keys off specific
96+
# Network TestIds.
97+
#
98+
# Because the source is a *real* tenant, every brought test is fully scrubbed
99+
# here (emails -> demouser<N>@contoso.com, IPv4 -> 203.0.113.x, tenant
100+
# domain/brand/GUID -> Contoso) before it is merged, in addition to the normal
101+
# anonymization passes that run later.
102+
# ---------------------------------------------------------------------------
103+
if ($PSBoundParameters.ContainsKey('SourceJsonPath')) {
104+
$bringPillars = @('Network', 'AI')
105+
Write-Host ("Overlaying {0} pillar(s) from source: {1}" -f ($bringPillars -join ' + '), $SourceJsonPath) -ForegroundColor Cyan
106+
$sourceContent = Get-Content -Path $SourceJsonPath -Raw | ConvertFrom-Json -Depth 100
107+
108+
function Get-PillarSet {
109+
param($Test)
110+
$p = $Test.TestPillar
111+
if ($null -eq $p) { return @() }
112+
if ($p -is [System.Array]) { return @($p) }
113+
return @($p)
114+
}
115+
116+
$isBrought = {
117+
param($test)
118+
$pillars = Get-PillarSet $test
119+
foreach ($x in $pillars) { if ($bringPillars -contains $x) { return $true } }
120+
return $false
121+
}
122+
123+
$keptTests = @($jsonContent.Tests | Where-Object { -not (& $isBrought $_) })
124+
$broughtTests = @($sourceContent.Tests | Where-Object { & $isBrought $_ })
125+
126+
# Re-tag brought tests to the intersection of their pillars and the pillars
127+
# we overlay. This drops non-brought tags (e.g. "Data" on a ["Data","AI"]
128+
# test, so it doesn't surface on the sample-owned Data page) while keeping
129+
# brought tags (e.g. a ["Network","AI"] test stays on both pages).
130+
foreach ($test in $broughtTests) {
131+
$kept = @(Get-PillarSet $test | Where-Object { $bringPillars -contains $_ })
132+
$test.TestPillar = if ($kept.Count -eq 1) { $kept[0] } else { $kept }
133+
}
134+
135+
# --- Full scrub of source-derived (real tenant) content ---
136+
$demoTenantId = 'aaaabbbb-0000-cccc-1111-dddd2222eeee'
137+
$srcTenantId = [string]$sourceContent.TenantId
138+
$srcDomain = [string]$sourceContent.Domain
139+
$srcName = [string]$sourceContent.TenantName
140+
$srcBrand = if ($srcDomain -match '^([^.]+)\.') { $matches[1] } else { $srcName }
141+
142+
$script:__emailAliases = @{}
143+
$script:__emailNext = 1
144+
$script:__ipAliases = @{}
145+
$script:__ipNext = 10
146+
147+
$scrub = {
148+
param([string]$text)
149+
if ([string]::IsNullOrEmpty($text)) { return $text }
150+
151+
# Emails -> deterministic demouser<N>@contoso.com (leave demo/Microsoft as-is).
152+
$text = [regex]::Replace($text, '[A-Za-z0-9._%+\-]+@[A-Za-z0-9.\-]+\.[A-Za-z]{2,}', {
153+
param($m)
154+
$e = $m.Value
155+
if ($e -match '(?i)@(contoso\.com|contoso\.onmicrosoft\.com|microsoft\.com)$') { return $e }
156+
if (-not $script:__emailAliases.ContainsKey($e)) {
157+
$script:__emailAliases[$e] = "demouser$($script:__emailNext)@contoso.com"
158+
$script:__emailNext++
159+
}
160+
return $script:__emailAliases[$e]
161+
})
162+
163+
# IPv4 -> deterministic TEST-NET (RFC 5737) 203.0.113.x.
164+
$text = [regex]::Replace($text, '\b(?:\d{1,3}\.){3}\d{1,3}\b', {
165+
param($m)
166+
$ip = $m.Value
167+
if (-not $script:__ipAliases.ContainsKey($ip)) {
168+
$script:__ipAliases[$ip] = "203.0.113.$($script:__ipNext)"
169+
$script:__ipNext++
170+
}
171+
return $script:__ipAliases[$ip]
172+
})
173+
174+
if ($srcTenantId) { $text = $text -replace [regex]::Escape($srcTenantId), $demoTenantId }
175+
# Any onmicrosoft tenant remnants -> contoso.onmicrosoft.com.
176+
$text = $text -replace '(?i)[A-Za-z0-9-]+\.onmicrosoft\.com', 'contoso.onmicrosoft.com'
177+
# Remaining references to the source domain (URLs, bare host names) -> contoso.com.
178+
if ($srcDomain) { $text = $text -replace ('(?i)[A-Za-z0-9.\-]*' + [regex]::Escape($srcDomain)), 'contoso.com' }
179+
if ($srcName) { $text = $text -replace ('(?i)' + [regex]::Escape($srcName)), 'Contoso' }
180+
if ($srcBrand) { $text = $text -replace ('(?i)\b' + [regex]::Escape($srcBrand) + '\b'), 'contoso' }
181+
182+
return $text
183+
}
184+
185+
foreach ($test in $broughtTests) {
186+
foreach ($field in 'TestResult', 'TestDescription', 'SkippedReason') {
187+
if (($test.PSObject.Properties.Name -contains $field) -and ($test.$field -is [string])) {
188+
$test.$field = & $scrub $test.$field
189+
}
190+
}
191+
}
192+
193+
$jsonContent.Tests = @($keptTests + $broughtTests)
194+
195+
# Overlay the summary counts for each brought pillar.
196+
foreach ($pil in $bringPillars) {
197+
$jsonContent.TestResultSummary."${pil}Passed" = $sourceContent.TestResultSummary."${pil}Passed"
198+
$jsonContent.TestResultSummary."${pil}Total" = $sourceContent.TestResultSummary."${pil}Total"
199+
}
200+
201+
Write-Host ("Brought {0} test(s) across {1}; scrubbed {2} email(s) and {3} IP(s)" -f `
202+
$broughtTests.Count, ($bringPillars -join '/'), $script:__emailAliases.Count, $script:__ipAliases.Count) -ForegroundColor Cyan
203+
foreach ($pil in $bringPillars) {
204+
Write-Host (" {0} summary now {1}/{2}" -f $pil, $jsonContent.TestResultSummary."${pil}Passed", $jsonContent.TestResultSummary."${pil}Total") -ForegroundColor Cyan
205+
}
206+
}
207+
79208
Write-Host "Anonymizing report data..." -ForegroundColor Cyan
80209

81210
# Anonymize tenant information

0 commit comments

Comments
 (0)