Assets/RemediationLibrary/investigation-common/Get-AdditionalDeviceEvidence.ps1

#requires -Version 5.1
function Get-AdditionalDeviceEvidence {
    [CmdletBinding()]
    param([switch]$Certificates,[switch]$Events)
    if($Certificates){
        foreach($store in @('Cert:\LocalMachine\My','Cert:\CurrentUser\My')){
            try {
                $items=@(Get-ChildItem -LiteralPath $store -ErrorAction Stop | Select-Object -First 501)
                if($items.Count -gt 500){throw 'Certificate store exceeds the 500-record limit.'}
                $metadata=@($items | ForEach-Object {
                    [pscustomobject]@{Thumbprint=$_.Thumbprint;Issuer=$_.Issuer;NotBefore=$_.NotBefore.ToUniversalTime().ToString('o');NotAfter=$_.NotAfter.ToUniversalTime().ToString('o');HasPrivateKey=[bool]$_.HasPrivateKey;EnhancedKeyUsage=@($_.EnhancedKeyUsageList | ForEach-Object {[string]$_.ObjectId} | Sort-Object)}
                } | Sort-Object Thumbprint)
                [pscustomobject]@{Key="certificates/$store";State='Observed';Value=$metadata;Source=$store;Detail='Metadata only. No private key material, subject or SAN exported. Key presence does not prove the application can use it. CurrentUser is the executing identity.'}
            } catch {[pscustomobject]@{Key="certificates/$store";State='Unavailable';Value=$null;Source=$store;Detail=$_.Exception.Message}}
        }
    }
    if($Events){
        $end=Get-Date;$start=$end.AddDays(-7)
        foreach($log in @('Microsoft-Windows-DeviceManagement-Enterprise-Diagnostics-Provider/Admin','Microsoft-Windows-WindowsUpdateClient/Operational')){
            try {
                $items=@(Get-WinEvent -FilterHashtable @{LogName=$log;StartTime=$start;EndTime=$end;Level=@(2,3)} -MaxEvents 101 -ErrorAction Stop)
                $metadata=@($items | Select-Object -First 100 | ForEach-Object {[pscustomobject]@{Id=$_.Id;RecordId=$_.RecordId;TimeCreated=$_.TimeCreated.ToUniversalTime().ToString('o');Level=$_.Level;Provider=$_.ProviderName}})
                [pscustomobject]@{Key="events/$log";State='Observed';Value=@{WindowStart=$start.ToUniversalTime().ToString('o');WindowEnd=$end.ToUniversalTime().ToString('o');LimitReached=($items.Count -gt 100);Events=$metadata};Source=$log;Detail='Last seven days, warning/error metadata only, newest 100 records. No event messages or XML payloads. Event absence does not prove health.'}
            } catch {
                if($_.FullyQualifiedErrorId -like 'NoMatchingEventsFound*'){
                    [pscustomobject]@{Key="events/$log";State='Observed';Value=@{WindowStart=$start.ToUniversalTime().ToString('o');WindowEnd=$end.ToUniversalTime().ToString('o');LimitReached=$false;Events=@()};Source=$log;Detail='No matching events returned in the bounded query. This is not proof of health.'}
                } else {[pscustomobject]@{Key="events/$log";State='Unavailable';Value=$null;Source=$log;Detail=$_.Exception.Message}}
            }
        }
    }
}