Functions/CertificateManagement/Get-FpsCertificate.ps1
<#
.SYNOPSIS Returns all installed certificates that matches with the given ThumbPrint or SubjectFilter. .DESCRIPTION Default this cmdlet searches for certificates that have a private key. Enable IncludePublicCertificates to search for certificates with only a public key too. .EXAMPLE Get-FpsCertificate -ReturnCertObject .EXAMPLE Get-FpsCertificate -ThumbPrint '008CEE1FEA5RANDOM2AF4F603EBPRINTBB0341D1' .EXAMPLE Get-FpsCertificate -CertificatePath 'cert:\CurrentUser\My' -SubjectFilter 'MySubject*' -IncludePublicCertificates #> function Get-FpsCertificate { [CmdletBinding(DefaultParameterSetName='SearchWithSubjectFilter')] param( # The certificate unique thumbprint [Parameter(Mandatory=$true, ParameterSetName='SearchWithThumbPrint', ValueFromPipelineByPropertyName=$true, ValueFromPipeline=$true)] [ValidatePattern('^[a-zA-Z\d]+$')] [string] $ThumbPrint, # A subject filter to find certificates. E.g. 'MySubject*' returns all certificates where the subject starts with 'MySubject'. # Default value is: '*4ps*' [Parameter(ParameterSetName='SearchWithSubjectFilter', ValueFromPipelineByPropertyName=$true)] [string] $SubjectFilter = '*4ps*', # The certificate provider path where to scan for certificates. Path should start with 'Cert:'. E.g. 'cert:\LocalMachine\WebHosting'. # Default value is: 'cert:\LocalMachine\My' [Parameter(ValueFromPipelineByPropertyName=$true)] [string] $CertStorePath = 'cert:\LocalMachine\My', # When enabled this cmdlet returns the X509Certificate2 certificate object instead of a new powershell object. # Note: When enabled additional properties like UsedOnIISWebSites and UsedOnBcServerInstances are not added on the returned object anymore. [Parameter(ValueFromPipelineByPropertyName=$true)] [switch] $ReturnCertObject, # Enable IncludePublicCertificates to search for Public and Private installed certificates. [Parameter(ValueFromPipelineByPropertyName=$true)] [switch] $IncludePublicCertificates ) if(-not [string]::IsNullOrEmpty($ThumbPrint)){ $certificates = Get-ChildItem -path $CertStorePath | Where-Object -Property Thumbprint -eq $ThumbPrint } else { $certificates = Get-ChildItem -path $CertStorePath | Where-Object subject -like $SubjectFilter } if(-not $IncludePublicCertificates){ $certificates = $certificates | Where-Object -Property HasPrivateKey -eq $true } $certificates = $certificates | Where-Object -Property FriendlyName -ne '' if($ReturnCertObject){ return $certificates } $bcServerInstances = Get-BCServerInstance $bcServerInstances | ForEach-Object {$_.AppSettings = New-Object psobject -Property $_.AppSettings} # work-around: Convert hashtable to psobject $WebSites = Get-Website foreach ($certificate in $certificates){ # Add IIS WebSite names to certificate object where the certificate is used in the https bindings $WebSitesWithCertBinding = $WebSites | ForEach-Object { foreach ($binding in $_.bindings.Collection){ if($binding.protocol -eq 'https' -and $binding.certificateHash -eq $certificate.Thumbprint){ $_ } } } $certificate | Add-Member -NotePropertyName 'UsedOnIISWebSites' -NotePropertyValue $WebSitesWithCertBinding.Name # Add Business Central ServerInstances names to certificate object where the certificate is used $certificate | Add-Member -NotePropertyName 'UsedOnBcServerInstances' -NotePropertyValue ` ($bcServerInstances | Where-Object {$_.AppSettings.ServicesCertificateThumbprint -eq $certificate.Thumbprint}).ServerInstance # Add users to certificate object with Read access on the certificate Write-Verbose 'Searching for users with read access on the previous certificate...' $CertPath = '{0}\Microsoft\Crypto\RSA\MachineKeys\{1}' -f $env:ALLUSERSPROFILE, [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey((Get-FpsCertificate -ThumbPrint $certificate.Thumbprint -ReturnCertObject)).key.UniqueName Write-Verbose ('Certificate path for certificate ''{0}'': {1}' -f $certificate.Thumbprint, $CertPath) $certificate | Add-Member -NotePropertyName 'UsersWithReadAccess' -NotePropertyValue ` ((Get-Acl -Path $CertPath).Access | Where-Object {$_.AccessControlType -eq 'Allow' -and $_.FileSystemRights -match 'FullControl|Read' -and $_.IdentityReference -notlike 'S-*'}).IdentityReference.Value # Add expiration information to certificate object $certificate | Add-Member -NotePropertyName 'IsExpired' -NotePropertyValue ($certificate.NotAfter -lt (Get-Date)) $DaysToExpiration = ($certificate.NotAfter - (Get-Date)).Days if([double]$DaysToExpiration -lt 0){$DaysToExpiration = 0} $certificate | Add-Member -NotePropertyName 'DaysToExpiration' -NotePropertyValue $DaysToExpiration } # Converts X509Certificate2 to PSCustom objects and select most usefull properties return $certificates | Select-Object FriendlyName, Subject, Thumbprint, Issuer, HasPrivateKey, NotBefore, NotAfter, DaysToExpiration, IsExpired, UsedOnIISWebSites, UsedOnBcServerInstances, UsersWithReadAccess } Export-ModuleMember -Function Get-FpsCertificate |