Files
Samsara/powershell/Get-ServerInventory.ps1
oceans2alaska 610a3bb447 Privacy hardening, remote-peer IP masking and review fixes
- Add privacy projection (core/privacy.py), private report storage, bounded
  process capture; omit identities, free text and unapproved paths
- Mask remote peer IPs: only loopback/host/wildcard stay numeric, others are
  reduced to remote_scope private/public (schema + scoring updated)
- Map ss TCP states to canonical names; ASCII-only numeric fields; fix
  "Microsoft Visual C++" product matching (Python and PowerShell)
- Merge 7fed3b9: -Diagnostic switch, serialization exit code 3, PS7 module
  path, UI error detail; keep hardened task/certificate collectors
- Add audit docs, privacy docs and regression tests

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-04 18:50:24 -08:00

63 lines
3.1 KiB
PowerShell

#requires -Version 5.1
[CmdletBinding()]
param([ValidateSet('all','system','roles','services','network','tasks','software','storage','shares','certificates')][string]$Section = 'all', [switch]$Diagnostic)
$ErrorActionPreference = 'Stop'
$ProgressPreference = 'SilentlyContinue'
$WarningPreference = 'SilentlyContinue'
$InformationPreference = 'SilentlyContinue'
$env:PSModulePath = Join-Path $PSHOME 'Modules'
if ($PSVersionTable.PSEdition -eq 'Core') {
# Inbox Windows modules remain under WindowsPowerShell when invoked from PS7.
$env:PSModulePath += ';' + (Join-Path ([Environment]::SystemDirectory) 'WindowsPowerShell\v1.0\Modules')
}
$script:SamsaraDiagnostic = $Diagnostic.IsPresent
[Console]::OutputEncoding = New-Object System.Text.UTF8Encoding($false)
if ([Environment]::OSVersion.Platform -ne [PlatformID]::Win32NT) {
[Console]::Error.WriteLine('This collector requires a local Windows Server execution host.')
exit 2
}
. (Join-Path $PSScriptRoot 'Inventory.Common.ps1')
Get-SamsaraPrivacyConfiguration
foreach ($file in @('System','Roles','Services','Network','Tasks','Software','Storage','Certificates')) {
. (Join-Path $PSScriptRoot ('Get-Server' + $file + '.ps1'))
}
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
try {
$principal = New-Object Security.Principal.WindowsPrincipal($identity)
$script:SamsaraIsElevated = $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
} finally { $identity.Dispose() }
$collectors = [ordered]@{
system = { param($r) Get-SamsaraSystem $r }; roles = { param($r) Get-SamsaraRoles $r }
services = { param($r) Get-SamsaraServices $r }; network = { param($r) Get-SamsaraNetwork $r }
tasks = { param($r) Get-SamsaraTasks $r }; software = { param($r) Get-SamsaraSoftware $r }
storage = { param($r) Get-SamsaraStorage $r }; shares = { param($r) Get-SamsaraShares $r }
certificates = { param($r) Get-SamsaraCertificates $r }
}
if ($Section -ne 'all') {
$result = Invoke-SamsaraSection $Section $collectors[$Section]
ConvertTo-SamsaraJson $result 12
exit 0
}
# Direct PowerShell use emits the same complete inventory envelope as the Python backend.
$inventory = [ordered]@{ roles=@(); services=@(); network=@(); tasks=@(); software=@(); storage=@(); certificates=@() }
$checks = [ordered]@{}
$collectedAt = Get-SamsaraTimestamp
$server = $null
foreach ($name in $collectors.Keys) {
$result = Invoke-SamsaraSection $name $collectors[$name]
$checks[$name] = ConvertTo-SamsaraCheck $result
if ($name -eq 'system') {
$server = $result.data
if ([int]$server.product_type -notin @(2,3) -or $server.os_version -notin @('2016','2019','2022','2025')) {
[Console]::Error.WriteLine('Unable to verify a supported Windows Server identity. No inventory emitted.')
exit 2
}
} elseif ($name -eq 'shares') { $inventory.storage += @($result.data) }
else { $inventory[$name] = @($result.data) }
}
ConvertTo-SamsaraJson ([ordered]@{ schema_version='1.0'; synthetic=$false; collected_at=$collectedAt
server=$server; checks=$checks; inventory=$inventory }) 14
exit 0