Monday, 22 October 2012
OpenAM Policy Agents for IIS don't support multiple sites correctly
We learned from the agent source code that it uses a global variable readAgentConfigFile to flag if it has already processed the agent configuration file or not. We had a feeling that this could be causing the issue but weren't certain until our co-worker Thomas from Exsertus explained to us that if sites share an Application Pool, they run in the same process. This means that there will be only one global variable in C and C++ code per process but this variable will be shared between multiple sites and thus OpenAM policy agent instances. This explains why every OpenAM policy agent shares the "winning" configuration file.
And now for the solution? We assigned every site its own Application Pool, a practice which the customer was already applying on its production IIS servers. But in my humble opinion, that's only a workaround.
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:
OCSP powershell script
I read following question on http://blogs.technet.com/b/askds/.
Question
Are there any available PowerShell, WMI, or command-line options for configuring an OCSP responder? I know that I can install the feature with the Add-WindowsFeature, but I'd like to script configuring the responder and creating the array.
Answer
[Courtesy of the Jonathan “oh no, feet!” Stephens – Ned]
There are currently no command line tools or dedicated PowerShell cmdlets available to perform management tasks on the Online Responder. You can, however, use the COM interfaces IOCSPAdmin and IOSCPCAConfiguration to manage the revocation providers on the Online Responder.
- Create an IOSCPAdmin object.
- The IOSCPAdmin::OCSPCAConfigurationCollection property will return an IOCSPCAConfigurationCollection object.
- Use IOCSPCAConfigurationCollection::CreateCAConfiguration to create a new revocation provider.
- Make sure you call IOCSPAdmin::SetConfiguration when finished so the online responder gets updated with the new revocation configuration.
Because these are COM interfaces, you can call them from VBScript or PowerShell, so you have great flexibility in how you write your script.
My solution
I have written and tested a powershell script that creates an ocsp configuration.
Required parameters:
- $cert: CA certificate (stored locally)
- $crl: URL of the corresponding crl
- $servername: The server name (eg. OcspServer)
- $signingcertificate: The DN of your signing certificate (eg. CN=ocspSigning, OU=Cert, O=Company, C=Country)
The first two parameters can be passed on the command line, the other two can be hardcoded or saved in an xml file.
First thing we do is save the raw certifcate data of the signing certificate.
# Create a new certificate object
$SigningCert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate
# Get the certificate from the local store by using it's DN
$SigningCert = ls cert:\LocalMachine\My | where {$_.Subject -eq $signingcertificate}
# Save the raw certificate data
$SigningCert = $SigningCert.GetRawCertData()
Next we convert the string that points to the certificate to a file, take it's location and save the raw certificate data of the ca certificate.
$file = Get-Childitem $cert
$certName = $file.Name
$certPath = $file.DirectoryName
$CaCert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate
$CaCert.Import($certPath + "\" + $certName)
$CaCert = $CaCert.GetRawCertData()
We then create an OCSPPropertyCollection. In here we store the url of the certificate revocation list and we specify the refresh interval. After the time specified in the refresh interval, windows will download the newest version of the crl from the specified location.
# Save the desired OcspProperties in a collection object
$OcspProperties = New-Object -com "CertAdm.OCSPPropertyCollection"
$OcspProperties.CreateProperty("BaseCrlUrls", $crl)
$OcspProperties.CreateProperty("RevocationErrorCode", 0)
# Sets the refresh interval to 1 hour (time is specified in milliseconds)
$OcspProperties.CreateProperty("RefreshTimeOut", 3600000)
Finally, we create an OCSPAdmin object and create a new revocation provider.
# Save the baseName in a variable, this is the filename without extension
# eg. basename of certificate.cer is certificate
$certBaseName = $file.BaseName
# Save the current configuration in an OcspAdmin object
$OcspAdmin = New-Object -com "CertAdm.OCSPAdmin"
$OcspAdmin.GetConfiguration($servername, $true)
# Create a new revocation configuration
$NewConfig = $OcspAdmin.OCSPCAConfigurationCollection.CreateCAConfiguration($certBaseName, $CaCert)
$NewConfig.HashAlgorithm = "SHA1"
$NewConfig.SigningFlags = 0x020
$NewConfig.SigningCertificate = $SigningCert
$NewConfig.ProviderProperties = $OcspProperties.GetAllProperties()
$NewConfig.ProviderCLSID = "{4956d17f-88fd-4198-b287-1e6e65883b19}"
$NewConfig.ReminderDuration = 90
# Commit the new configuration to the server
$OcspAdmin.SetConfiguration($servername, $true)
Following links were very helpful when I was writing this script:
Friday, 2 March 2012
Boost for ForgeRock
IS4U is looking forward to what end this investment will aid the evolution of ForgeRock's I³ Open Identity Platform which includes OpenAM, OpenIDM and OpenDJ.