Hello again, PowerShell CryptoGuy is back!
I was impressed how many feedback I received on my proof of concept version of Enterprise PKI health verifier: Enterprise PKI (pkiview.msc) PowerShell Edition (PoC). I carefully reviewed each feedback and implemented almost all requests.
New version become more unified with more input and configuration options:
I got a request to validate previous non-expired CA keys and certificates. Unfortunately, it is not possible to retrieve CA Exchange certificate for previous CA keys and it is too hard to implement, while workarounds are easier. It is not even scheduled to implement. With new parameter (that accepts end-entity certificate as input) you can manually check previous CA keys/certs.
Since the code is more unified, new parameters were added (instead of hardcoded values):
Value range for threshold values is between 1 and 99 (in percent). Help copy added to a file. Here is a sample debug output:
PS C:\> get-ca dc2* | Get-EnterprisePKIHealthStatus -Debug DEBUG: Initializing parameterset: __CA. ==================== contoso-DC2-CA ==================== DEBUG: contoso-DC2-CA: retrieving CA Exchange certificate. DEBUG: Entering certification path validation routine... DEBUG: Chain status for certificate 'CN=contoso-DC2-CA-Xchg, DC=contoso, DC=com': True DEBUG: CA name: contoso-DC2-CA DEBUG: ========================= CN=contoso-DC2-CA, DC=contoso, DC=com ========================= DEBUG: Getting URLs. DEBUG: Fetching CRL Distribution Points extension... DEBUG: Found 1 CDP URLs. DEBUG: http://www.contoso.com/pki/contoso-DC2-CA(3).crl DEBUG: Fetching Authority Information Access extension... DEBUG: Found 1 Certification Authority Issuer URLs. DEBUG: http://www.contoso.com/pki/dc2ica(3).crt DEBUG: Found 1 On-line Certificate Status Protocol URLs. DEBUG: http://dc2.contoso.com/ocsp DEBUG: Processing Certification Authority Issuer URLs... DEBUG: Downloading cert URL: http://www.contoso.com/pki/dc2ica(3).crt. DEBUG: URL error: -2145844844 DEBUG: Failed to download certificate. DEBUG: Downloading CRL URL: http://www.contoso.com/pki/contoso-DC2-CA(3).crl. DEBUG: CRL: CN=contoso-DC2-CA, DC=contoso, DC=com DEBUG: Entering CRL validation routine... DEBUG: Base CRL start validity : 01/12/2015 15:44:01 DEBUG: Base CRL end validity : 01/19/2015 17:04:01 DEBUG: Crl number: 5240 DEBUG: Base CRL is about to expire. Elapsed: 88% DEBUG: Getting URLs. DEBUG: Fetching 'Freshest CRL extension' DEBUG: 'Freshest CRL' extension is presented. DEBUG: Found 1 Freshest CRL URLs. DEBUG: http://www.contoso.com/pki/contoso-DC2-CA(3)+.crl DEBUG: Downloading CRL URL: http://www.contoso.com/pki/contoso-DC2-CA(3)+.crl. DEBUG: CRL: CN=contoso-DC2-CA, DC=contoso, DC=com DEBUG: Entering CRL validation routine... DEBUG: Delta CRL start validity : 01/18/2015 15:44:30 DEBUG: Delta CRL end validity : 01/19/2015 17:04:30 DEBUG: Crl number: 5246 DEBUG: Referenced Base CRL number: 5240 DEBUG: Required minimum Base CRL number: 5240 DEBUG: Processing On-line Certificate Status Protocol URLs... DEBUG: Entering OCSP validation routine... DEBUG: URL: http://dc2.contoso.com/ocsp DEBUG: OCSP server failed: Unauthorized DEBUG: ========================= CN=Contoso CA, DC=contoso, DC=com ========================= DEBUG: Getting URLs. DEBUG: Fetching CRL Distribution Points extension... DEBUG: Found 1 CDP URLs. DEBUG: http://www.contoso.com/pki/contoso_RCA.crl DEBUG: Fetching Authority Information Access extension... DEBUG: Found 1 Certification Authority Issuer URLs. DEBUG: http://www.contoso.com/pki/Contoso_RCA(1).crt DEBUG: Found 0 On-line Certificate Status Protocol URLs. DEBUG: Processing Certification Authority Issuer URLs... DEBUG: Downloading cert URL: http://www.contoso.com/pki/Contoso_RCA(1).crt. DEBUG: Certificate: CN=Contoso CA, DC=contoso, DC=com DEBUG: Entering certificate validation routine. DEBUG: Leaf certificate: CN=Contoso CA, DC=contoso, DC=com. DEBUG: Self-signed certificate, issuer is itself. DEBUG: Certificate start validity : 02/15/2009 16:31:15 DEBUG: Certificate end validity : 05/19/2029 10:11:24 DEBUG: Subject name binary comparison : passed DEBUG: Public key binary comparison : passed DEBUG: Public key parameters binary comparison: passed DEBUG: Certificate passed all validity checks. DEBUG: Downloading CRL URL: http://www.contoso.com/pki/contoso_RCA.crl. DEBUG: CRL: CN=Contoso CA, DC=contoso, DC=com DEBUG: Entering CRL validation routine... DEBUG: Base CRL start validity : 10/27/2014 01:18:30 DEBUG: Base CRL end validity : 01/28/2015 01:38:30 DEBUG: Crl number: 390 DEBUG: Base CRL is about to expire. Elapsed: 90% DEBUG: Getting URLs. DEBUG: Fetching 'Freshest CRL extension' DEBUG: No FreshestCRL Urls DEBUG: Processing On-line Certificate Status Protocol URLs... DEBUG: ========================= CN=Contoso CA, DC=contoso, DC=com ========================= DEBUG: Leaf certificate is self-signed, skip validation. Name Status Childs ---- ------ ------ contoso-DC2-CA Error {contoso-DC2-CA, Contoso CA} PS C:\> (get-ca dc2* | Get-EnterprisePKIHealthStatus).childs Name : contoso-DC2-CA Status : Error ChainStatus : NoError ExtendedErrorInfo : URLs : {AIA Location #1: http://www.contoso.com/pki/dc2ica(3).crt, expire: , Status: FailedToDownload, CDP Location #1: http://www.contoso.com/pki/contoso-DC2-CA(3).crl, expire: 2015.01.19. 17:04:01, Statu s: Expiring, DeltaCRL Location #1: http://www.contoso.com/pki/contoso-DC2-CA(3)+.crl, expire: 2015. 01.19. 17:04:30, Status: Ok, OCSP Location #1: http://dc2.contoso.com/ocsp, expire: , Status: Unaut horized} Name : Contoso CA Status : Warning ChainStatus : NoError ExtendedErrorInfo : URLs : {AIA Location #1: http://www.contoso.com/pki/Contoso_RCA(1).crt, expire: 2029.05.19. 10:11:24, Stat us: Ok, CDP Location #1: http://www.contoso.com/pki/contoso_RCA.crl, expire: 2015.01.28. 1:38:30, S tatus: Expiring} PS C:\>
CA objects are the same. In order to make things more consistent, I decided to wrap CA object collection to a single chain object. For each chain a separate object is used. This object has “Status” property which is automatically calculated based on CA object (in Childs property) status. CA object status is now automatically calculated based on URL object status (in URLs property). Therefore, when automating CA health validation, you need only to check Status property on chain object.
As always, feedback is accepted and appreciated. How good the tool will be – it depends on you :)
this script requires installed PowerShell PKI module!
Hello, Great new version! And indeed, passing a certificate directly is enough for checking previous CA keys/certificates. I have found some bugs though when passing some certificates directly. First, try to pass the "VeriSign Class 3 Secure Server CA - G3" CA certificate (installed by default in the CA store on Windows), and you'll have the following error: Exception calling "DecodeInteger" with "1" argument(s): "Value cannot be null." At C:\Users\ng177f6\Documents\WindowsPowerShell\Get-EnterprisePKIHealthStatus.ps1:490 char:4 + [Int64]$dcrlNumber = [PKI.ASN.ASN1]::DecodeInteger(($crl.Extensions | ? {$_.O ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : ArgumentNullException StackTrace: at System.Management.Automation.ExceptionHandlingOps.ConvertToMethodInvocationException(Exception exception, Type ty peToThrow, String methodName, Int32 numArgs, MemberInfo memberInfo) at CallSite.Target(Closure , CallSite , RuntimeType , Object ) at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1) at System.Management.Automation.Interpreter.DynamicInstruction`3.Run(InterpretedFrame frame) at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame) I also have a "Proxy Authentication Required" when sending the OCSP request. It might be good to allow passing a proxy object to the command since many functions will need to set it (I don't know if it is not automatically set for cert/CRL download but it's needed at least for OCSP requests which don't use the CryptoAPI functions). Finally, there seems to be a bug in the constructor of the X509CRLDistributionPointExtension (maybe linked with the PSPKI module itself then...). I can't reproduce it with the default installed CAs so you'll have to test it on this certificate in order to reproduce: http://publication.certificateservices.eads.com/CAcerts/EADSecoSHA2CA1.cer (this is not a Microsoft CA). Here is the error: New-Object : Exception calling ".ctor" with "2" argument(s): "The data is invalid" At C:\Users\ng177f6\Documents\WindowsPowerShell\Get-EnterprisePKIHealthStatus.ps1:363 char:13 + $cdp = New-Object Security.Cryptography.X509Certificates.X509CRLDistributio ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [New-Object], MethodInvocationException + FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand StackTrace: at System.Management.Automation.DotNetAdapter.AuxiliaryConstructorInvoke(MethodInformation methodInformation, Object [] arguments, Object[] originalArguments) at System.Management.Automation.DotNetAdapter.ConstructorInvokeDotNet(Type type, ConstructorInfo[] constructors, Obj ect[] arguments) at Microsoft.PowerShell.Commands.NewObjectCommand.CallConstructor(Type type, ConstructorInfo[] constructors, Object[ ] args) If you need any more details, don't hesitate to ask. Jordan
Thanks for report. First issue is caused due to a missing extension existence check (CRL is extensionless v1 CRL). I will add this check. Second issue in the X509CRLDistributionPointExtension -- it is a non-implemented code branch. I did not support partitioned CRLs, because never had them to verify. It is strange that you use non-partitioned CRL in a partitioned manner (internal encoding). I'll write a missing code branch to fully support CDP extension. BTW, it would be easier if you contact me via email and I will send you fixed files.
HI vadmins,
I've tried to use the get-enterprisepkihealthstatus with a certificate, created a new-object of type x509certificate2 and assigned a certificate to it. ran the cmdlet only to get an error saying this.
PS C:\Users\administrator.JLR> Get-EnterprisePKIHealthStatus -Certificate $cer -debug
DEBUG: Initializing parameterset: __EndCerts.
DEBUG: Entering certification path validation routine...
DEBUG: Chain status for certificate 'CN=sam.jlr.ktsecureqa.co.uk, DC=jlr, DC=ktsecureqa, DC=co, DC=uk': True
DEBUG: CA name: JLR eToken Issuing CA
DEBUG: ========================= CN=JLR eToken Issuing CA, O=JaguarLandRover, C=GB =========================
DEBUG: Getting URLs.
DEBUG: Fetching CRL Distribution Points extension...
DEBUG: Found 1 CDP URLs.
DEBUG: string[] GetURLs()
DEBUG: Fetching Authority Information Access extension...
DEBUG: Found 1 Certification Authority Issuer URLs.
DEBUG: http://pki.jlr.ktsecureqa.co.uk/JLR%20eToken%20Issuing%20CA.crt
DEBUG: Found 0 On-line Certificate Status Protocol URLs.
DEBUG: Processing Certification Authority Issuer URLs...
DEBUG: Downloading cert URL: http://pki.jlr.ktsecureqa.co.uk/JLR eToken Issuing CA.crt.
DEBUG: Certificate: CN=JLR eToken Issuing CA, O=JaguarLandRover, C=GB
DEBUG: Entering certificate validation routine.
DEBUG: Leaf certificate: CN=JLR eToken Issuing CA, O=JaguarLandRover, C=GB.
DEBUG: Issuer candidate: CN=JLR eToken Issuing CA, O=JaguarLandRover, C=GB.
DEBUG: Certificate start validity : 07/30/2015 13:57:29
DEBUG: Certificate end validity : 07/30/2016 14:07:29
DEBUG: Subject name binary comparison : passed
DEBUG: Public key binary comparison : passed
DEBUG: Public key parameters binary comparison: passed
DEBUG: Certificate passed all validity checks.
New-Object : The value supplied is not valid, or the property is read-only. Change the value, and then try again.
At C:\Program Files\Sysadmins LV\PowerShell PKI Module\pspki\Server\Get-EnterprisePKIHealthStatus.ps1:605 char:20
+ $urlElement = New-Object PKI.EnterprisePKI.UrlElement -Property @{
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [New-Object], Exception
+ FullyQualifiedErrorId : SetValueException,Microsoft.PowerShell.Commands.NewObjectCommand
DEBUG: Downloading CRL URL: .
DEBUG: URL error: 50
DEBUG: Failed to download CRL.
You cannot call a method on a null-valued expression.
At C:\Program Files\Sysadmins LV\PowerShell PKI Module\pspki\Server\Get-EnterprisePKIHealthStatus.ps1:638 char:7
+ $urlElement.SetError($s_error -bor [PKI.EnterprisePKI.UrlStatus]::FailedTo ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
The property 'ExtendedErrorInfo' cannot be found on this object. Verify that the property exists and can be set.
At C:\Program Files\Sysadmins LV\PowerShell PKI Module\pspki\Server\Get-EnterprisePKIHealthStatus.ps1:639 char:7
+ $urlElement.ExtendedErrorInfo = $obj
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFound
DEBUG: Processing On-line Certificate Status Protocol URLs...
DEBUG: ========================= CN=JaguarLandRover Root CA =========================
DEBUG: Getting URLs.
DEBUG: Fetching CRL Distribution Points extension...
DEBUG: Found 1 CDP URLs.
DEBUG: string[] GetURLs()
DEBUG: Fetching Authority Information Access extension...
DEBUG: Found 1 Certification Authority Issuer URLs.
DEBUG: http://pki.jaguarlandrover.com/JaguarLandRoverRootCertificate.crt
DEBUG: Found 0 On-line Certificate Status Protocol URLs.
DEBUG: Processing Certification Authority Issuer URLs...
DEBUG: Downloading cert URL: http://pki.jaguarlandrover.com/JaguarLandRoverRootCertificate.crt.
DEBUG: Certificate: CN=JaguarLandRover Root CA
DEBUG: Entering certificate validation routine.
DEBUG: Leaf certificate: CN=JaguarLandRover Root CA.
DEBUG: Self-signed certificate, issuer is itself.
DEBUG: Certificate start validity : 07/30/2015 11:27:56
DEBUG: Certificate end validity : 07/30/2035 11:37:55
DEBUG: Subject name binary comparison : passed
DEBUG: Public key binary comparison : passed
DEBUG: Public key parameters binary comparison: passed
DEBUG: Certificate passed all validity checks.
New-Object : The value supplied is not valid, or the property is read-only. Change the value, and then try again.
At C:\Program Files\Sysadmins LV\PowerShell PKI Module\pspki\Server\Get-EnterprisePKIHealthStatus.ps1:605 char:20
+ $urlElement = New-Object PKI.EnterprisePKI.UrlElement -Property @{
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [New-Object], Exception
+ FullyQualifiedErrorId : SetValueException,Microsoft.PowerShell.Commands.NewObjectCommand
the above is debug for the cmdlet, looks like its failing to fetch the cdp url and hence creating an empty object, thus giving out error.
It is a known issue: https://pspki.codeplex.com/workitem/86. You can redownload PSPKI.zip and updated PKI.Core.dll. This should your issue.
thanks a ton mate, worked like a charm. Now i want to insert, ouputs and exit codes within the script and pipe the status messages to nagios.
Guess i need to resign the script with a certificate or change my execution policy for the time being. thank you vadmis.
I Am very new to this PKI Automation. Could you please send me the script including all parameters. I am not able to find and edit the parameters.
Post your comment:
Comments: