Working with Certification Authorities (CA), native PowerShell commands are not too well established yet to fit all my needs, so I had to think about a solution how I could use the well-known certutil tool and use its output within PowerShell.
That is what I came up with (thanks to Shane’s blogpost):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | function certutilToObjectList($certutilOutput){ $certutilObjectList = @() $currentKey = $null $currentValue = $null $certutilOutput -split [environment]::NewLine | foreach { switch -regex ($_){ '[Entry|Row] \d+:(.*)' { # New Object found $currentObject = New-Object psobject $currentValue = $null continue } '(\s{2})(?[\w\s]+):\s*(?.*)' { # Add key / value pair to Object if($currentObject){ if( -not $matches.value){ $currentKey = $matches.key.Trim() $currentValue = $null } else { $currentObject | Add-Member -MemberType NoteProperty -Name $($matches.key.Trim()) -Value $($matches.value.trim(@("'",'"','`'))) -Force } } } '^$' { # Add Object to ObjectList if Object exists if($currentObject){ if($currentKey -and $currentValue){ $currentObject | Add-Member -MemberType NoteProperty -Name $($currentKey) -Value $($currentValue) -Force } $certutilObjectList += $currentObject $currentObject = $null $currentKey = $null $currentValue = $null } } default { # Save Values of Multiline Parameters if a current Key exists if($currentObject -and $currentKey){ $currentValue += $_+"`n" } } } } # Add last Object to ObjectList if necessary if($currentKey -and $currentValue){ $currentObject | Add-Member -MemberType NoteProperty -Name $($currentKey) -Value $($currentValue) -Force } $certutilObjectList += $currentObject return $certutilObjectList } $certutil = "$($env:SystemRoot)\system32\certutil.exe" $certutilOutput = Invoke-Expression "$certutil -view -restrict disposition==20 -out 'serialnumber,requestid,Issued Common Name,Certificate Expiration Date'" $certutilObjectList = certutilToObjectList $certutilOutput |
This function splits the certutil output into single rows and processes them one by one using regular expressions to figure out what to do with each row. It further creates a list (array) of PowerShell objects to make the output easily usable with PowerShell.
Used regex
1 | [Entry|Row] \d+:(.*) |
Matches every row starting with the word “Entry” or “Row” followed by at least one digit and finished by a colon “:” and zero one or multiple characters.
1 | (\s{2})(?<key>[\w\s]+):\s*(?<value>.*) |
Matches all word characters from a-z, A-Z, -0-9, the underscore “_” and whitespaces, after two spaces, until the colon “:” and stores it in the match variable “key”. It further matches every character after the colon and stores it in the match variable “value”.
1 | ^$ |
Matches with empty rows which signals the end of the object in this case
Example certutil output
Row 1:
Serial Number: “MyCertSerialNumber”
Issued Request ID: 0x8
Issued Common Name: “MyCertCommonName”
Certificate Expiration Date: 15.07.2017 12:00
Row 2:
Serial Number: “MyCertSerialNumber”
Issued Request ID: 0x9
Issued Common Name: “MyCertCommonName”
Certificate Expiration Date: 01.10.2017 13:30
I’ve published a slightly edited version of this script in the Technet Gallery: https://gallery.technet.microsoft.com/Script-to-Convert-9793db94
Feel free to download and use it.
I tried to use your script with “certutil -store my”.
To get it to work I had to change the match strings .
# New object detected
‘(Entry|Row|Certificate) \d+’ {
# Add key / value pair to the current object if there is one
‘(^\s*)(?\w+[\w\s\|/]+):\s*(?.*)’ {
Hi
We are using a clustered CA, to use Certutil in a command prompt we have to pass the -config parameter so the query works such as certutil.exe -config “testdomsca.testdom.local\testdom sca” -catemplates
Ive been trying $certutilObjectList = Get-CertutilObjectList(Invoke-Expression “$($env:SystemRoot)\system32\certutil.exe -config “testdomsca.testdom.local\testdom sca” -CATemplates”) with the script but am getting the error
Invoke-Expression : A positional parameter cannot be found that accepts argument ‘testdomsca.testdom.local\testdom’.
At C:\Certs\Get-CertutilObjectList_1.2.ps1:146 char:46
+ … lObjectList(Invoke-Expression “$($env:SystemRoot)\system32\certutil.e …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Invoke-Expression], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.InvokeExpressionCommand
Am I doing anything wrong ?