Sync all scripts from website downloads — 352 scripts total
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.
This commit is contained in:
@@ -0,0 +1,651 @@
|
||||
###############################################################################
|
||||
#### 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 }
|
||||
Reference in New Issue
Block a user