PkiHelper/Public/Get-Certificate2.ps1
function Get-Certificate2 { [cmdletBinding(DefaultParameterSetName = 'FindCer')] param ( [Parameter(Mandatory = $true, ParameterSetName = 'FindCer')] [Parameter(Mandatory = $true, ParameterSetName = 'FindPfx')] [string]$SearchString, [Parameter(Mandatory = $true, ParameterSetName = 'FindCer')] [Parameter(Mandatory = $true, ParameterSetName = 'FindPfx')] [System.Security.Cryptography.X509Certificates.X509FindType]$FindType, [Parameter(ParameterSetName = 'AllCer')] [Parameter(ParameterSetName = 'AllPfx')] [Parameter(ParameterSetName = 'FindCer')] [Parameter(ParameterSetName = 'FindPfx')] [System.Security.Cryptography.X509Certificates.CertStoreLocation]$Location, [Parameter(ParameterSetName = 'AllCer')] [Parameter(ParameterSetName = 'AllPfx')] [Parameter(ParameterSetName = 'FindCer')] [Parameter(ParameterSetName = 'FindPfx')] [string]$Store, [Parameter(ParameterSetName = 'AllCer')] [Parameter(ParameterSetName = 'AllPfx')] [Parameter(ParameterSetName = 'FindCer')] [Parameter(ParameterSetName = 'FindPfx')] [string]$ServiceName, [Parameter(Mandatory = $true, ParameterSetName = 'AllCer')] [Parameter(Mandatory = $true, ParameterSetName = 'AllPfx')] [switch]$All, [Parameter(ParameterSetName = 'AllCer')] [Parameter(ParameterSetName = 'AllPfx')] [switch]$IncludeServices, [Parameter(Mandatory = $true, ParameterSetName = 'FindPfx')] [Parameter(Mandatory = $true, ParameterSetName = 'AllPfx')] [securestring]$Password, [Parameter(ParameterSetName = 'FindPfx')] [Parameter(ParameterSetName = 'AllPfx')] [switch]$ExportPrivateKey ) $services = Get-Service if ($ServiceName -and $Location -ne 'CERT_SYSTEM_STORE_SERVICES') { $Location = 'CERT_SYSTEM_STORE_SERVICES' } if ($ServiceName -and $ServiceName -notin $services.Name) { Write-Error "The service '$ServiceName' could not be found." return } $storeProvider = [System.Security.Cryptography.X509Certificates.CertStoreProvider]::CERT_STORE_PROV_SYSTEM $certs = foreach ($currentLocation in [Enum]::GetNames([System.Security.Cryptography.X509Certificates.CertStoreLocation])) { if ($Location -and $Location -ne $currentLocation) { Write-Verbose "Skipping location '$currentLocation'" continue } Write-Verbose "Enumerating stores location '$currentLocation'" $internalLocation = [System.Security.Cryptography.X509Certificates.CertStoreLocation]$currentLocation -bor [System.Security.Cryptography.X509Certificates.CertOpenStoreFlags]::CERT_STORE_READONLY_FLAG $availableStores = if ($ServiceName) { [System.Security.Cryptography.X509Certificates.Win32]::GetServiceCertificateStores($ServiceName) } elseif ($Location -eq [System.Security.Cryptography.X509Certificates.CertStoreLocation]::CERT_SYSTEM_STORE_SERVICES) { $services = Get-Service foreach ($Service in $services) { [System.Security.Cryptography.X509Certificates.Win32]::GetServiceCertificateStores($service.Name) } } else { [System.Security.Cryptography.X509Certificates.Win32]::GetCertificateStores() } $availableStores = if ($Location -eq [System.Security.Cryptography.X509Certificates.CertStoreLocation]::CERT_SYSTEM_STORE_CURRENT_USER) { $availableStores | Where-Object Location -eq CurrentUser } elseif ($Location -eq [System.Security.Cryptography.X509Certificates.CertStoreLocation]::CERT_SYSTEM_STORE_LOCAL_MACHINE) { $availableStores | Where-Object Location -eq LocalMachine } elseif ($Location -eq [System.Security.Cryptography.X509Certificates.CertStoreLocation]::CERT_SYSTEM_STORE_LOCAL_MACHINE) { $availableStores | Where-Object Location -eq LocalMachine } elseif ($Location -eq [System.Security.Cryptography.X509Certificates.CertStoreLocation]::CERT_SYSTEM_STORE_SERVICES) { $availableStores | Where-Object Location -eq Services } elseif ($Location -eq [System.Security.Cryptography.X509Certificates.CertStoreLocation]::CERT_SYSTEM_STORE_USERS) { $availableStores | Where-Object Location -eq Users } elseif ($Location -eq [System.Security.Cryptography.X509Certificates.CertStoreLocation]::CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY) { $availableStores | Where-Object Location -eq CurrentUserGroupPolicy } elseif ($Location -eq [System.Security.Cryptography.X509Certificates.CertStoreLocation]::CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY) { $availableStores | Where-Object Location -eq LocalMachineGroupPolicy } elseif ($Location -eq [System.Security.Cryptography.X509Certificates.CertStoreLocation]::CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE) { $availableStores | Where-Object Location -eq LocalMachineEnterprise } else { $availableStores } if ($Store) { if ($ServiceName) { if ("$ServiceName\$Store" -notin $availableStores.Name) { Write-Error "The store '$Store' does not exist for location '$currentLocation' for service '$ServiceName'" continue } else { $availableStores = $availableStores | Where-Object Name -eq "$ServiceName\$Store" } } else { if ($Store -notin $availableStores.Name) { Write-Error "The store '$Store' does not exist for location '$currentLocation'" continue } else { $availableStores = $availableStores | Where-Object Name -eq $Store } } } foreach ($storePath in $availableStores) { Write-Verbose "Enumerating certificates in store '$storePath' in location '$currentLocation'" $storePtr = [System.Security.Cryptography.X509Certificates.Win32]::CertOpenStore($storeProvider, 0, 0, $internalLocation, $storePath.Name) if ($storePtr -eq [System.IntPtr]::Zero) { Write-Verbose "Store '$storePath' in location '$currentLocation' could not be opened." continue } $s = New-Object System.Security.Cryptography.X509Certificates.X509Store($storePtr) $result = if ($All) { $s.Certificates } else { $s.Certificates.Find($FindType, $SearchString, $false) } foreach ($item in $result) { $item | Add-Member -MemberType NoteProperty -Name Location -Value $currentLocation $item | Add-Member -MemberType NoteProperty -Name Store -Value $storePath $item | Add-Member -MemberType NoteProperty -Name Password -Value $plainPassword if ($Location -eq 'CERT_SYSTEM_STORE_SERVICES') { $item | Add-Member -MemberType NoteProperty -Name ServiceName -Value ($storePath -split '\\')[0] $item | Add-Member -MemberType NoteProperty -Name Store -Value ($storePath -split '\\')[1] -Force } $item } [void][System.Security.Cryptography.X509Certificates.Win32]::CertCloseStore($storePtr, 0) } } Write-Verbose "Found $($certs.Count) certificates" if ($SearchString -and $certs.Count -eq 0) { Write-Error "No certificate found applying search string '$SearchString' and looking for '$FindType'" return } foreach ($cert in $certs) { $tempFile = [System.IO.Path]::GetTempFileName() Remove-Item -Path $tempFile Write-Verbose "Current certificate is $($cert.Thumbprint)" try { if ($cert.HasPrivateKey -and $ExportPrivateKey) { Write-Verbose 'Calling Export-PfxCertificate' Export-PfxCertificate -Cert $cert -FilePath $tempFile -Password $Password -ErrorAction Stop | Out-Null } else { Write-Verbose 'Calling Export-Certificate' Export-Certificate -Cert $cert -FilePath $tempFile -ErrorAction Stop | Out-Null } Write-Verbose 'Export finished' } catch { if ($SearchString) #A specific cert is desired so an error is written as not in list mode { Write-Error $_ } continue } $certInfo = if ($ExportPrivateKey) { New-Object Pki.Certificates.CertificateInfo($tempFile, $Password) } else { New-Object Pki.Certificates.CertificateInfo($tempFile) } Remove-Item -Path $tempFile $certInfo.ComputerName = $env:COMPUTERNAME $certInfo.Location = $cert.Location $certInfo.Store = $cert.Store.Name $certInfo.ServiceName = $cert.ServiceName $certInfo } } |