Public/Get-PACertificate.ps1

function Get-PACertificate {
    [CmdletBinding()]
    [OutputType('PoshACME.PACertificate')]
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText','')]
    param(
        [Parameter(ParameterSetName='Specific',Position=0,ValueFromPipeline,ValueFromPipelineByPropertyName)]
        [string]$MainDomain,
        [Parameter(ParameterSetName='Specific',ValueFromPipelineByPropertyName)]
        [ValidateScript({Test-ValidFriendlyName $_ -ThrowOnFail})]
        [string]$Name,
        [Parameter(ParameterSetName='List',Mandatory)]
        [switch]$List
    )

    Begin {
        # Make sure we have an account configured
        if (-not (Get-PAAccount)) {
            try { throw "No ACME account configured. Run Set-PAAccount or New-PAAccount first." }
            catch { $PSCmdlet.ThrowTerminatingError($_) }
        }

        # prep to calculate SHA1 thumbprints
        $sha1 = [Security.Cryptography.SHA1CryptoServiceProvider]::new()
    }

    Process {

        # since the params in this function are a subset of the params for Get-PAOrder, we're
        # just going to pass them directly to it to get order(s) associated with the certificates
        Get-PAOrder @PSBoundParameters | ForEach-Object {

            $order = $_
            $certFile = Join-Path $order.Folder 'cert.cer'

            # skip if if there's no cert file
            if (-not (Test-Path $certFile -PathType Leaf)) {
                return
            }

            # import the cert
            $cert = Import-Pem -InputFile $certFile

            # build the list of SANs
            $altNames = $cert.GetSubjectAlternativeNames() | ForEach-Object {
                if ($_[0] -eq [Org.BouncyCastle.Asn1.X509.GeneralName]::DnsName) {
                    # second index is the actual DNS name
                    $_[1]
                }
                elseif ($_[0] -eq [Org.BouncyCastle.Asn1.X509.GeneralName]::IPAddress) {
                    # second index is a IP hex string like "#01010101" that we need to parse
                    ([ipaddress]([byte[]] -split ($_[1].Substring(1) -replace '..', '0x$& '))).ToString()
                }
            }

            # convert the PfxPass to a securestring
            if ($order.PfxPass) {
                $secPfxPass = ConvertTo-SecureString $order.PfxPass -AsPlainText -Force
            } else {
                $secPfxPass = [Security.SecureString]::new()
            }

            # send the output object to the pipeline
            [pscustomobject]@{
                PSTypeName = 'PoshACME.PACertificate'

                # add the literal subject rather than just the domain name
                Subject = $cert.SubjectDN.ToString()

                # PowerShell's cert:\ provider outputs these in local time, but BouncyCastle
                # outputs in UTC. So we'll convert so they match
                NotBefore = $cert.NotBefore.ToLocalTime()
                NotAfter  = $cert.NotAfter.ToLocalTime()

                KeyLength = $order.KeyLength

                # the thumbprint is a SHA1 hash of the DER encoded cert which is not actually
                # stored in the cert itself
                Thumbprint = [BitConverter]::ToString($sha1.ComputeHash($cert.GetEncoded())).Replace('-','')

                # add the full list of SANs
                AllSANs = @($altNames)

                # add the associated file paths whether they exist or not
                CertFile      = Join-Path $order.Folder 'cert.cer'
                KeyFile       = Join-Path $order.Folder 'cert.key'
                ChainFile     = Join-Path $order.Folder 'chain.cer'
                FullChainFile = Join-Path $order.Folder 'fullchain.cer'
                PfxFile       = Join-Path $order.Folder 'cert.pfx'
                PfxFullChain  = Join-Path $order.Folder 'fullchain.pfx'

                PfxPass = $secPfxPass
            }

        }

    }





    <#
    .SYNOPSIS
        Get ACME certificate details.
 
    .DESCRIPTION
        Returns details such as Thumbprint, Subject, Validity, SANs, and file locations for one or more ACME certificates previously created.
 
    .PARAMETER MainDomain
        The primary domain associated with the certificate. This is the domain that goes in the certificate's subject.
 
    .PARAMETER Name
        The name of the ACME order. This can be useful to distinguish between two orders that have the same MainDomain.
 
    .PARAMETER List
        If specified, the details for all completed certificates will be returned for the current account.
 
    .EXAMPLE
        Get-PACertificate
 
        Get cached ACME order details for the currently selected order.
 
    .EXAMPLE
        Get-PACertificate site.example.com
 
        Get cached ACME order details for the specified domain.
 
    .EXAMPLE
        Get-PACertificate -List
 
        Get all cached ACME order details.
 
    .LINK
        Project: https://github.com/rmbolger/Posh-ACME
 
    .LINK
        New-PACertificate
 
    #>

}