Thursday 7 June 2012

Renew OCSP signing certificate

In my previous post, I described on how to automate the creation of an ocsp responder configuration. This post describes on how to renew and replace the signing certificate when it is about to expire. It also replaces the signing certificate for all ocsp responder configurations. This script automates the process, but there is still some interaction required. The user that runs the script needs to click OK a few times.

Required parameters:

  • $servername: The server name (eg. OcspServer)
  • $signingcertificate: The DN of your signing certificate (eg. CN=ocspSigning, OU=Cert, O=Company, C=Country)

The two parameters can be passed on the command line, hardcoded or saved in an xml file.

The first thing we need is the serial of the OCSP signing certificate that is about to expire. We get it out of the local certificate store and store the serial number in a variable.
# Save the old ocsp signing certificate in a variable
$SigningCert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate
$SigningCert = ls cert:\LocalMachine\My | where {$_.Subject -eq $signingcertificate}

# Get the serial number of the old ocsp signing certificate
$serial = $SigningCert.SerialNumber
We then use certutil to get the key container. This part is a little tricky since this value is stored among a lot of other information. We pull the information we need by string matching and manipulation.
# Get the keycontainer id of the old ocsp signing certificate
$key = certutil.exe -store -v My $serial | Select-String -pattern "Key Container"
$keyContainer = ($key.ToString() -replace "Key Container = ","").Trim()
Once we have the key container value, we can write a certificate request file 'ocspsigigning.inf' and pass it to the certreq command. We store the result in the file 'ocspsigning.req'.
# Write the certificate request info to a file
Write-Output "[NewRequest]" | Out-File "ocspsigning.inf"
Write-Output "RenewalCert = $serial" | Out-File "ocspsigning.inf" -append
Write-Output "KeyContainer = $keyContainer" | Out-File "ocspsigning.inf" -append
Write-Output "UseExistingKeySet = True" | Out-File "ocspsigning.inf" -append
Write-Output "MachineKeySet = True" | Out-File "ocspsigning.inf" -append

# Request a renewal of the ocsp signing certificate using the constructed info
Certreq -new ocspsigning.inf ocspsigning.req
We can now submit the request. We save the returned information because we need the requestID to retrieve the issued certificate. As you have seen above, the same pattern matching and string manipulation is used to obtain this value. Finally we accept the certificate.
# Save the request id in a variable while submitting the request
$reqId = Certreq -submit ocspsigning.req ocspsigning.cer | Select-String -pattern "RequestId: [0-9]"
$reqId = ($reqId.ToString() -replace "RequestId:","").Trim()

# Retrieve the requested certificate
Certreq -retrieve $reqId ocspsigning.cer

# Store the certificate in the local certificate store
Certreq -accept -machine ocspsigning.cer
Now that we have a renewed signing certificate, we can use it to sign the ocsp responses. Therefore, we need to reassign the renewed certificate to all ocsp responder configurations. We save the raw certificate data of the new certificate and iterate over all OCSP configurations in the server array.
# Save the new ocsp signing certificate in a variable
$SigningCert = ls cert:\LocalMachine\My | where {$_.Subject -eq $signingcertificate}
$SigningCert = $SigningCert.GetRawCertData()

# Assign the new ocsp signing certificate to all revocation configurations
$OcspAdmin = New-Object -com "CertAdm.OCSPAdmin"
$OcspAdmin.GetConfiguration($servername, $true)
$OcspAdmin.OCSPCAConfigurationCollection | ForEach-Object {
  Write-Host "Replacing signing certificate for" $_.Identifier
  $_.SigningCertificate = $SigningCert
 }

# Commit the new configuration
$OcspAdmin.SetConfiguration($servername, $true)

Following links were very helpful when I was writing this script: