Public/New-WorkstationBirthCertificate.ps1
|
function New-WorkstationBirthCertificate { <# .SYNOPSIS Generates a hardware audit, cryptographic manifest fingerprint, and Markdown Birth Certificate. .DESCRIPTION Audits physical or virtual workstation hardware components (Motherboard, CPU, RAM, NVMe/Disks, GPU, Firmware, TPM, Secure Boot) and computes a reproducible SHA-256 hardware fingerprint. Outputs both a rich PowerShell object and a documentation-ready Markdown file. .PARAMETER OutputPath Optional path to write the generated Markdown birth certificate. .PARAMETER PassThru Outputs the structured PSCustomObject to the pipeline. .EXAMPLE New-WorkstationBirthCertificate -OutputPath ".\BirthCertificate.md" .EXAMPLE $cert = New-WorkstationBirthCertificate -PassThru $cert.HardwareFingerprint #> [CmdletBinding()] param ( [Parameter(Position = 0)] [string]$OutputPath, [Parameter()] [switch]$PassThru ) Write-Verbose "Collecting workstation hardware details..." # Baseboard / Motherboard $baseBoard = Get-CimInstance -ClassName Win32_BaseBoard -ErrorAction SilentlyContinue | Select-Object -First 1 $bios = Get-CimInstance -ClassName Win32_Bios -ErrorAction SilentlyContinue | Select-Object -First 1 # CPU $cpu = Get-CimInstance -ClassName Win32_Processor -ErrorAction SilentlyContinue | Select-Object -First 1 # RAM $ramModules = Get-CimInstance -ClassName Win32_PhysicalMemory -ErrorAction SilentlyContinue $totalRamBytes = ($ramModules | Measure-Object -Property Capacity -Sum).Sum $totalRamGB = if ($totalRamBytes) { [math]::Round($totalRamBytes / 1GB, 2) } else { 0 } # Disks $disks = Get-CimInstance -ClassName Win32_DiskDrive -ErrorAction SilentlyContinue | ForEach-Object { [PSCustomObject]@{ Model = $_.Model SizeGB = [math]::Round($_.Size / 1GB, 2) InterfaceType = $_.InterfaceType MediaType = $_.MediaType } } # Video / GPU $gpus = Get-CimInstance -ClassName Win32_VideoController -ErrorAction SilentlyContinue | ForEach-Object { [PSCustomObject]@{ Name = $_.Name DriverVersion = $_.DriverVersion AdapterRAM_MB = if ($_.AdapterRAM) { [math]::Round($_.AdapterRAM / 1MB, 0) } else { $null } } } # Network Adapters $netAdapters = Get-NetAdapter -ErrorAction SilentlyContinue | Where-Object { $_.Status -eq 'Up' } | ForEach-Object { $ip = (Get-NetIPAddress -InterfaceIndex $_.ifIndex -AddressFamily IPv4 -ErrorAction SilentlyContinue).IPAddress [PSCustomObject]@{ Name = $_.Name InterfaceDescription = $_.InterfaceDescription MacAddress = $_.MacAddress IPv4Address = ($ip -join ', ') LinkSpeed = $_.LinkSpeed } } # Security & Firmware $secureBoot = try { Confirm-SecureBootUEFI -ErrorAction Stop } catch { 'Not Supported / Disabled' } $tpm = Get-CimInstance -Namespace 'root\cimv2\security\microsofttpm' -ClassName Win32_Tpm -ErrorAction SilentlyContinue | Select-Object -First 1 # OS $os = Get-CimInstance -ClassName Win32_OperatingSystem -ErrorAction SilentlyContinue | Select-Object -First 1 # Compute Reproducible SHA-256 Hardware Fingerprint $rawEntropy = "$($baseBoard.SerialNumber)|$($baseBoard.Product)|$($cpu.ProcessorId)|$($cpu.Name)|$($disks[0].Model)" $hasher = [System.Security.Cryptography.SHA256]::Create() $bytes = [System.Text.Encoding]::UTF8.GetBytes($rawEntropy) $hashBytes = $hasher.ComputeHash($bytes) $fingerprint = -join ($hashBytes | ForEach-Object { '{0:x2}' -f $_ }) $certificate = [PSCustomObject]@{ ComputerName = $env:COMPUTERNAME GeneratedAt = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss") HardwareFingerprint = $fingerprint OperatingSystem = [PSCustomObject]@{ Caption = $os.Caption Version = $os.Version BuildNumber = $os.BuildNumber Architecture = $os.OSArchitecture InstallDate = $os.InstallDate } Motherboard = [PSCustomObject]@{ Manufacturer = $baseBoard.Manufacturer Product = $baseBoard.Product SerialNumber = $baseBoard.SerialNumber } BIOS = [PSCustomObject]@{ Version = $bios.SMBIOSBIOSVersion ReleaseDate = $bios.ReleaseDate } Processor = [PSCustomObject]@{ Name = $cpu.Name Cores = $cpu.NumberOfCores LogicalProcessors = $cpu.NumberOfLogicalProcessors MaxClockSpeedMHz = $cpu.MaxClockSpeed } Memory = [PSCustomObject]@{ TotalPhysicalGB = $totalRamGB ModuleCount = ($ramModules | Measure-Object).Count SpeedMHz = ($ramModules | Select-Object -First 1).Speed } Storage = $disks Graphics = $gpus Network = $netAdapters Security = [PSCustomObject]@{ SecureBoot = $secureBoot TpmPresent = [bool]$tpm TpmVersion = if ($tpm) { $tpm.SpecVersion } else { 'None' } } } # Generate Markdown representation $md = @" # 📜 Workstation Birth Certificate: $($certificate.ComputerName) > **Hardware Fingerprint (SHA-256):** ``$($certificate.HardwareFingerprint)`` > **Provisioned / Documented:** $($certificate.GeneratedAt) --- ## 🖥️ Operating System | Property | Value | | :--- | :--- | | **OS Name** | $($certificate.OperatingSystem.Caption) | | **Version / Build** | $($certificate.OperatingSystem.Version) (Build $($certificate.OperatingSystem.BuildNumber)) | | **Architecture** | $($certificate.OperatingSystem.Architecture) | --- ## ⚡ Core Hardware & Firmware | Component | Details | | :--- | :--- | | **Motherboard** | $($certificate.Motherboard.Manufacturer) $($certificate.Motherboard.Product) (S/N: $($certificate.Motherboard.SerialNumber)) | | **BIOS Version** | $($certificate.BIOS.Version) | | **Processor** | $($certificate.Processor.Name) ($($certificate.Processor.Cores) Cores / $($certificate.Processor.LogicalProcessors) Threads) | | **Memory (RAM)** | $($certificate.Memory.TotalPhysicalGB) GB ($($certificate.Memory.ModuleCount) modules @ $($certificate.Memory.SpeedMHz) MHz) | --- ## 🔒 Platform Security | Feature | Status | | :--- | :--- | | **Secure Boot** | $($certificate.Security.SecureBoot) | | **TPM 2.0 Security** | $(if ($certificate.Security.TpmPresent) { "Present ($($certificate.Security.TpmVersion))" } else { "Not Detected" }) | --- ## 💾 Storage Drives | Model | Size (GB) | Interface | Type | | :--- | :--- | :--- | :--- | $($certificate.Storage | ForEach-Object { "| $($_.Model) | $($_.SizeGB) | $($_.InterfaceType) | $($_.MediaType) |" } | Out-String).TrimEnd() --- ## 🎮 Display & Graphics | GPU Adapter | Driver Version | Video RAM (MB) | | :--- | :--- | :--- | $($certificate.Graphics | ForEach-Object { "| $($_.Name) | $($_.DriverVersion) | $($_.AdapterRAM_MB) |" } | Out-String).TrimEnd() --- ## 🌐 Active Network Interfaces | Interface Name | Description | MAC Address | IPv4 | | :--- | :--- | :--- | :--- | $($certificate.Network | ForEach-Object { "| $($_.Name) | $($_.InterfaceDescription) | $($_.MacAddress) | $($_.IPv4Address) |" } | Out-String).TrimEnd() --- *Generated autonomously by **LocalPilot** (https://github.com/thebubbsy/LocalPilot)* "@ if ($OutputPath) { $parentDir = Split-Path -Path $OutputPath -Parent if ($parentDir -and -not (Test-Path -Path $parentDir)) { New-Item -Path $parentDir -ItemType Directory -Force | Out-Null } $md | Set-Content -Path $OutputPath -Encoding utf8 Write-Host " [LocalPilot] Birth Certificate written to '$OutputPath'" -ForegroundColor Green } if ($PassThru -or -not $OutputPath) { return $certificate } } |