Select-PKICertificate.ps1


<#PSScriptInfo
 
.VERSION 1.0
 
.GUID f9b1b1cc-dac7-4371-8de1-0477f1c7887b
 
.AUTHOR Marc Collins
 
.COMPANYNAME
 
.COPYRIGHT
 
.TAGS
 
.LICENSEURI
 
.PROJECTURI
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
 
#>


<#
 
.DESCRIPTION
 Select-PKICertificate will look at the Requested Certificate Store and Prompt the User to Select a Certificate based on KeyUsage Requirements
Default KeyUsage of KeyEncipherment if parameter if not selected.
 
#>
 

Param()


<#
    .NOTES
    ===========================================================================
     Created on: 8/11/2017 9:49 AM
     Created by: Marc Collins
     Filename: Select-PKICertificate.ps1
    ===========================================================================
    .DESCRIPTION
        Finds a Certificate based on the Requested KeyUsage.
         
#>


function Select-PKICertificate
{
<#
    .SYNOPSIS
        Prompts User to select a certificate
     
    .DESCRIPTION
        Select-PKICertificate will look at the Requested Certificate Store and Prompt the User to Select a Certificate based on KeyUsage Requirements
        Default KeyUsage of KeyEncipherment if parameter if not selected.
     
    .PARAMETER ComputerCertificate
        The ComputerCertificate parameter tells the function to look at the Computer Certificate Store, else it will use the User Store
 
    .PARAMETER KeyUsage
        The Dynamic parameter KeyUsage is used to select the Type of Certificate to find.
        Default Value for this paramater is KeyEncipherment
     
    .EXAMPLE
        PS C:\> Select-PKICertificate
            Will present any Certificate in the User Store with the Default KeyUsage of KeyEncipherment
 
    .EXAMPLE
        PS C:\> Select-PKICertificate -KeyUsage DigitalSignature
            Will present any Certificate in the User Store with the KeyUsage of DigitalSignature
    .EXAMPLE
        PS C:\> Select-PKICertificate -ComputerCertificate
            Will present any Certificate in the Computer Store with the Default KeyUsage of KeyEncipherment
    .EXAMPLE
        PS C:\> Select-PKICertificate -ComputerCertificate -KeyUsage EncipherOnly
            Will present any Certificate in the Computer Store with the Default KeyUsage of EncipherOnly
 
#>

    
    [CmdletBinding(ConfirmImpact = 'Low',
                   SupportsPaging = $false)]
    param
    (
        [Parameter(Mandatory = $false,
                   Position = 1)]
        [switch]$ComputerCertificate
    )
    
    DynamicParam
    {
        # Set the dynamic parameters name
        $ParameterName = 'KeyUsage'
        # Create the dictionary
        $RuntimeParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
        # Create the collection of attributes
        $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
        # Create and set the parameters' attributes
        $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute
        $ParameterAttribute.ValueFromPipeline = $true
        $ParameterAttribute.ValueFromPipelineByPropertyName = $true
        $ParameterAttribute.Mandatory = $false
        $ParameterAttribute.Position = 0
        # Add the attributes to the attributes collection
        $AttributeCollection.Add($ParameterAttribute)
        # Generate and set the ValidateSet
        $arrSet = [Enum]::GetNames([System.Security.Cryptography.X509Certificates.X509KeyUsageFlags])
        $ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($arrSet)
        # Add the ValidateSet to the attributes collection
        $AttributeCollection.Add($ValidateSetAttribute)
        # Create and return the dynamic parameter
        $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($ParameterName, [string], $AttributeCollection)
        $RuntimeParameterDictionary.Add($ParameterName, $RuntimeParameter)
        return $RuntimeParameterDictionary
    }
    
    begin
    {
        #If the Dynamic KeyUsage Paramater was not used, set the default value
        if (!$psBoundParameters.ContainsKey('KeyUsage'))
        {
            $PSBoundParameters.KeyUsage = "KeyEncipherment"
        }
        
        $KeyUsage = $PSBoundParameters.KeyUsage
        
        if ($ComputerCertificate.IsPresent)
        {
            $KeyStore = "Computer"
        }
        else
        {
            $KeyStore = "User"
        }
        
        Function Test-ElevatedCredential
        {
            $wid = [System.Security.Principal.WindowsIdentity]::GetCurrent()
            $prp = new-object System.Security.Principal.WindowsPrincipal($wid)
            $adm = [System.Security.Principal.WindowsBuiltInRole]::Administrator
            $IsAdmin = $prp.IsInRole($adm)
            return $IsAdmin
        }
        try
        {
            Add-Type -AssemblyName System.Security
            $CertificateCollection = [System.Security.Cryptography.X509Certificates.X509Certificate2Collection]::new()
        }
        catch
        {
            break
        }
    }
    
    process
    {
        if ($KeyStore -eq "Computer")
        {
            if (Test-ElevatedCredential)
            {
                $CertsComputerKey = Get-ChildItem Cert:\LocalMachine\My -Recurse | Where-Object { $(($_.Extensions.KeyUsages -split (",")).Trim()) -contains $KeyUsage }
                $CertsComputerKey | %{ $CertificateCollection.Add($_) } | Out-Null
            }
            else
            {
                Write-Warning "Not Running with Elevated Credentials, Computer Store is Unavailable."
                break
            }
        }
        if ($KeyStore -eq "User")
        {
            $CertsUserKey = Get-ChildItem Cert:\CurrentUser\My -Recurse | Where-Object { $(($_.Extensions.KeyUsages -split (",")).Trim()) -contains $KeyUsage }
            $CertsUserKey | %{ $CertificateCollection.Add($_) } | Out-Null
        }
    }
    end
    {
        if ($CertificateCollection.Count -gt 0)
        {
            $SelectionFlag = [System.Security.Cryptography.X509Certificates.X509SelectionFlag]::SingleSelection
            $Selected = [System.Security.Cryptography.X509Certificates.X509Certificate2UI]::SelectFromCollection($CertificateCollection, "Select", "Title", $SelectionFlag)
            return $Selected
        }
        else
        {
            Write-Warning -Message "No Certificates in the $($KeyStore) Store Matched the Selected KeyUsage: $($KeyUsage)"
            return $null
        }
    }
}