
The purpose of this script is to automate your certificate revocation on a Microsoft PKI. The script uses the powershell module PSPKI. To install it, run the following command :
PS> Install-Module -Name PSPKI
This module is intended to simplify various PKI and Active Directory Certificate Services management tasks by using automation with Windows PowerShell.
This module is intended for Certification Authority management. For local certificate store management you should consider to use Quest AD PKI cmdlets.
The script will revoke your certificate using the “Hold” reason. In that case, you will be able to unrevoke the certificate you want. The two following reasons will trigger a certificate revocation:
- The certificate is expired
- The Certificate is in duplicate (same common name): the most recent is kept
import-module PSPKI
# list CA
$CAlist = Get-CertificationAuthority
Write-Host "The following CA have been found:"
$CAlist
write-host ""
$issuedcerts_arr = @()
# list expired certificates
$CAlist | % {
	$CAName = $_.DisplayName
	write-host "Listing all issued certificates for $CAName..."
	$issuedcerts_arr += Get-CertificationAuthority -name $CAName | Get-IssuedRequest | select *,@{n='IssuingCAName';e={$CAName}}
}
$expiredCerts = $issuedcerts_arr | ? { $_.NotAfter -lt (get-date) }
$duplicateValidCerts = @()
$RevokeCerts = @()
$NoNewCerts_ManualCheckRequired = @()
$expiredCerts | % {
	$ExpiredCert = $_
	$ExpiredcertCN = $_.CommonName
	$ExpiredcertDate = $_.NotAfter
	$validCertFoundTag = 0
	$ValidCert = @($issuedcerts_arr | ?{$_.CommonName -eq $ExpiredcertCN -and $_.NotAfter -gt (Get-Date)})
	if ($ValidCert.count -eq 1) {
		write-host "Revoking the certificate for $ExpiredcertCN that expires on $ExpiredcertDate (valid cert : "$ValidCert.RequestID" / "$ValidCert.NotAfter" / "$ValidCert.ConfigString")" -ForegroundColor DarkCyan
		$RevokeCerts += $ExpiredCert
		$ExpRequestID = $ExpiredCert.RequestID
		$ExpRequestCA = $ExpiredCert.IssuingCAName
		Get-CertificationAuthority -name $ExpRequestCA | Get-IssuedRequest -filter "RequestID -eq $ExpRequestID" | Revoke-Certificate -Reason "Hold"
	}
	elseif ($ValidCert.count -gt 1) {
		write-host "Revoking the expired certificate ($ExpiredcertCN valid to $ExpiredcertDate). However, please check the following certificates. More than one valid certificate has been found for the same CommonName" -ForegroundColor Yellow
		$duplicateValidCerts += $ValidCert
		$RevokeCerts += $ExpiredCert
		$ExpRequestID = $ExpiredCert.RequestID
		$ExpRequestCA = $ExpiredCert.IssuingCAName
		Get-CertificationAuthority -name $ExpRequestCA | Get-IssuedRequest -filter "RequestID -eq $ExpRequestID" | Revoke-Certificate -Reason "Hold"
	}
	else {
		write-host "No new valid cert exits for $ExpiredcertCN (expires on $ExpiredcertDate)" -ForegroundColor Magenta
		$ValidCert
		$NoNewCerts_ManualCheckRequired += $ExpiredCert
		$ExpRequestID = $ExpiredCert.RequestID
		$ExpRequestCA = $ExpiredCert.IssuingCAName
		Get-CertificationAuthority -name $ExpRequestCA | Get-IssuedRequest -filter "RequestID -eq $ExpRequestID" | Revoke-Certificate -Reason "Hold"
	}
}
#check valid duplicated certificates
$ValidCertificates_arr = @($issuedcerts_arr | ?{$_.NotAfter -gt (Get-Date)})
$ValidCertificatesCN_arr = $ValidCertificates_arr.CommonName | ? { $_ -notmatch "Administrator" } | select -Unique
$ValidCertificatesCN_arr | % {
	$ValidCertCN = $_
	@($issuedcerts_arr | ?{$_.CommonName -eq $ValidCertCN -and $_.NotAfter -gt (Get-Date)}).CertificateTemplate | select -unique | % {
		$DuplValidCertTempl = $_
		$DuplValidCert = @($issuedcerts_arr | ?{$_.CommonName -eq $ValidCertCN -and $_.NotAfter -gt (Get-Date) -and $_.CertificateTemplate -eq $DuplValidCertTempl})
		if ($DuplValidCert.count -gt 1) {
			write-host "Duplicate valid certs have been found for the CommonName : $ValidCertCN" -ForegroundColor Yellow
			$DuplValidCert_sorted = $DuplValidCert | Sort-Object -Descending NotAfter
			for ($i=0; $i -lt $DuplValidCert_sorted.Length; $i++){
				$reqid = ($DuplValidCert_sorted[$i]).RequestID
				$certempl = ($DuplValidCert_sorted[$i]).CertificateTemplate
				$issuingcaname = ($DuplValidCert_sorted[$i]).IssuingCAName
				$expdate = ($DuplValidCert_sorted[$i]).NotAfter
				if ($i -eq 0) {
					write-host "`t KEEP: RequestID: $reqid / Expires on: $expdate / CA: $issuingcaname / Cert Template: $certempl" -ForegroundColor Green
				}
				else {
					write-host "`t REVOKE: RequestID: $reqid / Expires on: $expdate / CA: $issuingcaname / Cert Template: $certempl" -ForegroundColor Magenta
					Get-CertificationAuthority -name $issuingcaname | Get-IssuedRequest -filter "RequestID -eq $reqid" | Revoke-Certificate -Reason "Hold"
				}
			}
		}
	}
}
# Create revocation reports
$RevokeCerts_CSV = "C:\Scripts\Report_RevokedCerts_"+((get-date).ToString("yyyyMMdd-HHmmss"))+".csv"
$RevokeCerts | ConvertTo-Csv -Delimiter ";" -NoTypeInformation | Out-File -Encoding utf8 $RevokeCerts_CSV
$duplicateValidCerts_CSV = "C:\Scripts\Report_DuplicatedValidCerts_"+((get-date).ToString("yyyyMMdd-HHmmss"))+".csv"
$duplicateValidCerts | ConvertTo-Csv -Delimiter ";" -NoTypeInformation | Out-File -Encoding utf8 $duplicateValidCerts_CSV
$NoNewCerts_ManualCheckRequired_CSV = "C:\Scripts\Report_NoNewCerts_ManualCheckRequired_"+((get-date).ToString("yyyyMMdd-HHmmss"))+".csv"
$NoNewCerts_ManualCheckRequired | ConvertTo-Csv -Delimiter ";" -NoTypeInformation | Out-File -Encoding utf8 $NoNewCerts_ManualCheckRequired_CSV
My Powershell script categories
- Active Directory
- Cluster
- Database
- Exchange
- Files and folders
- Hardware
- Network
- Operating System
- PKI
- SCCM
- Service and process
- Tips
- VMWare
Sample of the cmdlets availables in the PSPKI module (full list here):
    Add-AdCertificate
    Add-AdCertificateRevocationList
    Add-AuthorityInformationAccess (Alias: Add-AIA)
    Add-CAAccessControlEntry (Alias: Add-CAACL)
    Add-CATemplate
    Add-CertificateEnrollmentPolicyService
    Add-CertificateEnrollmentService
    Add-CertificateTemplateAcl
    Add-CRLDistributionPoint (Alias: Add-CDP)
    Convert-PemToPfx
    Convert-PfxToPem
    Deny-CertificateRequest
    Disable-PolicyModuleFlag
    Get-CATemplate
    Get-CertificateRequest
    Get-CertificateRevocationList (Alias: Get-CRL)
    Get-CertificateRevocationListFlag (Alias: Get-CRLFlag)
    Get-CertificateTemplate
    Get-CertificateTemplateAcl
    Get-IssuedRequest
    Get-PendingRequest
    Publish-CRL
    Remove-CATemplate
    Remove-ExtensionList
    Restart-CertificationAuthority
    Revoke-Certificate
    Start-CertificationAuthority
    Test-WebServerSSL
    Uninstall-CertificationAuthority
