#Requires -Version 5.1 <# .SYNOPSIS Automatyczny test wdrozenia certyfikatow i konfiguracji Wi-Fi/LAN (TEAP/802.1X). Wersja NON-ADMIN v3.0 .NOTES Wymagania: Windows 10/11, PowerShell 5.1+ #> # ================================================================ # KONFIGURACJA # ================================================================ $Config = @{ ExpectedSSID = "WIFI_USERS" ComputerCertSubject = "LAP-" UserCertSubject = "" ExpectedIssuer = "InPost-SUB01-CA" ExpectedRootCA = "INPOST-ROOT-CA" ExpectedSubCA = "InPost-SUB01-CA" MinValidDaysWarning = 30 MinValidDaysError = 7 ExpectedEAPType = 55 # 55=TEAP, 13=EAP-TLS, 25=PEAP AcceptableEAPTypes = @(55, 13) # Typy EAP ktore sa akceptowalne (TEAP lub EAP-TLS jako outer) ExportDir = "C:\Temp" } # ================================================================ $Results = [System.Collections.Generic.List[PSCustomObject]]::new() $Passed = 0; $Failed = 0; $Warnings = 0 $LINE = "=" * 70 $LINE2 = "-" * 70 # ---------------------------------------------------------------- # Funkcje pomocnicze # ---------------------------------------------------------------- function Write-Header { param([string]$Text) Write-Host "`n$LINE" -ForegroundColor Cyan Write-Host " $Text" -ForegroundColor White Write-Host $LINE -ForegroundColor Cyan } function Write-SubHeader { param([string]$Text) Write-Host "`n $LINE2" -ForegroundColor DarkCyan Write-Host " >> $Text" -ForegroundColor DarkCyan Write-Host " $LINE2" -ForegroundColor DarkCyan } function Add-Result { param( [string]$Category, [string]$TestName, [ValidateSet("PASS","FAIL","WARN","INFO","SKIP")] [string]$Status, [string]$Detail = "" ) $color = switch ($Status) { "PASS" { "Green" } "FAIL" { "Red" } "WARN" { "Yellow" } "SKIP" { "Magenta" } "INFO" { "Cyan" } } $icon = switch ($Status) { "PASS" { "[ OK ]" } "FAIL" { "[FAIL]" } "WARN" { "[WARN]" } "SKIP" { "[SKIP]" } "INFO" { "[INFO]" } } Write-Host " $icon $TestName" -ForegroundColor $color if ($Detail) { Write-Host " --> $Detail" -ForegroundColor DarkGray } $script:Results.Add([PSCustomObject]@{ Nr = $script:Results.Count + 1 Kategoria = $Category Test = $TestName Status = $Status Szczegoly = $Detail Czas = (Get-Date -Format "yyyy-MM-dd HH:mm:ss") }) switch ($Status) { "PASS" { $script:Passed++ } "FAIL" { $script:Failed++ } "WARN" { $script:Warnings++ } } } function Get-CertCN { param($Subject) if ($Subject -match "CN=([^,]+)") { return $Matches[1] } else { return $Subject } } function Get-EAPName { param([int]$Type) switch ($Type) { 55 {"TEAP"} 13 {"EAP-TLS"} 25 {"PEAP"} 21 {"TTLS"} default {"Typ $Type"} } } # ================================================================ # TEST 1: Certyfikat uzytkownika # ================================================================ function Test-UserCertificate { Write-Header "TEST 1: Certyfikat UZYTKOWNIKA [CurrentUser\My]" $allCerts = Get-ChildItem "Cert:\CurrentUser\My" -ErrorAction SilentlyContinue if ($null -eq $allCerts) { Add-Result "1-Cert-User" "Dostep do magazynu CurrentUser\My" "FAIL" "Nie mozna otworzyc magazynu certyfikatow."; return } Add-Result "1-Cert-User" "Dostep do magazynu CurrentUser\My" "PASS" "Magazyn dostepny. Wszystkich certyfikatow: $($allCerts.Count)" $certs = $allCerts | Where-Object { $_.Issuer -like "*$($Config.ExpectedIssuer)*" } if ($Config.UserCertSubject) { $certs = $certs | Where-Object { $_.Subject -like "*$($Config.UserCertSubject)*" } } if ($certs.Count -eq 0) { Add-Result "1-Cert-User" "Certyfikat wystawiony przez $($Config.ExpectedIssuer)" "FAIL" "Brak certyfikatow uzytkownika wystawionych przez '$($Config.ExpectedIssuer)'."; return } Add-Result "1-Cert-User" "Certyfikaty wystawione przez $($Config.ExpectedIssuer)" "PASS" "Znaleziono: $($certs.Count) certyfikat(ow)" $now = Get-Date; $i = 0 foreach ($cert in $certs) { $i++ $daysLeft = ($cert.NotAfter - $now).Days Write-SubHeader "Certyfikat uzytkownika #$i z $($certs.Count)" Add-Result "1-Cert-User" "Subject (pelna nazwa)" "INFO" $cert.Subject Add-Result "1-Cert-User" "Issuer (wystawca)" "INFO" $cert.Issuer Add-Result "1-Cert-User" "Thumbprint" "INFO" $cert.Thumbprint Add-Result "1-Cert-User" "Numer seryjny" "INFO" $cert.SerialNumber Add-Result "1-Cert-User" "Wazny OD" "INFO" $cert.NotBefore.ToString('yyyy-MM-dd HH:mm') Add-Result "1-Cert-User" "Wazny DO" "INFO" $cert.NotAfter.ToString('yyyy-MM-dd HH:mm') $waznoscLabel = "Waznosc certyfikatu [$($cert.NotAfter.ToString('yyyy-MM-dd'))]" if ($daysLeft -lt 0) { Add-Result "1-Cert-User" $waznoscLabel "FAIL" "WYGASL $([Math]::Abs($daysLeft)) dni temu!" } elseif ($daysLeft -lt $Config.MinValidDaysError) { Add-Result "1-Cert-User" $waznoscLabel "FAIL" "Wygasa za $daysLeft dni – krytyczne!" } elseif ($daysLeft -lt $Config.MinValidDaysWarning) { Add-Result "1-Cert-User" $waznoscLabel "WARN" "Wygasa za $daysLeft dni – ostrzezenie." } else { Add-Result "1-Cert-User" $waznoscLabel "PASS" "Pozostalo $daysLeft dni waznosci." } $sanExt = $cert.Extensions | Where-Object { $_.Oid.FriendlyName -eq "Subject Alternative Name" } if ($sanExt) { Add-Result "1-Cert-User" "Subject Alternative Names (SAN)" "INFO" $sanExt.Format($false) } if ($cert.HasPrivateKey) { Add-Result "1-Cert-User" "Klucz prywatny" "PASS" "Dostepny – uwierzytelnienie 802.1X mozliwe." } else { Add-Result "1-Cert-User" "Klucz prywatny" "FAIL" "BRAK – uwierzytelnienie 802.1X NIEMOZLIWE!" } $ekuExt = $cert.Extensions | Where-Object { $_.Oid.FriendlyName -eq "Enhanced Key Usage" } if ($ekuExt) { $ekuVal = $ekuExt.Format($false) $hasClient = $ekuVal -match "1\.3\.6\.1\.5\.5\.7\.3\.2|Client Authentication" Add-Result "1-Cert-User" "EKU – Client Authentication" $(if ($hasClient) {"PASS"} else {"FAIL"}) $(if ($hasClient) {"Client Authentication (1.3.6.1.5.5.7.3.2) – OK"} else {"BRAK EKU Client Authentication – certyfikat nie nadaje sie do 802.1X!"}) } $chain = [System.Security.Cryptography.X509Certificates.X509Chain]::new() $chain.ChainPolicy.RevocationMode = [System.Security.Cryptography.X509Certificates.X509RevocationMode]::NoCheck if ($chain.Build($cert)) { $chainPath = ($chain.ChainElements | ForEach-Object { Get-CertCN $_.Certificate.Subject }) -join " --> " Add-Result "1-Cert-User" "Lancuch zaufania" "PASS" "Poprawny ($($chain.ChainElements.Count) elementow)" Add-Result "1-Cert-User" "Sciezka certyfikatu" "INFO" $chainPath } else { $errs = ($chain.ChainStatus | ForEach-Object { $_.StatusInformation.Trim() }) -join "; " Add-Result "1-Cert-User" "Lancuch zaufania" "WARN" "Problemy: $errs" } } } # ================================================================ # TEST 2: Certyfikat komputerowy # ================================================================ function Test-ComputerCertificate { Write-Header "TEST 2: Certyfikat KOMPUTEROWY [LocalMachine\My]" Add-Result "2-Cert-Computer" "Klucze prywatne LocalMachine\My" "SKIP" "Weryfikacja kluczy prywatnych wymaga uprawnien administratora." $allCerts = Get-ChildItem "Cert:\LocalMachine\My" -ErrorAction SilentlyContinue if ($null -eq $allCerts) { Add-Result "2-Cert-Computer" "Dostep do magazynu LocalMachine\My" "WARN" "Brak dostepu – moze wymagac admina."; return } Add-Result "2-Cert-Computer" "Dostep do magazynu LocalMachine\My" "PASS" "Magazyn dostepny. Wszystkich certyfikatow: $($allCerts.Count)" $certs = $allCerts | Where-Object { $_.Issuer -like "*$($Config.ExpectedIssuer)*" } if ($Config.ComputerCertSubject) { $certs = $certs | Where-Object { $_.Subject -like "*$($Config.ComputerCertSubject)*" } } if ($certs.Count -eq 0) { Add-Result "2-Cert-Computer" "Certyfikat wystawiony przez $($Config.ExpectedIssuer)" "FAIL" "Brak certyfikatow pasujacych do konfiguracji (Issuer: $($Config.ExpectedIssuer), Subject zawiera: '$($Config.ComputerCertSubject)')."; return } Add-Result "2-Cert-Computer" "Certyfikaty wystawione przez $($Config.ExpectedIssuer)" "PASS" "Znaleziono: $($certs.Count) certyfikat(ow)" $now = Get-Date; $i = 0 foreach ($cert in $certs) { $i++ $daysLeft = ($cert.NotAfter - $now).Days Write-SubHeader "Certyfikat komputerowy #$i z $($certs.Count)" Add-Result "2-Cert-Computer" "Subject (pelna nazwa)" "INFO" $cert.Subject Add-Result "2-Cert-Computer" "Issuer (wystawca)" "INFO" $cert.Issuer Add-Result "2-Cert-Computer" "Thumbprint" "INFO" $cert.Thumbprint Add-Result "2-Cert-Computer" "Numer seryjny" "INFO" $cert.SerialNumber Add-Result "2-Cert-Computer" "Wazny OD" "INFO" $cert.NotBefore.ToString('yyyy-MM-dd HH:mm') Add-Result "2-Cert-Computer" "Wazny DO" "INFO" $cert.NotAfter.ToString('yyyy-MM-dd HH:mm') $waznoscLabel = "Waznosc certyfikatu [$($cert.NotAfter.ToString('yyyy-MM-dd'))]" if ($daysLeft -lt 0) { Add-Result "2-Cert-Computer" $waznoscLabel "FAIL" "WYGASL $([Math]::Abs($daysLeft)) dni temu!" } elseif ($daysLeft -lt $Config.MinValidDaysError) { Add-Result "2-Cert-Computer" $waznoscLabel "FAIL" "Wygasa za $daysLeft dni – krytyczne!" } elseif ($daysLeft -lt $Config.MinValidDaysWarning) { Add-Result "2-Cert-Computer" $waznoscLabel "WARN" "Wygasa za $daysLeft dni." } else { Add-Result "2-Cert-Computer" $waznoscLabel "PASS" "Pozostalo $daysLeft dni waznosci." } $sanExt = $cert.Extensions | Where-Object { $_.Oid.FriendlyName -eq "Subject Alternative Name" } if ($sanExt) { Add-Result "2-Cert-Computer" "Subject Alternative Names (SAN)" "INFO" $sanExt.Format($false) } $ekuExt = $cert.Extensions | Where-Object { $_.Oid.FriendlyName -eq "Enhanced Key Usage" } if ($ekuExt) { $ekuVal = $ekuExt.Format($false) $hasClient = $ekuVal -match "1\.3\.6\.1\.5\.5\.7\.3\.2|Client Authentication" Add-Result "2-Cert-Computer" "EKU – Client Authentication" $(if ($hasClient) {"PASS"} else {"FAIL"}) $(if ($hasClient) {"Client Authentication (1.3.6.1.5.5.7.3.2) – OK"} else {"BRAK EKU Client Authentication!"}) } Add-Result "2-Cert-Computer" "Klucz prywatny" "SKIP" "Weryfikacja klucza prywatnego wymaga uprawnien administratora." } } # ================================================================ # TEST 3: Urzedy certyfikacji # ================================================================ function Test-CertificateAuthorities { Write-Header "TEST 3: URZEDY CERTYFIKACJI (CA)" Write-SubHeader "Zaufane Glowne Urzedy Certyfikacji [LocalMachine\Root]" $rootStore = Get-ChildItem "Cert:\LocalMachine\Root" -ErrorAction SilentlyContinue if ($null -eq $rootStore) { Add-Result "3-CA" "Dostep do LocalMachine\Root" "WARN" "Brak dostepu do magazynu Root CA." } else { $rootCAs = $rootStore | Where-Object { $_.Subject -like "*$($Config.ExpectedRootCA)*" } if ($rootCAs) { Add-Result "3-CA" "ROOT CA: $($Config.ExpectedRootCA)" "PASS" "Znaleziono $($rootCAs.Count) certyfikat(ow) w Zaufanych Glownych CA." foreach ($ca in $rootCAs) { $days = ($ca.NotAfter - (Get-Date)).Days Add-Result "3-CA" "Subject ROOT CA" "INFO" $ca.Subject Add-Result "3-CA" "Thumbprint ROOT CA" "INFO" $ca.Thumbprint Add-Result "3-CA" "Wazny DO (ROOT CA)" $(if ($days -gt 30) {"PASS"} elseif ($days -gt 0) {"WARN"} else {"FAIL"}) "$($ca.NotAfter.ToString('yyyy-MM-dd')) (pozostalo $days dni)" } } else { Add-Result "3-CA" "ROOT CA: $($Config.ExpectedRootCA)" "FAIL" "NIE ZNALEZIONO '$($Config.ExpectedRootCA)' w Zaufanych Glownych Urzedach Certyfikacji! Klienci nie beda ufac certyfikatom tej CA." } } Write-SubHeader "Posrednie Urzedy Certyfikacji [LocalMachine\CA]" $subStore = Get-ChildItem "Cert:\LocalMachine\CA" -ErrorAction SilentlyContinue if ($null -eq $subStore) { Add-Result "3-CA" "Dostep do LocalMachine\CA" "WARN" "Brak dostepu do magazynu posrednich CA." } else { $subCAs = $subStore | Where-Object { $_.Subject -like "*$($Config.ExpectedSubCA)*" } if ($subCAs) { Add-Result "3-CA" "SUB CA: $($Config.ExpectedSubCA)" "PASS" "Znaleziono $($subCAs.Count) certyfikat(ow) w Posrednich CA." foreach ($ca in $subCAs) { $days = ($ca.NotAfter - (Get-Date)).Days Add-Result "3-CA" "Subject SUB CA" "INFO" $ca.Subject Add-Result "3-CA" "Issuer SUB CA" "INFO" $ca.Issuer Add-Result "3-CA" "Thumbprint SUB CA" "INFO" $ca.Thumbprint Add-Result "3-CA" "Wazny DO (SUB CA)" $(if ($days -gt 30) {"PASS"} elseif ($days -gt 0) {"WARN"} else {"FAIL"}) "$($ca.NotAfter.ToString('yyyy-MM-dd')) (pozostalo $days dni)" } } else { Add-Result "3-CA" "SUB CA: $($Config.ExpectedSubCA)" "FAIL" "NIE ZNALEZIONO '$($Config.ExpectedSubCA)' w Posrednich Urzedach Certyfikacji! Lancuch zaufania bedzie niekompletny." } } Write-SubHeader "Magazyn uzytkownika [CurrentUser\Root]" $userRoot = Get-ChildItem "Cert:\CurrentUser\Root" -ErrorAction SilentlyContinue | Where-Object { $_.Subject -like "*$($Config.ExpectedRootCA)*" } if ($userRoot) { Add-Result "3-CA" "ROOT CA w CurrentUser\Root" "INFO" "Takze obecny w magazynie uzytkownika." } else { Add-Result "3-CA" "ROOT CA w CurrentUser\Root" "INFO" "Nieobecny w CurrentUser\Root (normalnie wystarczy LocalMachine\Root)." } } # ================================================================ # TEST 4: Profil Wi-Fi i konfiguracja EAP # ================================================================ function Test-WiFiProfile { Write-Header "TEST 4: PROFIL WI-FI i KONFIGURACJA EAP [netsh wlan]" $netshOutput = netsh wlan show profiles 2>&1 if ($LASTEXITCODE -ne 0) { Add-Result "4-WiFi" "Usluga WLAN AutoConfig" "FAIL" "Nie mozna pobrac listy profili."; return } $profiles = ($netshOutput | Select-String "Profil uzytkownika\s*:\s*(.+)|All User Profile\s*:\s*(.+)" | ForEach-Object { if ($_.Matches[0].Groups[1].Value) { $_.Matches[0].Groups[1].Value.Trim() } else { $_.Matches[0].Groups[2].Value.Trim() } }) if ($profiles.Count -eq 0) { Add-Result "4-WiFi" "Lista profili Wi-Fi" "FAIL" "Brak zapisanych profili WLAN."; return } Add-Result "4-WiFi" "Lista profili Wi-Fi" "INFO" "Dostepne: $($profiles -join ' | ')" $matchedProfile = $profiles | Where-Object { $_ -like "*$($Config.ExpectedSSID)*" } | Select-Object -First 1 if (-not $matchedProfile) { Add-Result "4-WiFi" "Profil SSID: $($Config.ExpectedSSID)" "FAIL" "Profil '$($Config.ExpectedSSID)' NIE ISTNIEJE. Dostepne: $($profiles -join ', ')"; return } Add-Result "4-WiFi" "Profil SSID: $($Config.ExpectedSSID)" "PASS" "Profil '$matchedProfile' znaleziony." $profileDetails = netsh wlan show profile name="$matchedProfile" 2>&1 $authLine = $profileDetails | Select-String "Uwierzytelnienie|Authentication" | Select-Object -First 1 if ($authLine) { $authValue = ($authLine -split ":")[1].Trim() Add-Result "4-WiFi" "Typ uwierzytelnienia" $(if ($authValue -match "WPA2|WPA3") {"PASS"} else {"WARN"}) "Uwierzytelnienie: $authValue" } $encLine = $profileDetails | Select-String "Szyfrowanie|Cipher" | Select-Object -First 1 if ($encLine) { Add-Result "4-WiFi" "Szyfrowanie" "INFO" "Szyfrowanie: $(($encLine -split ':')[1].Trim())" } $dot1xLine = $profileDetails | Select-String "802\.1X|OneX" | Select-Object -First 1 if ($dot1xLine) { $dot1xValue = ($dot1xLine -split ":")[1].Trim() Add-Result "4-WiFi" "802.1X wlaczone" $(if ($dot1xValue -match "Wlaczon|Enabled|Yes") {"PASS"} else {"FAIL"}) "802.1X: $dot1xValue" } else { Add-Result "4-WiFi" "802.1X w profilu" "WARN" "Nie wykryto wpisu 802.1X w detalach profilu." } # EAP Type z XML $xmlFile = $null try { $null = netsh wlan export profile name="$matchedProfile" folder="$env:TEMP" key=clear 2>&1; $xmlFile = Get-ChildItem "$env:TEMP\*.xml" | Sort-Object LastWriteTime -Descending | Select-Object -First 1 } catch {} if ($xmlFile) { [xml]$profileXml = Get-Content $xmlFile.FullName -Encoding UTF8 -ErrorAction SilentlyContinue Remove-Item $xmlFile.FullName -Force -ErrorAction SilentlyContinue if ($profileXml) { $eapTypeRaw = $profileXml.InnerXml | Select-String '(\d+)' -AllMatches | ForEach-Object { $_.Matches } | Select-Object -First 1 | ForEach-Object { $_.Groups[1].Value } if ($eapTypeRaw) { $eapType = [int]$eapTypeRaw $eapName = Get-EAPName $eapType $expName = Get-EAPName $Config.ExpectedEAPType if ($eapType -eq $Config.ExpectedEAPType) { Add-Result "4-WiFi" "Typ EAP w profilu" "PASS" "EAP Type = $eapType ($eapName) – zgodny z oczekiwanym ($expName)." } else { $acceptableNames = ($Config.AcceptableEAPTypes | ForEach-Object { "$(Get-EAPName $_) ($_)" }) -join ", " Add-Result "4-WiFi" "Typ EAP w profilu" "FAIL" "Profil uzywa EAP Type $eapType ($eapName), a oczekiwano $($Config.ExpectedEAPType) ($expName). WYJASNIENIE: Profil Wi-Fi ma skonfigurowany $eapName jako metode zewnetrzna (outer). Serwer ISE oczekuje $expName. Klient moze negocjowac typ EAP podczas polaczenia (NAK), ale niezgodnosc profilu z polityka serwera moze powodowac problemy z autentykacja. Sprawdz konfiguracje profilu w: Polaczenia sieciowe > Wlasciwosci sieci > Zabezpieczenia > Typ EAP. Akceptowalne typy w tym srodowisku: $acceptableNames." } } } } else { Add-Result "4-WiFi" "Odczyt EAP Type (XML)" "SKIP" "Eksport XML profilu nieudany bez uprawnien admina." } } # ================================================================ # TEST 5: Stan polaczenia Wi-Fi # ================================================================ function Test-WiFiConnection { Write-Header "TEST 5: STAN POLACZENIA WI-FI / 802.1X" $ifaceInfo = netsh wlan show interfaces 2>&1 $connectedSSID = ($ifaceInfo | Select-String "^\s+SSID\s+:\s+(?!BSSID)(.+)" | Select-Object -First 1 | ForEach-Object { $_.Matches[0].Groups[1].Value.Trim() }) if ($connectedSSID -eq $Config.ExpectedSSID) { Add-Result "5-Polaczenie" "Aktywny SSID" "PASS" "Polaczono z: $connectedSSID" } elseif ($connectedSSID) { Add-Result "5-Polaczenie" "Aktywny SSID" "WARN" "Polaczono z: '$connectedSSID' – oczekiwano: '$($Config.ExpectedSSID)'" } else { Add-Result "5-Polaczenie" "Aktywny SSID" "WARN" "Brak aktywnego polaczenia Wi-Fi." } $stateLine = ($ifaceInfo | Select-String "Stan\s+:\s+(.+)|State\s+:\s+(.+)" | Select-Object -First 1 | ForEach-Object { if ($_.Matches[0].Groups[1].Value) { $_.Matches[0].Groups[1].Value.Trim() } else { $_.Matches[0].Groups[2].Value.Trim() } }) if ($stateLine) { Add-Result "5-Polaczenie" "Stan adaptera" $(if ($stateLine -match "polaczon|connected") {"PASS"} else {"WARN"}) "Stan: $stateLine" } $signalLine = ($ifaceInfo | Select-String "Sygnal|Signal" | Select-Object -First 1 | ForEach-Object { ($_ -split ":")[1].Trim() }) if ($signalLine) { $signalVal = [int]($signalLine -replace '%','') $signalStatus = if ($signalVal -ge 70) {"PASS"} elseif ($signalVal -ge 40) {"WARN"} else {"FAIL"} $signalNote = if ($signalVal -lt 40) {"– ZA SLABY!"} elseif ($signalVal -lt 70) {"– akceptowalny"} else {"– dobry"} Add-Result "5-Polaczenie" "Sila sygnalu Wi-Fi" $signalStatus "Sygnal: $signalLine $signalNote" } $bssidLine = ($ifaceInfo | Select-String "BSSID\s+:\s+(.+)" | Select-Object -First 1 | ForEach-Object { $_.Matches[0].Groups[1].Value.Trim() }) if ($bssidLine) { Add-Result "5-Polaczenie" "BSSID (Access Point)" "INFO" $bssidLine } $radioLine = ($ifaceInfo | Select-String "Typ radia|Radio type" | Select-Object -First 1 | ForEach-Object { ($_ -split ":")[1].Trim() }) if ($radioLine) { Add-Result "5-Polaczenie" "Typ radia" "INFO" $radioLine } $channelLine = ($ifaceInfo | Select-String "Kanal|Channel" | Select-Object -First 1 | ForEach-Object { ($_ -split ":")[1].Trim() }) if ($channelLine) { Add-Result "5-Polaczenie" "Kanal" "INFO" $channelLine } $authLine = ($ifaceInfo | Select-String "Uwierzytelnienie|Authentication" | Select-Object -First 1 | ForEach-Object { ($_ -split ":")[1].Trim() }) if ($authLine) { Add-Result "5-Polaczenie" "Uwierzytelnienie" "INFO" $authLine } Add-Result "5-Polaczenie" "Logi 802.1X (Event Log)" "SKIP" "Odczyt Event Log WLAN wymaga uprawnien admina." if ($connectedSSID) { $pingOk = Test-Connection -ComputerName "8.8.8.8" -Count 2 -Quiet -ErrorAction SilentlyContinue Add-Result "5-Polaczenie" "Lacznosc sieciowa (ping 8.8.8.8)" $(if ($pingOk) {"PASS"} else {"WARN"}) $(if ($pingOk) {"Ping 8.8.8.8 OK – dostep do sieci potwierdzony."} else {"Brak odpowiedzi ping 8.8.8.8."}) $dnsOk = Resolve-DnsName "login.microsoftonline.com" -ErrorAction SilentlyContinue Add-Result "5-Polaczenie" "DNS – login.microsoftonline.com" $(if ($dnsOk) {"PASS"} else {"WARN"}) $(if ($dnsOk) {"Rozwiazanie DNS poprawne."} else {"Brak rozwiazania DNS."}) } } # ================================================================ # TEST 6: Konfiguracja 802.1X na interfejsach LAN # ================================================================ function Test-LAN8021X { Write-Header "TEST 6: KONFIGURACJA 802.1X – INTERFEJSY LAN" $lanAdapters = Get-NetAdapter | Where-Object { $_.PhysicalMediaType -notmatch "802.11|Native 802.11" -and $_.HardwareInterface -eq $true } if ($lanAdapters.Count -eq 0) { Add-Result "6-LAN" "Adaptery LAN" "INFO" "Nie wykryto kablowych adapterow sieciowych." return } Add-Result "6-LAN" "Wykryte interfejsy LAN" "INFO" "Znaleziono $($lanAdapters.Count) interfejs(ow): $($lanAdapters.Name -join ', ')" foreach ($adapter in $lanAdapters) { Write-SubHeader "Interfejs LAN: $($adapter.Name)" $statusOk = $adapter.Status -eq "Up" Add-Result "6-LAN" "Interfejs: $($adapter.Name)" $(if ($statusOk) {"PASS"} else {"WARN"}) "Status: $($adapter.Status) | MAC: $($adapter.MacAddress) | Predkosc: $($adapter.LinkSpeed)" Add-Result "6-LAN" "Opis adaptera" "INFO" $adapter.InterfaceDescription $ipConfig = Get-NetIPAddress -InterfaceIndex $adapter.InterfaceIndex -AddressFamily IPv4 -ErrorAction SilentlyContinue if ($ipConfig) { $isApipa = $ipConfig.IPAddress -match "^169\.254\." Add-Result "6-LAN" "Adres IPv4: $($adapter.Name)" $(if ($isApipa) {"WARN"} else {"PASS"}) $(if ($isApipa) {"APIPA: $($ipConfig.IPAddress) – mozliwy blad 802.1X lub brak DHCP!"} else {"IP: $($ipConfig.IPAddress)/$($ipConfig.PrefixLength)"}) } else { Add-Result "6-LAN" "Adres IPv4: $($adapter.Name)" "WARN" "Brak adresu IPv4." } # Konfiguracja 802.1X przez netsh lan $lanProfile = netsh lan show profiles interface="$($adapter.Name)" 2>&1 if ($LASTEXITCODE -eq 0 -and $lanProfile -notmatch "brak|no profile|not found") { Add-Result "6-LAN" "Profil 802.1X LAN: $($adapter.Name)" "PASS" "Profil 802.1X znaleziony na interfejsie." $dot1xLine = $lanProfile | Select-String "802\.1X\s*:\s*(.+)" | Select-Object -First 1 if ($dot1xLine) { Add-Result "6-LAN" "Status 802.1X" "INFO" $dot1xLine.Line.Trim() } $enforceLine = $lanProfile | Select-String "Enforced|Wymuszony" | Select-Object -First 1 if ($enforceLine) { Add-Result "6-LAN" "802.1X Enforced" "INFO" $enforceLine.Line.Trim() } $eapLine = $lanProfile | Select-String "EAP type|Typ EAP" | Select-Object -First 1 if ($eapLine) { Add-Result "6-LAN" "Typ EAP (LAN)" "INFO" $eapLine.Line.Trim() } $credLine = $lanProfile | Select-String "credential|uwierzytelnienie" | Select-Object -First 1 if ($credLine) { Add-Result "6-LAN" "Poswiadczenia 802.1X" "INFO" $credLine.Line.Trim() } $cacheLine = $lanProfile | Select-String "Cache|Pamiec" | Select-Object -First 1 if ($cacheLine) { Add-Result "6-LAN" "Cache poswiadczen" "INFO" $cacheLine.Line.Trim() } # Pelny output profilu jako INFO $profileClean = ($lanProfile | Where-Object { $_ -and $_.Trim() -ne "" }) -join " | " Add-Result "6-LAN" "Pelna konfiguracja profilu" "INFO" $profileClean } else { # Sprawdz przez netsh lan show interfaces $lanIface = netsh lan show interfaces 2>&1 $ifaceSection = $false; $ifaceLines = @() foreach ($line in $lanIface) { if ($line -match [regex]::Escape($adapter.Name)) { $ifaceSection = $true } if ($ifaceSection) { $ifaceLines += $line if ($ifaceLines.Count -gt 15) { break } } } if ($ifaceLines.Count -gt 0) { $dot1xStatus = $ifaceLines | Select-String "802\.1X\s*:\s*(.+)" | Select-Object -First 1 if ($dot1xStatus) { $val = ($dot1xStatus -split ":")[1].Trim() $enabled = $val -match "Enabled|Wlaczon" Add-Result "6-LAN" "802.1X na $($adapter.Name)" $(if ($enabled) {"PASS"} else {"INFO"}) "802.1X: $val" } else { Add-Result "6-LAN" "Profil 802.1X LAN: $($adapter.Name)" "INFO" "Brak profilu 802.1X lub 802.1X nie skonfigurowane na tym interfejsie." } } else { Add-Result "6-LAN" "Profil 802.1X LAN: $($adapter.Name)" "INFO" "Brak konfiguracji 802.1X na tym interfejsie." } } } } # ================================================================ # TEST 7: Karta sieciowa Wi-Fi # ================================================================ function Test-NetworkAdapter { Write-Header "TEST 7: KARTA SIECIOWA WI-FI" $adapters = Get-NetAdapter | Where-Object { ($_.InterfaceDescription -match "Wi-Fi|Wireless|WLAN|802.11") -and ($_.PhysicalMediaType -match "802.11|Native 802.11") } if ($adapters.Count -eq 0) { $adapters = Get-NetAdapter | Where-Object { $_.Name -match "Wi-Fi|WLAN|Wireless" } } if ($adapters.Count -eq 0) { Add-Result "7-Karta" "Adapter Wi-Fi" "WARN" "Nie wykryto adaptera Wi-Fi."; return } foreach ($adapter in $adapters) { Write-SubHeader "Adapter: $($adapter.Name)" $statusOk = $adapter.Status -eq "Up" Add-Result "7-Karta" "Adapter: $($adapter.Name)" $(if ($statusOk) {"PASS"} else {"WARN"}) "Status: $($adapter.Status) | MAC: $($adapter.MacAddress) | Predkosc: $($adapter.LinkSpeed)" Add-Result "7-Karta" "Opis adaptera" "INFO" $adapter.InterfaceDescription $ipConfig = Get-NetIPAddress -InterfaceIndex $adapter.InterfaceIndex -AddressFamily IPv4 -ErrorAction SilentlyContinue if ($ipConfig) { $isApipa = $ipConfig.IPAddress -match "^169\.254\." Add-Result "7-Karta" "Adres IPv4" $(if ($isApipa) {"WARN"} else {"PASS"}) $(if ($isApipa) {"APIPA: $($ipConfig.IPAddress) – brak DHCP lub blad 802.1X!"} else {"IP: $($ipConfig.IPAddress)/$($ipConfig.PrefixLength)"}) } else { Add-Result "7-Karta" "Adres IPv4" "WARN" "Brak adresu IPv4 na adapterze." } Add-Result "7-Karta" "Wlasciwosci zaawansowane 802.1X" "SKIP" "Wymaga uprawnien admina." } } # ================================================================ # TEST 8: WLAN Report – ostatnie proby logowania # ================================================================ function Test-WLANReport { Write-Header "TEST 8: WLAN REPORT – OSTATNIE PROBY LOGOWANIA" Add-Result "8-WLAN-Report" "Generowanie raportu WLAN" "INFO" "Uruchamianie: netsh wlan show wlanreport ..." $reportOutput = netsh wlan show wlanreport 2>&1 if ($LASTEXITCODE -ne 0) { Add-Result "8-WLAN-Report" "WLAN Report" "WARN" "Nie mozna wygenerowac raportu WLAN. Moze wymagac uprawnien admina." return } # Znajdz sciezke do wygenerowanego raportu HTML $reportPath = ($reportOutput | Select-String "([A-Za-z]:\\[^\s]+\.html)" | Select-Object -First 1 | ForEach-Object { $_.Matches[0].Groups[1].Value }) if (-not $reportPath) { $reportPath = "$env:ProgramData\Microsoft\Windows\WlanReport\wlan-report-latest.html" } if (Test-Path $reportPath) { Add-Result "8-WLAN-Report" "Raport WLAN wygenerowany" "PASS" "Plik: $reportPath" $script:WlanReportPath = $reportPath # Parsuj HTML raportu w poszukiwaniu prob polaczen $reportContent = Get-Content $reportPath -Encoding UTF8 -ErrorAction SilentlyContinue if ($reportContent) { # Szukaj linii z eventami polaczenia/rozlaczenia $connectionEvents = $reportContent | Select-String "Success|Failure|Disconnect|Connect|Auth|8021X|EAP|SSID" | Select-Object -First 50 if ($connectionEvents.Count -gt 0) { Add-Result "8-WLAN-Report" "Zdarzenia w raporcie WLAN" "INFO" "Znaleziono $($connectionEvents.Count) zdarzen sieciowych (szczegoly w raporcie HTML)" # Szukaj ostatnich prob logowania 802.1X $authEvents = $reportContent | Select-String "8021X|EAP|Authentication|Auth" | Select-Object -Last 10 $successCount = ($reportContent | Select-String "Success|Succeeded|Successful" | Measure-Object).Count $failCount = ($reportContent | Select-String "Failure|Failed|Error" | Measure-Object).Count Add-Result "8-WLAN-Report" "Udane autentykacje w raporcie" "INFO" "Liczba zdarzen sukcesu: $successCount" Add-Result "8-WLAN-Report" "Nieudane autentykacje w raporcie" $(if ($failCount -gt 0) {"WARN"} else {"PASS"}) "Liczba zdarzen bledu: $failCount" } else { Add-Result "8-WLAN-Report" "Zdarzenia WLAN" "INFO" "Brak zdarzen lub raport jest pusty." } # Data ostatniego raportu $reportFile = Get-Item $reportPath -ErrorAction SilentlyContinue if ($reportFile) { Add-Result "8-WLAN-Report" "Data wygenerowania raportu" "INFO" $reportFile.LastWriteTime.ToString('yyyy-MM-dd HH:mm:ss') } } } else { Add-Result "8-WLAN-Report" "Plik raportu WLAN" "WARN" "Nie znaleziono pliku raportu pod sciezka: $reportPath" } Add-Result "8-WLAN-Report" "Pelny raport WLAN" "INFO" "Otworz w przegladarce: $reportPath (zawiera pelna historie polaczen z wykresami)" } # ================================================================ # MAIN # ================================================================ $WlanReportPath = "" Clear-Host Write-Host "" Write-Host $LINE -ForegroundColor Cyan Write-Host " CERT & 802.1X TEST SUITE v3.0 [NON-ADMIN]" -ForegroundColor White Write-Host " TEAP | User + Computer + CA + LAN + WLAN Report" -ForegroundColor White Write-Host $LINE -ForegroundColor Cyan Write-Host "" Write-Host " Host : $env:COMPUTERNAME" -ForegroundColor White Write-Host " User : $env:USERDOMAIN\$env:USERNAME" -ForegroundColor White Write-Host " Data : $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" -ForegroundColor White Write-Host " SSID : $($Config.ExpectedSSID)" -ForegroundColor White Write-Host " Root CA : $($Config.ExpectedRootCA)" -ForegroundColor White Write-Host " Sub CA : $($Config.ExpectedSubCA)" -ForegroundColor White Write-Host " EAP Type : TEAP ($($Config.ExpectedEAPType))" -ForegroundColor White Write-Host "" Write-Host " [SKIP] = wymaga uprawnien administratora" -ForegroundColor Magenta Write-Host $LINE -ForegroundColor Cyan Test-UserCertificate Test-ComputerCertificate Test-CertificateAuthorities Test-WiFiProfile Test-WiFiConnection Test-LAN8021X Test-NetworkAdapter Test-WLANReport # ================================================================ # PODSUMOWANIE # ================================================================ Write-Host "`n" Write-Host $LINE -ForegroundColor Cyan Write-Host " PODSUMOWANIE TESTOW" -ForegroundColor White Write-Host $LINE -ForegroundColor Cyan Write-Host "" Write-Host " [ OK ] Testy zaliczone : " -NoNewline -ForegroundColor Green; Write-Host $Passed -ForegroundColor Green Write-Host " [FAIL] Testy nieudane : " -NoNewline -ForegroundColor Red; Write-Host $Failed -ForegroundColor Red Write-Host " [WARN] Ostrzezenia : " -NoNewline -ForegroundColor Yellow; Write-Host $Warnings -ForegroundColor Yellow $skipped = ($Results | Where-Object { $_.Status -eq "SKIP" }).Count Write-Host " [SKIP] Pominiete : " -NoNewline -ForegroundColor Magenta; Write-Host $skipped -ForegroundColor Magenta Write-Host "" $failedItems = $Results | Where-Object { $_.Status -eq "FAIL" } if ($failedItems.Count -gt 0) { Write-Host $LINE2 -ForegroundColor Red Write-Host " BLEDY DO NAPRAWIENIA:" -ForegroundColor Red Write-Host $LINE2 -ForegroundColor Red foreach ($item in $failedItems) { Write-Host " [FAIL] [$($item.Kategoria)] $($item.Test)" -ForegroundColor Red if ($item.Szczegoly) { Write-Host " --> $($item.Szczegoly)" -ForegroundColor DarkGray } } Write-Host "" } $warnItems = $Results | Where-Object { $_.Status -eq "WARN" } if ($warnItems.Count -gt 0) { Write-Host $LINE2 -ForegroundColor Yellow Write-Host " OSTRZEZENIA:" -ForegroundColor Yellow Write-Host $LINE2 -ForegroundColor Yellow foreach ($item in $warnItems) { Write-Host " [WARN] [$($item.Kategoria)] $($item.Test)" -ForegroundColor Yellow if ($item.Szczegoly) { Write-Host " --> $($item.Szczegoly)" -ForegroundColor DarkGray } } Write-Host "" } # ================================================================ # EKSPORT HTML # ================================================================ $exportDir = $Config.ExportDir if (-not (Test-Path $exportDir)) { New-Item -ItemType Directory -Path $exportDir -Force | Out-Null; Write-Host " Utworzono folder: $exportDir" -ForegroundColor DarkGray } $timestamp = Get-Date -Format 'yyyyMMdd_HHmmss' $htmlPath = "$exportDir\CertTest_$($env:COMPUTERNAME)_$timestamp.html" $wynikKolor = if ($Failed -gt 0) { "#ef4444" } elseif ($Warnings -gt 0) { "#f59e0b" } else { "#22c55e" } $wynikTekst = if ($Failed -gt 0) { "BLEDY WYKRYTE – $Failed problem(ow) wymaga uwagi!" } elseif ($Warnings -gt 0) { "OSTRZEZENIA – $Warnings ostrzezenie(n) do sprawdzenia." } else { "WSZYSTKIE TESTY ZALICZONE" } $statusKolory = @{ "PASS"="#22c55e"; "FAIL"="#ef4444"; "WARN"="#f59e0b"; "INFO"="#38bdf8"; "SKIP"="#a78bfa" } $rows = "" $lastCat = "" foreach ($r in $Results) { $bg = if ($r.Nr % 2 -eq 0) { "#0f172a" } else { "#111827" } $sc = $statusKolory[$r.Status]; if (!$sc) { $sc = "#94a3b8" } if ($r.Kategoria -ne $lastCat) { $rows += "$($r.Kategoria)" $lastCat = $r.Kategoria } $szcz = [System.Web.HttpUtility]::HtmlEncode($r.Szczegoly) 2>$null if (-not $szcz) { $szcz = $r.Szczegoly -replace '<','<' -replace '>','>' -replace '&','&' } $testEnc = $r.Test -replace '<','<' -replace '>','>' $rows += "$($r.Nr)$($r.Status)$testEnc$szcz$($r.Czas)" } $wlanLink = if ($WlanReportPath -and (Test-Path $WlanReportPath)) { "
📶 WLAN Report: $WlanReportPath
" } else { "" } $skippedCount = ($Results | Where-Object { $_.Status -eq "SKIP" }).Count $html = @" CertTest v3.0 – $env:COMPUTERNAME

⌨ CERT & 802.1X TEST SUITE v3.0 [NON-ADMIN]

Host: $env:COMPUTERNAME  |  User: $env:USERDOMAIN\$env:USERNAME  |  Data: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')
$wynikTekst
$Passed
[ OK ] Zaliczone
$Failed
[FAIL] Nieudane
$Warnings
[WARN] Ostrzezenia
$skippedCount
[SKIP] Pominiete
$wlanLink $rows
NRSTATUSTESTSZCZEGOLYCZAS
Wygenerowano: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')
SSID: $($Config.ExpectedSSID) | Root CA: $($Config.ExpectedRootCA) | Sub CA: $($Config.ExpectedSubCA) | EAP: $(Get-EAPName $Config.ExpectedEAPType) ($($Config.ExpectedEAPType))
"@ [System.IO.File]::WriteAllText($htmlPath, $html, [System.Text.Encoding]::UTF8) Write-Host $LINE -ForegroundColor Cyan if ($Failed -gt 0) { Write-Host " WYNIK: BLEDY WYKRYTE – $Failed problem(ow) wymaga uwagi!" -ForegroundColor Red } elseif ($Warnings -gt 0) { Write-Host " WYNIK: OSTRZEZENIA – $Warnings ostrzezenie(n) do sprawdzenia." -ForegroundColor Yellow } else { Write-Host " WYNIK: WSZYSTKIE TESTY ZALICZONE" -ForegroundColor Green } Write-Host $LINE -ForegroundColor Cyan Write-Host "" Write-Host " Raport HTML : $htmlPath" -ForegroundColor Cyan if ($WlanReportPath -and (Test-Path $WlanReportPath)) { Write-Host " WLAN Report : $WlanReportPath" -ForegroundColor Cyan } Write-Host "" Read-Host " Nacisnij ENTER aby zamknac"