How to export issued certificates from a CA programatically (PowerShell)
Hi all,
The following sample is a conversion of How to export issued certificates from a CA programatically (C#) sample to PowerShell. It will get all the issued certs in the CA database and copy them to a folder:
#Params
$strServer = "myserver";
$strCAName = "myserver-CA";
$strPathForCerts = "c:\test\";
# Constants
$CV_OUT_BASE64HEADER = 0;
$CV_OUT_BINARY = 2;
# Connecting to the Certificate Authority
$objCertView = New-Object -ComObject CertificateAuthority.View
$objCertView.OpenConnection($strServer + "\" + $strCAName)
# Get a column count and place columns into the view
$iColumnCount = $objCertView.GetColumnCount(0)
$objCertView.SetResultColumnCount($iColumnCount)
# Place each column in the view
for ($x=0; $x -lt $iColumnCount; $x++)
{
$objCertView.SetResultColumn($x)
}
# Open the View and reset the row position
$objCertViewRow = $objCertView.OpenView();
$objCertViewRow.Reset();
# Enumerate Row and Column Information
# Rows (one per cert)
for ($x = 0; $objCertViewRow.Next() -ne -1; $x++)
{
# Columns with the info we need
$objCertViewColumn = $objCertViewRow.EnumCertViewColumn()
while ($objCertViewColumn.Next() -ne -1)
{
switch ($objCertViewColumn.GetDisplayName())
{
"Request ID"
{
#Request ID
$objValue = $objCertViewColumn.GetValue($CV_OUT_BINARY)
if ($objValue -ne $null) {
$strID = "Request ID " + $objValue
}
break
}
"Binary Certificate"
{
# Binary Certificate
$objValue = $objCertViewColumn.GetValue($CV_OUT_BASE64HEADER);
if ($objValue -ne $null) {
# Write certificate to file
$strPath = $strPathForCerts + $strID + ".cer"
Set-Content $strPath $objValue
}
break
}
default
{
}
}
}
}
Write-Host "We are done!`nCerts have been copied to " + $strPathForCerts
I hope it helps.
Regards,
Alex (Alejandro Campos Magencio)
Comments
- Anonymous
April 14, 2012
The code is not very efficient. At first, you don't need to add all columns to the view. For the current task it is enough to add RequestID and rawCertificate columns. The part:# Place each column in the viewfor ($x=0; $x -lt $iColumnCount; $x++) { $objCertView.SetResultColumn($x) }should be replaced with:$objCertView.SetResultColumnCount(2)$Column = $objCertView.GetColumnIndex($false,"RequestID")$objCertView.SetResultColumn($Column)$Column = $objCertView.GetColumnIndex($false,"RawCertificate")$objCertView.SetResultColumn($Column)the next: the code dumps entire Request table (which includes issued, revoked, pending and denied requests). It is reasonable to limit DB search to required request state — Issued certificates. In that case you need to set restriction based on disposition ID (which is 20 for issued certificates). Add the code to previous modification:$RColumn = $objCertView.GetColumnIndex($False, "Disposition")$objCertView.SetRestriction($RColumn,1,0,20)and then open view.p.s. $objCertViewRow.Reset(); — for what reason you reset enumerator when it is already set to initial position?p.p.s. Set-Content $strPath $objValue — by default Set-Content cmdlet saves the file by using Unicode encoding which may be not supported by 3rd party tools (hence, Windows Server 2008 R2 CA still do not support Unicode requests!) and waste disk space. You should use ASCII encoding for saved files:Set-Content -Path $strPath -Value $objValue -Encoding ASCIIp.p.p.s in PowerShell it is not necessary to place BREAK statement after each case element. This is because PowerShell supports multiple case matching. - Anonymous
June 14, 2012
Hello,for me this is very interesting.Is this possible to get with this code one certificate thats meet a criteria (e.g. Disply name = Firstname Lastname).Regards,Stefan Horz - Anonymous
May 05, 2014
Extremely dodgy piece of code - come on guys, surely you can do better? - Anonymous
May 07, 2014
worked like a charm. for something I need once a year I'll take expedience over elegance. Save the elegant code for something worthy. Thank you!