diagnosticsModule/Private/CertificateChecks.ps1
Function Test-CertificateAvailable { param( [Parameter(HelpMessage="Single element of list Generated by Get-AdfsCertificatesToTest")] $certificateAvailable, [string] $certificateType, [bool] $isPrimary = $true, [string] $notRunReason ) $testName = Create-CertCheckName -certType $certificateType -checkName "NotFoundInStore" -isPrimary $isPrimary if (-not $certificateAvailable -and [String]::IsNullOrEmpty($notRunReason)) { $notRunReason = "Certificate object is null." } if (-not [String]::IsNullOrEmpty($notRunReason)) { return Create-CertificateCheckResult -certCheckResult $null -testName $testName -result NotRun -detail $notRunReason } try { $thumbprint = $certificateAvailable.Thumbprint $testResult = New-Object TestResult -ArgumentList($testName) $testResult.Result = [ResultType]::NotRun; $testResult.Output = @{$tpKey = $thumbprint} if ($certificateAvailable.StoreLocation -eq "LocalMachine") { $certStore = New-Object System.Security.Cryptography.X509Certificates.X509Store($certificateAvailable.StoreName,` [System.Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine) try { $certStore.Open("IncludeArchived") $certSearchResult = $certStore.Certificates | where {$_.Thumbprint -eq $thumbprint} if (($certSearchResult | measure).Count -eq 0) { $testResult.Detail = "$certificateType certificate with thumbprint $thumbprint not found in LocalMachine\{0} store.`n" -f $certificateAvailable.StoreName $testResult.Result = [ResultType]::Fail } else { $testResult.Result = [ResultType]::Pass } } catch { $testResult.Result = [ResultType]:: NotRun; $testResult.Detail = "$certificateType certificate with thumbprint $thumbprint encountered exception with message`n" + $_.Exception.Message } finally { $certStore.Close() } } else { $testResult.Result = [ResultType]:: NotRun; $testResult.Detail = "$certificateType certificate with thumbprint $thumbprint not checked for availability because it is in store: " + $certificateAvailable.StoreLocation } return $testResult } catch [Exception] { return Create-NotRunExceptionTestResult $testName $_.Exception.Message } } function Test-CertificateExpired { param ( [System.Security.Cryptography.X509Certificates.X509Certificate2] $certExpired, [string] $certificateType, [bool] $isPrimary = $true, [string] $notRunReason ) $checkName = "Expired" $testName = Create-CertCheckName -certType $certificateType -checkName $checkName -isPrimary $isPrimary if (-not $certExpired -and [String]::IsNullOrEmpty($notRunReason)) { $notRunReason = "Certificate object is null." } if (-not [String]::IsNullOrEmpty($notRunReason)) { return Create-CertificateCheckResult -certCheckResult $null -testName $testName -result NotRun -detail $notRunReason } try { if (Verify-IsCertExpired -isCertExpired $certExpired) { $tp = $certExpired.Thumbprint $certificateExpiredTestDetail = "$certificateType certificate with thumbprint $tp has expired.`n"; $certificateExpiredTestDetail += "Valid From: " + $certExpired.NotBefore.ToString() + "`nValid To: " + $certExpired.NotAfter.ToString(); $certificateExpiredTestDetail += "`nAutoCertificateRollover Enabled: " + (Retrieve-AdfsProperties).AutoCertificateRollover + "`n"; return Create-CertificateCheckResult -certCheckResult $certExpired -testName $testName -result Fail -detail $certificateExpiredTestDetail } else { return Create-CertificateCheckResult -certCheckResult $certExpired -testName $testName -result Pass } } catch [Exception] { return Create-NotRunExceptionTestResult $testName $_.Exception.Message } } function Test-CertificateAboutToExpire { param ( [System.Security.Cryptography.X509Certificates.X509Certificate2] $certAboutToExpire, [string] $certificateType, [bool] $isPrimary = $true, [string] $notRunReason ) $checkName = "AboutToExpire" $testName = Create-CertCheckName -certType $certificateType -checkName $checkName -isPrimary $isPrimary $expiryLimitInDays = 90; if (-not $certAboutToExpire -and [String]::IsNullOrEmpty($notRunReason)) { $notRunReason = "Certificate object is null." } if (-not [String]::IsNullOrEmpty($notRunReason)) { return Create-CertificateCheckResult -certCheckResult $null -testName $testName -result NotRun -detail $notRunReason } try { $properties = Retrieve-AdfsProperties if ($properties.AutoCertificateRollover -and ($certificateType -eq "Token-Decrypting" -or $certificateType -eq "Token-Signing")) { return Create-CertificateCheckResult -certCheckResult $certAboutToExpire -testName $testName -result NotRun -detail "Check Skipped when AutoCertificateRollover is enabled" } $expirtyMinusToday = [System.Convert]::ToInt32(($certAboutToExpire.NotAfter - (Get-Date)).TotalDays); if ($expirtyMinusToday -le $expiryLimitInDays) { $tp = $certAboutToExpire.Thumbprint $certificateAboutToExpireTestDetail = "$certificateType certificate with thumbprint $tp is about to expire in $expirtyMinusToday days.`n" $certificateAboutToExpireTestDetail += "Valid From: " + $certAboutToExpire.NotBefore.ToString() + "`nValid To: " + $certAboutToExpire.NotAfter.ToString(); $certificateAboutToExpireTestDetail += "`nAutoCertificateRollover Enabled: " + (Retrieve-AdfsProperties).AutoCertificateRollover + "`n"; return Create-CertificateCheckResult -certCheckResult $certAboutToExpire -testName $testName -result Fail -detail $certificateAboutToExpireTestDetail } else { return Create-CertificateCheckResult -certCheckResult $certAboutToExpire -testName $testName -result Pass } } catch [Exception] { return Create-NotRunExceptionTestResult $testName $_.Exception.Message } } function Test-CertificateHasPrivateKey { param ( [System.Security.Cryptography.X509Certificates.X509Certificate2] $certHasPrivateKey, [string] $certificateType, [bool] $isPrimary = $true, [string] $storeName, [string] $storeLocation, [string] $notRunReason ) $checkName = "PrivateKeyAbsent" $testName = Create-CertCheckName -certType $certificateType -checkName $checkName -isPrimary $isPrimary if (-not $certHasPrivateKey -and [String]::IsNullOrEmpty($notRunReason)) { $notRunReason = "Certificate object is null." } if (-not [String]::IsNullOrEmpty($notRunReason)) { return Create-CertificateCheckResult -certCheckResult $null -testName $testName -result NotRun -detail $notRunReason } try { $properties = Retrieve-AdfsProperties if ($properties.AutoCertificateRollover -and ($certificateType -eq "Token-Decrypting" -or $certificateType -eq "Token-Signing")) { return Create-CertificateCheckResult -certCheckResult $certHasPrivateKey -testName $testName -result NotRun -detail "Check Skipped when AutoCertificateRollover is enabled" } #special consideration to the corner case where auto certificate rollover was on, then turned off, leaving behind some certificates in the CU\MY store #in which case, we cannot ascertain whether the private key is present or not if ($storeLocation -eq "CurrentUser") { return Create-CertificateCheckResult -certCheckResult $certHasPrivateKey -testName $testName -result NotRun -detail "Check Skipped because the certificate is in the CU\MY store" } if ($certHasPrivateKey.HasPrivateKey) { return Create-CertificateCheckResult -certCheckResult $certHasPrivateKey -testName $testName -result Pass } else { $tp = $certHasPrivateKey.Thumbprint $detail = "$certificateType certificate with thumbprint $tp does not have a private key." return Create-CertificateCheckResult -certCheckResult $certHasPrivateKey -testName $testName -result Fail -detail $detail } } catch [Exception] { return Create-NotRunExceptionTestResult $testName $_.Exception.Message } } function Test-CertificateSelfSigned { param ( [System.Security.Cryptography.X509Certificates.X509Certificate2] $certSelfSigned, [string] $certificateType, [bool] $isPrimary = $false, [string] $notRunReason ) $checkName = "IsSelfSigned" $testName = Create-CertCheckName -certType $certificateType -checkName $checkName -isPrimary $isPrimary if (-not $certSelfSigned -and [String]::IsNullOrEmpty($notRunReason)) { $notRunReason = "Certificate object is null." } if (-not [String]::IsNullOrEmpty($notRunReason)) { return Create-CertificateCheckResult -certCheckResult $null -testName $testName -result NotRun -detail $notRunReason } try { $properties = Retrieve-AdfsProperties if ($properties.AutoCertificateRollover -and ($certificateType -eq "Token-Decrypting" -or $certificateType -eq "Token-Signing")) { return Create-CertificateCheckResult -certCheckResult $certSelfSigned -testName $testName -result NotRun -detail "Check Skipped when AutoCertificateRollover is enabled" } if (Verify-IsCertSelfSigned $certSelfSigned) { $tp = $certSelfSigned.Thumbprint $detail = "$certificateType certificate with thumbprint $tp is self-signed." return Create-CertificateCheckResult -certCheckResult $certSelfSigned -testName $testName -result Fail -detail $detail } else { return Create-CertificateCheckResult -certCheckResult $certSelfSigned -testName $testName -result Pass } } catch [Exception] { return Create-NotRunExceptionTestResult $testName $_.Exception.Message } } function Test-CertificateCRL { param ( [System.Security.Cryptography.X509Certificates.X509Certificate2] $certCrl, [string] $certificateType, [bool] $isPrimary = $false, [string] $notRunReason ) $checkName = "Revoked" $chainStatusKey = "ChainStatus" $testName = Create-CertCheckName -certType $certificateType -checkName $checkName -isPrimary $isPrimary if (-not $certCrl -and [String]::IsNullOrEmpty($notRunReason)) { $notRunReason = "Certificate object is null." } if (-not [String]::IsNullOrEmpty($notRunReason)) { return Create-CertificateCheckResult -certCheckResult $null -testName $testName -result NotRun -detail $notRunReason } try { $crlResult = VerifyCertificateCRL -certCrl $certCrl $passFail = [ResultType]::Pass if (($crlResult.ChainBuildResult -eq $false) -and ($crlResult.IsSelfSigned -eq $false)) { $passFail = [ResultType]::Fail } $testResult = Create-CertificateCheckResult -certCheckResult $certCrl -testName $testName -result $passFail $testDetail = "Thumbprint: " + $crlResult.Thumbprint + "`n" $testResult.Output.Add($chainStatusKey, "NONE") if ($crlResult.ChainStatus) { $testResult.Output.Set_Item($chainStatusKey, $crlResult.ChainStatus) foreach($chainStatus in $crlResult.ChainStatus) { $testDetail = $testDetail + $chainStatus.Status + "-" + $chainStatus.StatusInformation + [System.Environment]::NewLine } } $testResult.Detail = $testDetail return $testResult } catch [Exception] { return Create-NotRunExceptionTestResult $testName $_.Exception.Message } } |