a1a17e81a1
Includes updated JS challenge scripts with Claude-User whitelist, same-site referer bypass, Blackbox-Exporter allowed bot, and all new exporters, cheat sheets, and automation scripts.
652 lines
24 KiB
PowerShell
652 lines
24 KiB
PowerShell
###############################################################################
|
|
#### windows-pki-smoke-tests.ps1 — Verify Windows PKI infrastructure ####
|
|
#### Checks CA service, certificates, CRL, OCSP, templates, ####
|
|
#### auto-enrollment, pending requests, AIA/CDP extensions. ####
|
|
#### ####
|
|
#### Author: Phil Connor ####
|
|
#### Contact: contact@mylinux.work ####
|
|
#### License: MIT ####
|
|
#### Version: 1.0 ####
|
|
#### ####
|
|
#### Usage: .\windows-pki-smoke-tests.ps1 ####
|
|
#### .\windows-pki-smoke-tests.ps1 -CAServer CA01 ####
|
|
#### .\windows-pki-smoke-tests.ps1 -OutputFormat tap ####
|
|
#### ####
|
|
#### See -Help for all options. ####
|
|
###############################################################################
|
|
|
|
[CmdletBinding()]
|
|
param(
|
|
[string]$CAName = "",
|
|
[string]$CAServer = "",
|
|
[int]$CRLThresholdHours = 24,
|
|
[int]$PendingThreshold = 10,
|
|
[ValidateSet("text","tap")]
|
|
[string]$OutputFormat = "text",
|
|
[switch]$NoColor,
|
|
[switch]$Help
|
|
)
|
|
|
|
$ErrorActionPreference = "Continue"
|
|
|
|
# ============================================================================
|
|
# HELP
|
|
# ============================================================================
|
|
|
|
if ($Help) {
|
|
@"
|
|
Usage: .\windows-pki-smoke-tests.ps1 [OPTIONS]
|
|
|
|
Smoke-test Windows PKI infrastructure. PowerShell 5.1+.
|
|
Designed for domain-joined Windows machines with AD CS.
|
|
|
|
Parameters:
|
|
-CAName NAME CA common name (default: auto-detect via certutil)
|
|
-CAServer SERVER CA server hostname or IP (default: auto-detect via certutil)
|
|
-CRLThresholdHours N Warn if CRL expires within N hours (default: 24)
|
|
-PendingThreshold N Warn if pending requests exceed N (default: 10)
|
|
-OutputFormat FORMAT Output: text (default), tap
|
|
-NoColor Disable coloured output
|
|
-Verbose Show debug output
|
|
-Help Show this help
|
|
|
|
Examples:
|
|
.\windows-pki-smoke-tests.ps1
|
|
.\windows-pki-smoke-tests.ps1 -CAServer CA01.corp.local
|
|
.\windows-pki-smoke-tests.ps1 -CAName "corp-CA01-CA" -CAServer CA01
|
|
.\windows-pki-smoke-tests.ps1 -CRLThresholdHours 48 -OutputFormat tap
|
|
.\windows-pki-smoke-tests.ps1 -NoColor -Verbose
|
|
"@
|
|
exit 0
|
|
}
|
|
|
|
# ============================================================================
|
|
# STATE
|
|
# ============================================================================
|
|
|
|
$script:Pass = 0
|
|
$script:Fail = 0
|
|
$script:Skip = 0
|
|
$script:Total = 0
|
|
$script:Results = @()
|
|
$script:StartTime = Get-Date
|
|
|
|
# ============================================================================
|
|
# COLORS
|
|
# ============================================================================
|
|
|
|
function Write-Color {
|
|
param([string]$Text, [string]$Color = "White")
|
|
if ($NoColor) {
|
|
Write-Host $Text
|
|
} else {
|
|
Write-Host $Text -ForegroundColor $Color
|
|
}
|
|
}
|
|
|
|
function Write-Log { param([string]$Msg) Write-Color "[INFO] $Msg" "Cyan" }
|
|
function Write-Warn { param([string]$Msg) Write-Color "[WARN] $Msg" "Yellow" }
|
|
function Write-Err { param([string]$Msg) Write-Color "[ERROR] $Msg" "Red" }
|
|
|
|
# ============================================================================
|
|
# TEST RESULT RECORDING
|
|
# ============================================================================
|
|
|
|
function Record-Pass {
|
|
param([string]$Name, [string]$Detail = "")
|
|
$script:Pass++
|
|
$script:Total++
|
|
$script:Results += [PSCustomObject]@{ Status="PASS"; Name=$Name; Detail=$Detail }
|
|
if ($OutputFormat -eq "tap") {
|
|
Write-Host "ok $($script:Total) - $Name$(if($Detail){" ($Detail)"})"
|
|
} else {
|
|
$mark = if ($NoColor) { "[PASS]" } else { [char]0x2713 }
|
|
$msg = " $mark $Name"
|
|
if ($Detail) { $msg += " - $Detail" }
|
|
Write-Color $msg "Green"
|
|
}
|
|
}
|
|
|
|
function Record-Fail {
|
|
param([string]$Name, [string]$Detail = "")
|
|
$script:Fail++
|
|
$script:Total++
|
|
$script:Results += [PSCustomObject]@{ Status="FAIL"; Name=$Name; Detail=$Detail }
|
|
if ($OutputFormat -eq "tap") {
|
|
Write-Host "not ok $($script:Total) - $Name"
|
|
if ($Detail) { Write-Host " # $Detail" }
|
|
} else {
|
|
$mark = if ($NoColor) { "[FAIL]" } else { [char]0x2717 }
|
|
$msg = " $mark $Name"
|
|
if ($Detail) { $msg += " - $Detail" }
|
|
Write-Color $msg "Red"
|
|
}
|
|
}
|
|
|
|
function Record-Skip {
|
|
param([string]$Name, [string]$Reason = "")
|
|
$script:Skip++
|
|
$script:Total++
|
|
$script:Results += [PSCustomObject]@{ Status="SKIP"; Name=$Name; Detail=$Reason }
|
|
if ($OutputFormat -eq "tap") {
|
|
Write-Host "ok $($script:Total) - $Name # SKIP $Reason"
|
|
} else {
|
|
$mark = if ($NoColor) { "[SKIP]" } else { [char]0x2298 }
|
|
$msg = " $mark $Name"
|
|
if ($Reason) { $msg += " - $Reason" }
|
|
Write-Color $msg "Yellow"
|
|
}
|
|
}
|
|
|
|
# ============================================================================
|
|
# HELPERS
|
|
# ============================================================================
|
|
|
|
function Test-CommandExists {
|
|
param([string]$Command)
|
|
$null -ne (Get-Command $Command -ErrorAction SilentlyContinue)
|
|
}
|
|
|
|
function Write-Section {
|
|
param([string]$Name)
|
|
if ($OutputFormat -eq "text") {
|
|
Write-Host ""
|
|
Write-Color $Name "White"
|
|
}
|
|
}
|
|
|
|
# ============================================================================
|
|
# AUTO-DETECTION
|
|
# ============================================================================
|
|
|
|
function Resolve-CAServer {
|
|
if ($CAServer) {
|
|
Write-Verbose "Using specified CA server: $CAServer"
|
|
return $CAServer
|
|
}
|
|
if (-not (Test-CommandExists "certutil")) {
|
|
Write-Err "certutil not available. Use -CAServer parameter."
|
|
exit 1
|
|
}
|
|
try {
|
|
$output = certutil -config - -ping 2>&1 | Out-String
|
|
if ($output -match "server\s*[`"``]([^`"``]+)[`"``]") {
|
|
Write-Verbose "Auto-detected CA server: $($Matches[1].Trim())"
|
|
return $Matches[1].Trim()
|
|
}
|
|
} catch {}
|
|
try {
|
|
$output = certutil 2>&1 | Out-String
|
|
if ($output -match "Config:\s*`"?([^\\`"]+)\\") {
|
|
Write-Verbose "Auto-detected CA server from certutil: $($Matches[1].Trim())"
|
|
return $Matches[1].Trim()
|
|
}
|
|
} catch {}
|
|
Write-Err "Cannot auto-detect CA server. Use -CAServer parameter."
|
|
exit 1
|
|
}
|
|
|
|
function Resolve-CAName {
|
|
if ($CAName) {
|
|
Write-Verbose "Using specified CA name: $CAName"
|
|
return $CAName
|
|
}
|
|
if (-not (Test-CommandExists "certutil")) {
|
|
Write-Err "certutil not available. Use -CAName parameter."
|
|
exit 1
|
|
}
|
|
try {
|
|
$output = certutil 2>&1 | Out-String
|
|
if ($output -match "Name:\s*[`"``]?([^`"``\r\n]+)[`"``]?") {
|
|
Write-Verbose "Auto-detected CA name: $($Matches[1].Trim())"
|
|
return $Matches[1].Trim()
|
|
}
|
|
} catch {}
|
|
try {
|
|
$output = certutil -config - -ping 2>&1 | Out-String
|
|
if ($output -match "CA\s*[`"``]([^`"``]+)[`"``]") {
|
|
Write-Verbose "Auto-detected CA name from config: $($Matches[1].Trim())"
|
|
return $Matches[1].Trim()
|
|
}
|
|
} catch {}
|
|
Write-Err "Cannot auto-detect CA name. Use -CAName parameter."
|
|
exit 1
|
|
}
|
|
|
|
# ============================================================================
|
|
# TESTS
|
|
# ============================================================================
|
|
|
|
# -- 1. CA Service -----------------------------------------------------------
|
|
|
|
function Test-CAService {
|
|
Write-Section "CA Service"
|
|
|
|
try {
|
|
$svc = Get-Service -Name "CertSvc" -ComputerName $script:CAServerName -ErrorAction Stop
|
|
if ($svc.Status -eq "Running") {
|
|
Record-Pass "CA service status" "CertSvc running on $($script:CAServerName)"
|
|
} else {
|
|
Record-Fail "CA service status" "CertSvc is $($svc.Status) on $($script:CAServerName)"
|
|
}
|
|
} catch {
|
|
try {
|
|
$svc = Get-Service -Name "CertSvc" -ErrorAction Stop
|
|
if ($svc.Status -eq "Running") {
|
|
Record-Pass "CA service status" "CertSvc running (local)"
|
|
} else {
|
|
Record-Fail "CA service status" "CertSvc is $($svc.Status)"
|
|
}
|
|
} catch {
|
|
Record-Fail "CA service status" "cannot query CertSvc - $($_.Exception.Message)"
|
|
}
|
|
}
|
|
}
|
|
|
|
# -- 2. CA Certificate Validity ---------------------------------------------
|
|
|
|
function Test-CACertificate {
|
|
Write-Section "CA Certificate"
|
|
if (-not (Test-CommandExists "certutil")) {
|
|
Record-Skip "CA certificate validity" "certutil not available"
|
|
return
|
|
}
|
|
|
|
try {
|
|
$configString = "$($script:CAServerName)\$($script:CACommonName)"
|
|
$output = certutil -config $configString -ca.cert 2>&1 | Out-String
|
|
|
|
if (-not ($output -match "NotAfter:\s*(.+)")) {
|
|
$output = certutil -ca.cert 2>&1 | Out-String
|
|
}
|
|
|
|
if ($output -match "NotAfter:\s*(.+)") {
|
|
$notAfter = [DateTime]::Parse($Matches[1].Trim())
|
|
$daysLeft = ($notAfter - (Get-Date)).Days
|
|
$expiryStr = $notAfter.ToString("yyyy-MM-dd")
|
|
|
|
if ($daysLeft -lt 0) {
|
|
Record-Fail "CA certificate validity" "CA certificate expired on $expiryStr"
|
|
} elseif ($daysLeft -le 30) {
|
|
Record-Fail "CA certificate validity" "CA certificate expires in $daysLeft days ($expiryStr)"
|
|
} else {
|
|
Record-Pass "CA certificate validity" "expires $expiryStr ($daysLeft days remaining)"
|
|
}
|
|
} else {
|
|
Record-Fail "CA certificate validity" "could not determine CA certificate expiry"
|
|
}
|
|
} catch {
|
|
Record-Fail "CA certificate validity" "certutil error - $($_.Exception.Message)"
|
|
}
|
|
}
|
|
|
|
# -- 3. CRL Publication ------------------------------------------------------
|
|
|
|
function Test-CRLPublication {
|
|
Write-Section "CRL"
|
|
if (-not (Test-CommandExists "certutil")) {
|
|
Record-Skip "CRL publication" "certutil not available"
|
|
return
|
|
}
|
|
|
|
try {
|
|
$configString = "$($script:CAServerName)\$($script:CACommonName)"
|
|
$output = certutil -config $configString -crl 2>&1 | Out-String
|
|
|
|
if ($output -match "CRL published" -or $output -match "command completed successfully") {
|
|
$crlOutput = certutil -config $configString -getcrl 2>&1 | Out-String
|
|
if (-not ($crlOutput -match "Next Update:\s*(.+)")) {
|
|
$crlOutput = certutil -getcrl 2>&1 | Out-String
|
|
}
|
|
|
|
if ($crlOutput -match "Next Update:\s*(.+)") {
|
|
$nextUpdate = [DateTime]::Parse($Matches[1].Trim())
|
|
$hoursLeft = ($nextUpdate - (Get-Date)).TotalHours
|
|
$hoursStr = [math]::Floor($hoursLeft)
|
|
|
|
if ($hoursLeft -lt 0) {
|
|
Record-Fail "CRL publication" "CRL has expired (next update was $($nextUpdate.ToString('yyyy-MM-dd HH:mm')))"
|
|
} elseif ($hoursLeft -le $CRLThresholdHours) {
|
|
Record-Fail "CRL publication" "CRL expires in ${hoursStr}h (threshold: ${CRLThresholdHours}h)"
|
|
} else {
|
|
Record-Pass "CRL publication" "next update in ${hoursStr}h"
|
|
}
|
|
} else {
|
|
Record-Pass "CRL publication" "CRL published successfully"
|
|
}
|
|
} elseif ($output -match "error|fail") {
|
|
Record-Fail "CRL publication" "certutil -crl reported an error"
|
|
} else {
|
|
Record-Fail "CRL publication" "could not verify CRL publication"
|
|
}
|
|
} catch {
|
|
Record-Fail "CRL publication" "certutil error - $($_.Exception.Message)"
|
|
}
|
|
}
|
|
|
|
# -- 4. OCSP Responder ------------------------------------------------------
|
|
|
|
function Test-OCSPResponder {
|
|
Write-Section "OCSP"
|
|
if (-not (Test-CommandExists "certutil")) {
|
|
Record-Skip "OCSP responder" "certutil not available"
|
|
return
|
|
}
|
|
|
|
try {
|
|
$configString = "$($script:CAServerName)\$($script:CACommonName)"
|
|
$output = certutil -config $configString -ca.cert 2>&1 | Out-String
|
|
|
|
if (-not ($output -match "URL=(\S*ocsp\S*)")) {
|
|
$output = certutil -ca.cert 2>&1 | Out-String
|
|
}
|
|
|
|
if ($output -match "URL=(\S*ocsp\S*)") {
|
|
$ocspUrl = $Matches[1].Trim()
|
|
Write-Verbose "Testing OCSP URL: $ocspUrl"
|
|
|
|
try {
|
|
$response = Invoke-WebRequest -Uri $ocspUrl -Method GET -UseBasicParsing -TimeoutSec 10 -ErrorAction Stop
|
|
if ($response.StatusCode -ge 200 -and $response.StatusCode -lt 400) {
|
|
Record-Pass "OCSP responder" $ocspUrl
|
|
} else {
|
|
Record-Fail "OCSP responder" "$ocspUrl - HTTP $($response.StatusCode)"
|
|
}
|
|
} catch {
|
|
$statusCode = if ($_.Exception.Response) { [int]$_.Exception.Response.StatusCode } else { $null }
|
|
if ($statusCode -and $statusCode -lt 500) {
|
|
Record-Pass "OCSP responder" "$ocspUrl (HTTP $statusCode)"
|
|
} else {
|
|
Record-Fail "OCSP responder" "$ocspUrl - $($_.Exception.Message)"
|
|
}
|
|
}
|
|
} else {
|
|
Record-Skip "OCSP responder" "OCSP URL not configured in CA certificate"
|
|
}
|
|
} catch {
|
|
Record-Fail "OCSP responder" "error - $($_.Exception.Message)"
|
|
}
|
|
}
|
|
|
|
# -- 5. Certificate Templates -----------------------------------------------
|
|
|
|
function Test-CertificateTemplates {
|
|
Write-Section "Templates"
|
|
if (-not (Test-CommandExists "certutil")) {
|
|
Record-Skip "Certificate templates" "certutil not available"
|
|
return
|
|
}
|
|
|
|
try {
|
|
$configString = "$($script:CAServerName)\$($script:CACommonName)"
|
|
$output = certutil -config $configString -catemplates 2>&1 | Out-String
|
|
|
|
if ($output -match "error|fail" -and $output -notmatch "command completed") {
|
|
$output = certutil -catemplates 2>&1 | Out-String
|
|
}
|
|
|
|
if ($output -match "command completed successfully" -or $output -match ":") {
|
|
$templateLines = ($output -split "`n") | Where-Object {
|
|
$_ -match ":" -and
|
|
$_ -notmatch "command completed" -and
|
|
$_ -notmatch "CertUtil" -and
|
|
$_ -notmatch "^\s*$"
|
|
}
|
|
$templateCount = ($templateLines | Measure-Object).Count
|
|
|
|
if ($templateCount -gt 0) {
|
|
Record-Pass "Certificate templates" "$templateCount template(s) published"
|
|
} else {
|
|
Record-Fail "Certificate templates" "no templates found"
|
|
}
|
|
} else {
|
|
Record-Fail "Certificate templates" "certutil -catemplates failed"
|
|
}
|
|
} catch {
|
|
Record-Fail "Certificate templates" "certutil error - $($_.Exception.Message)"
|
|
}
|
|
}
|
|
|
|
# -- 6. Auto-Enrollment ------------------------------------------------------
|
|
|
|
function Test-AutoEnrollment {
|
|
Write-Section "Auto-Enrollment"
|
|
try {
|
|
$regPath = "HKLM:\SOFTWARE\Policies\Microsoft\Cryptography\AutoEnrollment"
|
|
|
|
if (-not (Test-Path $regPath)) {
|
|
Record-Skip "Auto-enrollment configured" "registry key not found (GPO may not be applied)"
|
|
return
|
|
}
|
|
|
|
$flags = (Get-ItemProperty -Path $regPath -Name "AEPolicy" -ErrorAction SilentlyContinue).AEPolicy
|
|
|
|
if ($null -eq $flags) {
|
|
Record-Skip "Auto-enrollment configured" "AEPolicy value not set"
|
|
return
|
|
}
|
|
|
|
# AEPolicy flags: 1 = enroll, 2 = update, 4 = renew expired
|
|
if ($flags -band 1) {
|
|
$features = @()
|
|
if ($flags -band 1) { $features += "enroll" }
|
|
if ($flags -band 2) { $features += "update" }
|
|
if ($flags -band 4) { $features += "renew expired" }
|
|
$featureStr = $features -join ", "
|
|
Record-Pass "Auto-enrollment configured" "enabled ($featureStr)"
|
|
} else {
|
|
Record-Fail "Auto-enrollment configured" "AEPolicy is $flags (enrollment not enabled)"
|
|
}
|
|
} catch {
|
|
Record-Fail "Auto-enrollment configured" "registry error - $($_.Exception.Message)"
|
|
}
|
|
}
|
|
|
|
# -- 7. Pending Requests ----------------------------------------------------
|
|
|
|
function Test-PendingRequests {
|
|
Write-Section "Pending Requests"
|
|
if (-not (Test-CommandExists "certutil")) {
|
|
Record-Skip "Pending requests" "certutil not available"
|
|
return
|
|
}
|
|
|
|
try {
|
|
$configString = "$($script:CAServerName)\$($script:CACommonName)"
|
|
$output = certutil -config $configString -view -restrict "disposition=9" -out "requestid" 2>&1 | Out-String
|
|
|
|
$pendingCount = 0
|
|
if ($output -match "(\d+) Row\(s\)") {
|
|
$pendingCount = [int]$Matches[1]
|
|
} elseif ($output -match "0 Rows") {
|
|
$pendingCount = 0
|
|
}
|
|
|
|
if ($pendingCount -gt $PendingThreshold) {
|
|
Record-Fail "Pending requests" "$pendingCount pending (threshold: $PendingThreshold)"
|
|
} else {
|
|
Record-Pass "Pending requests" "$pendingCount pending (threshold: $PendingThreshold)"
|
|
}
|
|
} catch {
|
|
Record-Fail "Pending requests" "certutil error - $($_.Exception.Message)"
|
|
}
|
|
}
|
|
|
|
# -- 8. AIA Extension -------------------------------------------------------
|
|
|
|
function Test-AIAExtension {
|
|
Write-Section "Extensions"
|
|
if (-not (Test-CommandExists "certutil")) {
|
|
Record-Skip "AIA extension configured" "certutil not available"
|
|
return
|
|
}
|
|
|
|
try {
|
|
$configString = "$($script:CAServerName)\$($script:CACommonName)"
|
|
$output = certutil -config $configString -ca.cert 2>&1 | Out-String
|
|
if (-not ($output -match "Authority Information Access")) {
|
|
$output = certutil -ca.cert 2>&1 | Out-String
|
|
}
|
|
|
|
if ($output -match "Authority Information Access") {
|
|
$urlCount = ([regex]::Matches($output, "URL=\S+")).Count
|
|
if ($urlCount -gt 0) {
|
|
Record-Pass "AIA extension configured" "$urlCount URL(s) configured"
|
|
} else {
|
|
Record-Pass "AIA extension configured" "AIA extension present"
|
|
}
|
|
} else {
|
|
Record-Fail "AIA extension configured" "AIA extension not found in CA certificate"
|
|
}
|
|
} catch {
|
|
Record-Fail "AIA extension configured" "certutil error - $($_.Exception.Message)"
|
|
}
|
|
}
|
|
|
|
# -- 9. CDP Extension -------------------------------------------------------
|
|
|
|
function Test-CDPExtension {
|
|
if (-not (Test-CommandExists "certutil")) {
|
|
Record-Skip "CDP extension configured" "certutil not available"
|
|
return
|
|
}
|
|
|
|
try {
|
|
$configString = "$($script:CAServerName)\$($script:CACommonName)"
|
|
$output = certutil -config $configString -ca.cert 2>&1 | Out-String
|
|
if (-not ($output -match "CRL Distribution Point")) {
|
|
$output = certutil -ca.cert 2>&1 | Out-String
|
|
}
|
|
|
|
if ($output -match "CRL Distribution Point") {
|
|
$urlCount = ([regex]::Matches($output, "URL=\S+")).Count
|
|
if ($urlCount -gt 0) {
|
|
Record-Pass "CDP extension configured" "$urlCount URL(s) configured"
|
|
} else {
|
|
Record-Pass "CDP extension configured" "CDP extension present"
|
|
}
|
|
} else {
|
|
Record-Fail "CDP extension configured" "CDP extension not found in CA certificate"
|
|
}
|
|
} catch {
|
|
Record-Fail "CDP extension configured" "certutil error - $($_.Exception.Message)"
|
|
}
|
|
}
|
|
|
|
# -- 10. Enterprise CA Registration -----------------------------------------
|
|
|
|
function Test-EnterpriseCARegistration {
|
|
Write-Section "AD Registration"
|
|
if (-not (Test-CommandExists "certutil")) {
|
|
Record-Skip "Enterprise CA registration" "certutil not available"
|
|
return
|
|
}
|
|
|
|
try {
|
|
$output = certutil -dcsinfo 2>&1 | Out-String
|
|
if ($output -match $script:CACommonName -or $output -match "Enrollment Services") {
|
|
Record-Pass "Enterprise CA registration" "CA registered in AD"
|
|
return
|
|
}
|
|
} catch { Write-Verbose "certutil -dcsinfo failed: $($_.Exception.Message)" }
|
|
|
|
try {
|
|
$output = certutil -config "$($script:CAServerName)\$($script:CACommonName)" -ping 2>&1 | Out-String
|
|
if ($output -match "interface is alive" -or $output -match "command completed successfully") {
|
|
Record-Pass "Enterprise CA registration" "CA reachable and responsive"
|
|
return
|
|
}
|
|
} catch { Write-Verbose "certutil -ping failed: $($_.Exception.Message)" }
|
|
|
|
try {
|
|
$rootDSE = [ADSI]"LDAP://RootDSE"
|
|
$configNC = $rootDSE.configurationNamingContext
|
|
$enrollDN = "LDAP://CN=Enrollment Services,CN=Public Key Services,CN=Services,$configNC"
|
|
$enrollContainer = [ADSI]$enrollDN
|
|
|
|
$found = $false
|
|
foreach ($child in $enrollContainer.Children) {
|
|
if ($child.cn -eq $script:CACommonName -or $child.cn -match $script:CACommonName) {
|
|
$found = $true
|
|
break
|
|
}
|
|
}
|
|
|
|
if ($found) {
|
|
Record-Pass "Enterprise CA registration" "CA found in AD Enrollment Services"
|
|
} else {
|
|
Record-Fail "Enterprise CA registration" "CA not found in AD Enrollment Services"
|
|
}
|
|
} catch {
|
|
Record-Fail "Enterprise CA registration" "cannot verify AD registration - $($_.Exception.Message)"
|
|
}
|
|
}
|
|
|
|
# ============================================================================
|
|
# OUTPUT
|
|
# ============================================================================
|
|
|
|
function Write-Header {
|
|
if ($OutputFormat -eq "tap") {
|
|
Write-Host "TAP version 13"
|
|
} else {
|
|
Write-Host ""
|
|
Write-Color "Windows PKI Smoke Tests" "White"
|
|
Write-Host "CA Server: $($script:CAServerName)"
|
|
Write-Host "CA Name: $($script:CACommonName)"
|
|
Write-Host "Time: $(Get-Date -Format 'yyyy-MM-ddTHH:mm:ssZ')"
|
|
}
|
|
}
|
|
|
|
function Write-Summary {
|
|
$duration = [math]::Floor(((Get-Date) - $script:StartTime).TotalSeconds)
|
|
|
|
if ($OutputFormat -eq "tap") {
|
|
Write-Host "1..$($script:Total)"
|
|
Write-Host "# pass $($script:Pass)"
|
|
Write-Host "# fail $($script:Fail)"
|
|
Write-Host "# skip $($script:Skip)"
|
|
} else {
|
|
Write-Host ""
|
|
$separator = [string]::new([char]0x2500, 40)
|
|
Write-Color $separator "White"
|
|
Write-Color "Summary $($script:CAServerName)\$($script:CACommonName)" "White"
|
|
|
|
$summaryLine = " $($script:Pass) passed $($script:Fail) failed $($script:Skip) skipped (${duration}s)"
|
|
Write-Host $summaryLine
|
|
Write-Color $separator "White"
|
|
|
|
if ($script:Fail -eq 0) {
|
|
Write-Color "All tests passed." "Green"
|
|
} else {
|
|
Write-Color "$($script:Fail) test(s) failed." "Red"
|
|
}
|
|
}
|
|
}
|
|
|
|
# ============================================================================
|
|
# MAIN
|
|
# ============================================================================
|
|
|
|
# Resolve targets
|
|
$script:CAServerName = Resolve-CAServer
|
|
$script:CACommonName = Resolve-CAName
|
|
|
|
Write-Header
|
|
|
|
# Run all tests
|
|
Test-CAService
|
|
Test-CACertificate
|
|
Test-CRLPublication
|
|
Test-OCSPResponder
|
|
Test-CertificateTemplates
|
|
Test-AutoEnrollment
|
|
Test-PendingRequests
|
|
Test-AIAExtension
|
|
Test-CDPExtension
|
|
Test-EnterpriseCARegistration
|
|
|
|
Write-Summary
|
|
|
|
if ($script:Fail -eq 0) { exit 0 } else { exit 1 }
|