Solved

Need to get certificates inventory for each server into the spreadsheet- such as expiration date, name of the cert, issuer, cert purpose

Posted on 2015-02-24
23
441 Views
Last Modified: 2015-04-27
Need to get certificates inventory for each server into the spreadsheet- such as expiration date, name of the cert, issuer, cert purpose.

I think I should use a certutil or something similar to export it.

Could you please help with what parameters to use for certutil to export certificates info for each server into csv.
Thank you very much.
0
Comment
Question by:creative555
  • 10
  • 9
  • 4
23 Comments
 
LVL 70

Expert Comment

by:Chris Dent
Comment Utility
What do you mean by "cert purpose"?

You could use certutil, I wrote a bit of PowerShell that'd grab certificate stores (local and remote) though.
function Get-InCertificate {
  # .SYNOPSIS
  #   Get certificates from a local or remote certificate store.
  # .DESCRIPTION
  #   Get X509 certificates from a certificate store.
  # .PARAMETER ComputerName
  #   An optional ComputerName to use for this query. If ComputerName is not specified Get-InCertificate uses the current computer.
  # .PARAMETER Expired
  #   Filter results to only include expired certificates.
  # .PARAMETER ExpiresOn
  #   Filter restults to only include certificates which expire on the specified day (between 00:00:00 and 23:59:59).
  #
  #   This parameter may be used in conjunction with Expired to find certificates which expired on a specific day.
  # .PARAMETER HasPrivateKey
  #   Filter results to only include certificates which have a private key available.
  # .PARAMETER Request
  #   Show pending certificate requests.
  # .PARAMETER StoreLocation
  #   Get-InCertificate gets certificates from the LocalMachine store. The CurrentUser store may be specified.
  # .PARAMETER StoreName
  #   Get-InCertificate gets certificates from all stores. A specific store name, or list of store names, may be supplied if required.
  # .INPUTS
  #   System.Security.Cryptography.X509Certificates.StoreName
  #   System.Security.Cryptography.X509Certificates.StoreLocation
  #   System.String
  # .EXAMPLE
  #   Get-InCertificate -StoreName My -StoreLocation CurrentUser
  #
  #   Get all certificates from the Personal store for the CurrentUser (caller).
  # .EXAMPLE
  #   Get-InCertificate -StoreLocation LocalMachine -Request
  #
  #   Get pending certificate requests.
  # .EXAMPLE
  #   C:\PS>Get-Content ServerList.txt | ForEach-Object {
  #   >>  Get-InCertificate -StoreName My -HasPrivateKey -ComputerName $_
  #   >> }
  #
  #   Get certificates with private keys from the personal store (LocalMachine location) for each of the servers listed in ServerList.txt.
  # .NOTES
  #   Author: Chris Dent
  #
  #   Change log:
  #     09/02/2015 - Chris Dent - BugFix: Parameter existence check for ExpiresOn.
  #     04/02/2015 - Chris Dent - Added Issuer and NotAfter parameters.
  #     22/01/2015 - Chris Dent - Added Request parameter.
  #     24/06/2014 - Chris Dent - Added HasPrivateKey and Expired parameters.
  #     12/06/2014 - Chris Dent - First release.  
  
  [CmdLetBinding(DefaultParameterSetName = 'Certificate')]
  param(
    [Parameter(ParameterSetName = 'Certificate')]
    [Security.Cryptography.X509Certificates.StoreName[]]$StoreName = [Enum]::GetNames([Security.Cryptography.X509Certificates.StoreName]),

    [Security.Cryptography.X509Certificates.StoreLocation]$StoreLocation = "LocalMachine",
  
    [Parameter(ValueFromPipelineByPropertyName = $true)]
    [Alias('ComputerNameString', 'Name')]
    [String]$ComputerName = $env:ComputerName,
    
    [Parameter(ParameterSetName = 'Certificate')]
    [Switch]$HasPrivateKey,
    
    [Parameter(ParameterSetName = 'Certificate')]
    [Switch]$Expired,
    
    [Parameter(ParameterSetName = 'Certificate')]
    [ValidateScript( { Get-Date $_ } )]
    $ExpiresOn,
    
    [Parameter(ParameterSetName = 'Certificate')]
    [ValidateNotNullOrEmpty()]
    [String]$Issuer,
    
    [Parameter(ParameterSetName = 'Request')]
    [Switch]$Request
  )

  begin {
    if ($StoreLocation -ne [Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine -and $ComputerName -ne $env:ComputerName) {
      Write-Warning "Certificates in the CurrentUser location cannot be read remotely."
      break
    }
  
    $WhereStatementText = '$_'
    if ($HasPrivateKey) {
      $WhereStatementText = $WhereStatementText + ' -and $_.HasPrivateKey'
    }
    if ($Expired) {
      $WhereStatementText = $WhereStatementText + ' -and $_.NotAfter -lt (Get-Date)'
    }
    if ($psboundparameters.ContainsKey("ExpiresOn")) {
      $WhereStatementText = $WhereStatementText + ' -and $_.NotAfter -gt (Get-Date $ExpiresOn).Date -and $_.NotAfter -lt (Get-Date $ExpiresOn).Date.AddDays(1).AddSeconds(-1)'
    }
    if ($psboundparameters.ContainsKey("Issuer")) {
      $WhereStatementText = $WhereStatementText + ' -and $_.Issuer -like "*CN=$Issuer*"'
    }
    $WhereStatement = [ScriptBlock]::Create($WhereStatementText)
  }
  
  process {
    if ($Request) {
      if ($ComputerName -eq $env:ComputerName) {
        $StorePath = "REQUEST"
      } else {
        $StorePath = "\\$ComputerName\REQUEST"
      }
    
      $Store = New-Object Security.Cryptography.X509Certificates.X509Store($StorePath, $StoreLocation)
      $Store.Open([Security.Cryptography.X509Certificates.OpenFlags]::ReadOnly)
      $Store.Certificates |
        Add-Member StorePath -MemberType NoteProperty -Value $StorePath -PassThru |
        Add-Member ComputerName -MemberType NoteProperty -Value $ComputerName -PassThru
    } else {
      $StoreName | ForEach-Object {
        if ($ComputerName -eq $env:ComputerName) {
          $StorePath = $_
        } else {
          $StorePath = "\\$ComputerName\$_"
        }
    
        $Store = New-Object Security.Cryptography.X509Certificates.X509Store($StorePath, $StoreLocation)
        $Store.Open([Security.Cryptography.X509Certificates.OpenFlags]::ReadOnly)
        
        if ($?) {
          $Store.Certificates |
            Add-Member StorePath -MemberType NoteProperty -Value $StorePath -PassThru |
            Add-Member ComputerName -MemberType NoteProperty -Value $ComputerName -PassThru |
            Where-Object $WhereStatement
          
          $Store.Close()
        }
      }
    }
  }
}

Open in new window

I reckon you want a take on Example 3:
Get-Content ServerList.txt | ForEach-Object {
  Get-InCertificate -StoreName My -HasPrivateKey -ComputerName $_
} | Select-Object ComputerName, Subject, Issuer, NotAfter, FriendlyName

Open in new window

But I have trouble with "cert purpose". I guess you mean how the certificate is used on the remote system? If so, it's not something you're going to get. But perhaps you can clarify?

Cheers,

Chris
0
 
LVL 61

Expert Comment

by:btan
Comment Utility
powershell is good as shared by expert and also check out this forum for some tested sample PS script too
https://social.technet.microsoft.com/Forums/windowsserver/en-US/eb3f8f93-07ff-4d30-8b0a-7a5bfbb9420e/how-to-retrieve-certificate-information-from-a-remote-server-with-powershell?forum=winserverManagement

besides PS, I am thinking of the Certificate Manager tool (Certmgr.exe) which manages certificates, certificate trust lists (CTLs), and certificate revocation lists (CRLs). ONe sample script to get all MY cert as below (likewise to "certutil -store my")
http://certificate.fyicenter.com/419_Windows_certmgr.exe_List_My_Personal_Certificates.html
(cmd line option for certmgr.exe) https://msdn.microsoft.com/en-us/library/e78byta0(v=vs.110).aspx
To display the certificates in the Local Machine certificate store
Syntax
certutil -store [-f] [-enterprise] [-user] [-gmt] [-seconds] [-silent] [-v] [-dc DCName] CertificateStoreName [CertID [OutFile]]]
(cmd line example for certutil) https://technet.microsoft.com/en-us/library/cc772898(WS.10).aspx
0
 

Author Comment

by:creative555
Comment Utility
I tried this with -DC servername switch and also thought this would work....but didn't....

certutil -store [-f] [-enterprise] [-user] [-gmt] [-seconds] [-silent] [-v] [-dc DCName] CertificateStoreName [CertID [OutFile]]]

Fore the powershell script you posted I get the error that unrecongnized command.....Please note the servers that I want to get certificates in personal stores are all 2003. Would the powershell work for them?
0
 

Author Comment

by:creative555
Comment Utility
et-InCertificate : The term 'Get-InCertificate' is not recognized as the name of a cmdlet, function, script file, or
operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try
again.
At line:1 char:1
+ Get-InCertificate -StoreName My -HasPrivateKey -ComputerName DC01 | Se ...
+ ~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (Get-InCertificate:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
0
 

Author Comment

by:creative555
Comment Utility
I have not tried this option yet -certmgr.exe. Do I need to install Visual Studio for this on the server?
0
 
LVL 61

Expert Comment

by:btan
Comment Utility
Can also try to  certutil -error <Code> to decode Windows errors. I believe for W2K3 the available option may be for this stated in though it did not mentioned -dc http://www.tekweb.dk/manuals/command/commands/c/certutit.htm
Regardless, -dc should be resolving as per your dns configuration else use the IP address. To be more specific, it is actually, FQDN is used ( fully-qualified host and domain name) for the Directory Server, such as ldap.example.com. Note that this name must be available for DNS and reverse DNS lookups to Directory Server clients because certificate validation may fail if the clients cannot properly resolve the FQDN.

PowerShell is included with Windows Server 2008 R2 but it has to be added to Windows Server 2003. You need to download and install “Windows Management Framework” (Which gives you Windows PowerShell 2.0, WinRM 2.0, and BITS 4.0) Details on this package as well as the download links can be found here http://support.microsoft.com/kb/968929 Pls see this for more info - http://blogs.technet.com/b/danstolts/archive/2011/03/07/how-to-install-powershell-on-windows-server-2003-and-enable-remote-powershell-management-all-servers-should-have-this-done.aspx

The Certificate Manager (certmgr.exe, not certmgr.msc) is automatically installed with Visual Studio. So yes you need to install VStudio.
The Certificate Manager tool (Certmgr.exe) is a command-line utility, whereas Certificates (Certmgr.msc) is a Microsoft Management Console (MMC) snap-in. Because Certmgr.msc is usually found in the Windows System directory, entering certmgr at the command line may load the Certificates MMC snap-in even if you have opened the Visual Studio Command Prompt. This occurs because the path to the snap-in precedes the path to the Certificate Manager tool in the PATH environment variable. If you encounter this problem, you can execute Certmgr.exe commands by specifying the path to the executable.
0
 
LVL 70

Expert Comment

by:Chris Dent
Comment Utility
You must paste the first bit of PowerShell code into the prompt before the second will work. This creates the command you can use.

It does work on 2003, I've used it to audit a thousand or so servers running operating systems between 2003 and 2012 R2.

Chris
0
 

Author Comment

by:creative555
Comment Utility
i tried pasting one line by one like you said, but I still get error

get-InCertificate : The term 'get-InCertificate' is not recognized as the name
of a cmdlet, function, script file, or operable program. Check the spelling of
the name, or if a path was included, verify that the path is correct and try
again.
At line:1 char:1
+ get-InCertificate
+ ~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (get-InCertificate:String) [], C
   ommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
0
 
LVL 70

Expert Comment

by:Chris Dent
Comment Utility
Well, there's an alternative.

Save the attachment and rename it to Get-InCertificate.ps1 once you've downloaded it.

Then from the PowerShell window you can run:
Get-Content ServerList.txt | ForEach-Object {
  C:\Path\To\Script\Get-InCertificate.ps1 -StoreName My -HasPrivateKey -ComputerName $_
} | Select-Object ComputerName, Subject, Issuer, NotAfter, FriendlyName

Open in new window

If the first block of code can be copied in without error you shouldn't get the error message.

Chris
Get-InCertificate.txt
0
 

Author Comment

by:creative555
Comment Utility
It is working now!!! :)

how would I get additional in the select statement?
Select-Object ComputerName, Subject, Issuer, NotAfter, FriendlyName

Need to add the following:
- CERT_KEY_PROV_INFO_PROP_ID(2):
-Subject Alternative Name
  -  Enhanced Key Usage

Also, I need to remove the filter to show all certificates and not just expired
0
 

Author Comment

by:creative555
Comment Utility
Is there a way to get a subject alternative name also in the spreadsheet as well as CERT_KEY_PROV_INFO_PROP_ID(2)  ? I get this below. I checked with the certificate info and it had subject alternative name listed as below

SubjectName
System.Security.Cryptography.X509Certificates.X500DistinguishedName
System.Security.Cryptography.X509Certificates.X500DistinguishedName
System.Security.Cryptography.X509Certificates.X500DistinguishedName
System.Security.Cryptography.X509Certificates.X500DistinguishedName
System.Security.Cryptography.X509Certificates.X500DistinguishedName
System.Security.Cryptography.X509Certificates.X500DistinguishedName

EnhancedKeyUsageList
Blank



Below Is the output from certutil -store - v command
    Subject Alternative Name
        Other Name:
             1.3.6.1.4.1.311.25.1=04 10 5d 41 fd aa 6f 21 92 49 8c 82 d2 58 89 b9 7e da
        DNS Name=dcserver01.corp.domain.com

-  Enhanced Key Usage
        Server Authentication (1.3.6.1.5.5.7.3.1)

-- CERT_KEY_PROV_INFO_PROP_ID(2):
    Key Container = 5888c093bcfa376d2dd943e8bab17751_2168e4d8-46c7-4011-9c98-9ee2c4970af9
    Provider = Microsoft RSA SChannel Cryptographic Provider
0
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 
LVL 61

Expert Comment

by:btan
Comment Utility
0
 

Author Comment

by:creative555
Comment Utility
How do I combine it with the script that I already have? It is too complicated for me...sorry.
I made the script work that was first posted here and I just need to add SAN as well to this:

THis works for me. But SAN output name doesn't come into readable form in the excel

Get-Content ServerListPart3.txt | ForEach-Object {C:\Users\username\sslcerts\Get-InCertificate.ps1 -StoreName My -HasPrivateKey -ComputerName $_} | Select-Object ComputerName, Subject, Issuer, NotAfter, HasPrivateKey, SerialNumber, Thumbprint, FriendlyName | export-csv exportcert2.csv



With the script recommended, I do have to get a string for each cert such as this. $cert = get-childitem cert:\localmachine\my\73844B2206C170903185E777F65E969247462741
It is just as difficult as getting SAN name..
0
 
LVL 70

Expert Comment

by:Chris Dent
Comment Utility
The two interfaces (the one I worked with, and the cert: drive) provide exactly the same information in exactly the same format.

Subject Alternate Names needed a bit of work to add so I have a new script version for you which attempts to display it.

Your main script will only need SubjectAlternateNames adding to the output selection this once you've updated the script file:
Get-Content ServerListPart3.txt | 
  ForEach-Object {
    C:\Users\username\sslcerts\Get-InCertificate.ps1 -StoreName My -HasPrivateKey -ComputerName $_
  } |
  Select-Object ComputerName, Subject, SubjectAlternateNames, Issuer, NotAfter, HasPrivateKey, SerialNumber, Thumbprint, FriendlyName |
  export-csv exportcert2.csv -NoTypeInformation

Open in new window

The format of the field is a bit best effort. Please let me know how you get on.

HTH

Chris
Get-InCertificate.txt
0
 
LVL 70

Expert Comment

by:Chris Dent
Comment Utility
> The two interfaces (the one I worked with, and the cert: drive) provide exactly the same information
> in exactly the same format.

Sorry, I meant to add credit in here. The decode method I used was from the link btan posted so thank you for that :)

Chris
0
 

Author Comment

by:creative555
Comment Utility
Hey,
I am still getting this in the excel file.

SubjectName
System.Security.Cryptography.X509Certificates.X500DistinguishedName
System.Security.Cryptography.X509Certificates.X500DistinguishedName
System.Security.Cryptography.X509Certificates.X500DistinguishedName
System.Security.Cryptography.X509Certificates.X500DistinguishedName
System.Security.Cryptography.X509Certificates.X500DistinguishedName
0
 
LVL 70

Accepted Solution

by:
Chris Dent earned 500 total points
Comment Utility
You will, there are some complex properties in the certificate store. As such, you'll get SubjectName like that (because it's not simple) and another field called Subject which is simple. The two hold the same information (for the most part) so I recommend discarding SubjectName and relying on Subject unless you need something advanced.

Issuer and IssuerName will show the same behaviour.

If you find you need to know about Server Authentication and Client Authentication key usages I added an adapter today that would let those display in Export-Csv cleanly. They hide under the "extensions" property otherwise. Yell if you'd like me to post it.

Chris
0
 

Author Closing Comment

by:creative555
Comment Utility
Thank you so much, Chris! Your script provided an excellent excel spreadsheet and what I needed. I can't appreciate enough all the hard work you put into the answer for my question. Wish I could grant you more points. Thank you again!
0
 
LVL 70

Expert Comment

by:Chris Dent
Comment Utility
You're welcome :)

Chris
0
 
LVL 61

Expert Comment

by:btan
Comment Utility
I have learnt as well thanks folks :)
0
 
LVL 70

Expert Comment

by:Chris Dent
Comment Utility
For posterity, here's the updated code from Get-InCertificate from my Certificate Management module. It has a couple of tweaks over the original here:

Presents the EnhancedKeyUsages as a simple list on the return object.
No longer requests line breaks when decoding the SAN (.Format($false) vs .Format($true) or .Format(1))

Drop the "function Get-InCertificate {" line and the very last "}" in the code block and it can replace the content of the attachment posted above.
function Get-InCertificate {
  # .SYNOPSIS
  #   Get certificates from a local or remote certificate store.
  # .DESCRIPTION
  #   Get X509 certificates from a certificate store.
  # .PARAMETER ComputerName
  #   An optional ComputerName to use for this query. If ComputerName is not specified Get-InCertificate uses the current computer.
  # .PARAMETER Expired
  #   Filter results to only include expired certificates.
  # .PARAMETER ExpiresOn
  #   Filter restults to only include certificates which expire on the specified day (between 00:00:00 and 23:59:59).
  #
  #   This parameter may be used in conjunction with Expired to find certificates which expired on a specific day.
  # .PARAMETER HasPrivateKey
  #   Filter results to only include certificates which have a private key available.
  # .PARAMETER Request
  #   Show pending certificate requests.
  # .PARAMETER StoreLocation
  #   Get-InCertificate gets certificates from the LocalMachine store. The CurrentUser store may be specified.
  # .PARAMETER StoreName
  #   Get-InCertificate gets certificates from all stores. A specific store name, or list of store names, may be supplied if required.
  # .INPUTS
  #   System.Security.Cryptography.X509Certificates.StoreName
  #   System.Security.Cryptography.X509Certificates.StoreLocation
  #   System.String
  # .EXAMPLE
  #   Get-InCertificate -StoreName My -StoreLocation CurrentUser
  #
  #   Get all certificates from the Personal store for the CurrentUser (caller).
  # .EXAMPLE
  #   Get-InCertificate -StoreLocation LocalMachine -Request
  #
  #   Get pending certificate requests.
  # .NOTES
  #   Author: Chris Dent
  #   Team:   Core Technologies
  #
  #   Change log:
  #     03/03/2015 - Chris Dent - Changed Subject Alternate Names decode to drop line breaks. Modified EnhancedKeyUsages to correctly "ToString" from a remote machine.
  #     02/03/2015 - Chris Dent - Added EnhangedKeyUsages property to base object.
  #     27/02/2015 - Chris Dent - Merged store queries into a single statement. Added decode support for Subject Alternate Names.
  #     09/02/2015 - Chris Dent - BugFix: Parameter existence check for ExpiresOn.
  #     04/02/2015 - Chris Dent - Added Issuer and NotAfter parameters.
  #     22/01/2015 - Chris Dent - Added Request parameter.
  #     24/06/2014 - Chris Dent - Added HasPrivateKey and Expired parameters.
  #     12/06/2014 - Chris Dent - First release.  
  
  [CmdLetBinding(DefaultParameterSetName = 'Certificate')]
  param(
    [Parameter(ParameterSetName = 'Certificate')]
    [Security.Cryptography.X509Certificates.StoreName[]]$StoreName = [Enum]::GetNames([Security.Cryptography.X509Certificates.StoreName]),

    [Security.Cryptography.X509Certificates.StoreLocation]$StoreLocation = "LocalMachine",
  
    [Parameter(ValueFromPipelineByPropertyName = $true)]
    [Alias('ComputerNameString', 'Name')]
    [String]$ComputerName = $env:ComputerName,
    
    [Switch]$HasPrivateKey,
    
    [Switch]$Expired,
    
    [ValidateScript( { Get-Date $_ } )]
    $ExpiresOn,
    
    [ValidateNotNullOrEmpty()]
    [String]$Issuer,
    
    [Parameter(ParameterSetName = 'Request')]
    [Switch]$Request
  )

  begin {
    if ($StoreLocation -ne [Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine -and $ComputerName -ne $env:ComputerName) {
      Write-Warning "Certificates in the CurrentUser location cannot be read remotely."
      break
    }
  
    $WhereStatementText = '$_'
    if ($HasPrivateKey) {
      $WhereStatementText = $WhereStatementText + ' -and $_.HasPrivateKey'
    }
    if ($Expired) {
      $WhereStatementText = $WhereStatementText + ' -and $_.NotAfter -lt (Get-Date)'
    }
    if ($psboundparameters.ContainsKey("ExpiresOn")) {
      $WhereStatementText = $WhereStatementText + ' -and $_.NotAfter -gt (Get-Date $ExpiresOn).Date -and $_.NotAfter -lt (Get-Date $ExpiresOn).Date.AddDays(1).AddSeconds(-1)'
    }
    if ($psboundparameters.ContainsKey("Issuer")) {
      $WhereStatementText = $WhereStatementText + ' -and $_.Issuer -like "*CN=$Issuer*"'
    }
    $WhereStatement = [ScriptBlock]::Create($WhereStatementText)
  }
  
  process {
    if ($Request) {
      $StoreNames = 'REQUEST'
    } else {
      $StoreNames = $StoreName
    }
  
    $StoreNames | ForEach-Object {
      if ($ComputerName -eq $env:ComputerName) {
        $StorePath = $_
      } else {
        $StorePath = "\\$ComputerName\$_"
      }
  
      $Store = New-Object Security.Cryptography.X509Certificates.X509Store($StorePath, $StoreLocation)
      $Store.Open([Security.Cryptography.X509Certificates.OpenFlags]::ReadOnly)
      
      if ($?) {
        $Store.Certificates |
          Add-Member StorePath -MemberType NoteProperty -Value $StorePath -PassThru |
          Add-Member ComputerName -MemberType NoteProperty -Value $ComputerName -PassThru |
          Add-Member SubjectAlternativeNames -MemberType ScriptProperty -Value {
            if ($this.Extensions | Where-Object { $_.Oid.Value -eq '2.5.29.17' }) {
              $this.Extensions['2.5.29.17'].Format($false)
            }
          } -PassThru |
          Add-Member EnhancedKeyUsages -MemberType ScriptProperty -Value {
            if ($this.Extensions | Where-Object { $_.Oid.Value -eq '2.5.29.37' }) {
              $this.Extensions['2.5.29.37'].EnhancedKeyUsages |
                ForEach-Object {
                  $_ | Add-Member ToString -MemberType ScriptMethod -Force -Value {
                    "$($this.Value) ($($this.FriendlyName))"
                  }
                  
                  $_
              }
            }
          } -PassThru |
          Where-Object $WhereStatement
          
        $Store.Close()
      }
    }
  }
}

Open in new window

All the best.

Chris
0
 

Author Comment

by:creative555
Comment Utility
Hello Chris,
Sorry to trouble you. I want to use this script for another project but the latest updated script here is giving me troubles. I am not sure how to update it.

What do you mean by the following?

Drop the "function Get-InCertificate {" line and the very last "}" in the code block and it can replace the content of the attachment posted above.

THank you very much.
0
 
LVL 70

Expert Comment

by:Chris Dent
Comment Utility
If you put this bit into a .ps1 file it can be used as a normal script. It'll still have help text and so on.
  # .SYNOPSIS
  #   Get certificates from a local or remote certificate store.
  # .DESCRIPTION
  #   Get X509 certificates from a certificate store.
  # .PARAMETER ComputerName
  #   An optional ComputerName to use for this query. If ComputerName is not specified Get-InCertificate uses the current computer.
  # .PARAMETER Expired
  #   Filter results to only include expired certificates.
  # .PARAMETER ExpiresOn
  #   Filter restults to only include certificates which expire on the specified day (between 00:00:00 and 23:59:59).
  #
  #   This parameter may be used in conjunction with Expired to find certificates which expired on a specific day.
  # .PARAMETER HasPrivateKey
  #   Filter results to only include certificates which have a private key available.
  # .PARAMETER Request
  #   Show pending certificate requests.
  # .PARAMETER StoreLocation
  #   Get-InCertificate gets certificates from the LocalMachine store. The CurrentUser store may be specified.
  # .PARAMETER StoreName
  #   Get-InCertificate gets certificates from all stores. A specific store name, or list of store names, may be supplied if required.
  # .INPUTS
  #   System.Security.Cryptography.X509Certificates.StoreName
  #   System.Security.Cryptography.X509Certificates.StoreLocation
  #   System.String
  # .EXAMPLE
  #   Get-InCertificate -StoreName My -StoreLocation CurrentUser
  #
  #   Get all certificates from the Personal store for the CurrentUser (caller).
  # .EXAMPLE
  #   Get-InCertificate -StoreLocation LocalMachine -Request
  #
  #   Get pending certificate requests.
  # .NOTES
  #   Author: Chris Dent
  #   Team:   Core Technologies
  #
  #   Change log:
  #     03/03/2015 - Chris Dent - Changed Subject Alternate Names decode to drop line breaks. Modified EnhancedKeyUsages to correctly "ToString" from a remote machine.
  #     02/03/2015 - Chris Dent - Added EnhangedKeyUsages property to base object.
  #     27/02/2015 - Chris Dent - Merged store queries into a single statement. Added decode support for Subject Alternate Names.
  #     09/02/2015 - Chris Dent - BugFix: Parameter existence check for ExpiresOn.
  #     04/02/2015 - Chris Dent - Added Issuer and NotAfter parameters.
  #     22/01/2015 - Chris Dent - Added Request parameter.
  #     24/06/2014 - Chris Dent - Added HasPrivateKey and Expired parameters.
  #     12/06/2014 - Chris Dent - First release.  
  
  [CmdLetBinding(DefaultParameterSetName = 'Certificate')]
  param(
    [Parameter(ParameterSetName = 'Certificate')]
    [Security.Cryptography.X509Certificates.StoreName[]]$StoreName = [Enum]::GetNames([Security.Cryptography.X509Certificates.StoreName]),

    [Security.Cryptography.X509Certificates.StoreLocation]$StoreLocation = "LocalMachine",
  
    [Parameter(ValueFromPipelineByPropertyName = $true)]
    [Alias('ComputerNameString', 'Name')]
    [String]$ComputerName = $env:ComputerName,
    
    [Switch]$HasPrivateKey,
    
    [Switch]$Expired,
    
    [ValidateScript( { Get-Date $_ } )]
    $ExpiresOn,
    
    [ValidateNotNullOrEmpty()]
    [String]$Issuer,
    
    [Parameter(ParameterSetName = 'Request')]
    [Switch]$Request
  )

  begin {
    if ($StoreLocation -ne [Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine -and $ComputerName -ne $env:ComputerName) {
      Write-Warning "Certificates in the CurrentUser location cannot be read remotely."
      break
    }
  
    $WhereStatementText = '$_'
    if ($HasPrivateKey) {
      $WhereStatementText = $WhereStatementText + ' -and $_.HasPrivateKey'
    }
    if ($Expired) {
      $WhereStatementText = $WhereStatementText + ' -and $_.NotAfter -lt (Get-Date)'
    }
    if ($psboundparameters.ContainsKey("ExpiresOn")) {
      $WhereStatementText = $WhereStatementText + ' -and $_.NotAfter -gt (Get-Date $ExpiresOn).Date -and $_.NotAfter -lt (Get-Date $ExpiresOn).Date.AddDays(1).AddSeconds(-1)'
    }
    if ($psboundparameters.ContainsKey("Issuer")) {
      $WhereStatementText = $WhereStatementText + ' -and $_.Issuer -like "*CN=$Issuer*"'
    }
    $WhereStatement = [ScriptBlock]::Create($WhereStatementText)
  }
  
  process {
    if ($Request) {
      $StoreNames = 'REQUEST'
    } else {
      $StoreNames = $StoreName
    }
  
    $StoreNames | ForEach-Object {
      if ($ComputerName -eq $env:ComputerName) {
        $StorePath = $_
      } else {
        $StorePath = "\\$ComputerName\$_"
      }
  
      $Store = New-Object Security.Cryptography.X509Certificates.X509Store($StorePath, $StoreLocation)
      $Store.Open([Security.Cryptography.X509Certificates.OpenFlags]::ReadOnly)
      
      if ($?) {
        $Store.Certificates |
          Add-Member StorePath -MemberType NoteProperty -Value $StorePath -PassThru |
          Add-Member ComputerName -MemberType NoteProperty -Value $ComputerName -PassThru |
          Add-Member SubjectAlternativeNames -MemberType ScriptProperty -Value {
            if ($this.Extensions | Where-Object { $_.Oid.Value -eq '2.5.29.17' }) {
              $this.Extensions['2.5.29.17'].Format($false)
            }
          } -PassThru |
          Add-Member EnhancedKeyUsages -MemberType ScriptProperty -Value {
            if ($this.Extensions | Where-Object { $_.Oid.Value -eq '2.5.29.37' }) {
              $this.Extensions['2.5.29.37'].EnhancedKeyUsages |
                ForEach-Object {
                  $_ | Add-Member ToString -MemberType ScriptMethod -Force -Value {
                    "$($this.Value) ($($this.FriendlyName))"
                  }
                  
                  $_
              }
            }
          } -PassThru |
          Where-Object $WhereStatement
          
        $Store.Close()
      }
    }
  }

Open in new window

Chris
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

In this previous article (https://oddytee.wordpress.com/2016/05/05/provision-new-office-365-user-and-mailbox-from-exchange-hybrid-via-powershell/), we made basic license assignments to users in O365. When I say basic, the method is the simplest way …
"Migrate" an SMTP relay receive connector to a new server using info from an old server.
This tutorial will walk an individual through the steps necessary to join and promote the first Windows Server 2012 domain controller into an Active Directory environment running on Windows Server 2008. Determine the location of the FSMO roles by lo…
This tutorial will walk an individual through the process of transferring the five major, necessary Active Directory Roles, commonly referred to as the FSMO roles to another domain controller. Log onto the new domain controller with a user account t…

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now