Generate-CertificateRequest.ps1

<#PSScriptInfo
 
.VERSION 1.0
 
.GUID 7f18e5ff-6da6-4e3a-940e-7f6f5524f4c5
 
.AUTHOR markreno@microsoft.com
 
.COMPANYNAME
 
.COPYRIGHT
 
.TAGS
 
.LICENSEURI
 
.PROJECTURI
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
 
 
.PRIVATEDATA
 
#>


<#
.SYNOPSIS
Generates a certificate request .inf file as well as a certificate request .req file for a
client authentication certificate whose private key is protected by the Windows Hello for
Business gesture.
 
.DESCRIPTION
Generates a certificate request .inf file as well as a certificate request .req file for a
client authentication certificate whose private key is protected by the Windows Hello for
Business gesture.
 
The private key is stored in the "Microsoft Passport Key Storage Provider"
    
.PARAMETER INFPath
Specifies the file path where the certificate request .inf file will be written
e.g. C:\Temp\CertReq.inf
 
.PARAMETER CSRPath
Specifies the file path where the certificate request .req file will be written
e.g. C:\Temp\CertReq.req
 
.PARAMETER WindowsCA
If specified, indicates the certificate request will be to a Windows Enterprise Certificate
Authority
 
.PARAMETER CertificateTemplate
Only required when WindowsCA is provided. Specifies the certificate template used for the
certificate request
e.g. SCEPCertificate
 
.INPUTS
System.String
Path name for Generates a certificate request .inf file as well as a certificate request .req
file whose private key is protected by the Windows Hello for Business gesture. Optionally the
certificate template name that will be used for the request against a Windows Enterprise
Certificate Authority.
 
.OUTPUTS
None. Request-Certificate.ps1 does not generate any output.
 
.EXAMPLE
C:\PS> .\Generate-CertificateRequest.ps1 -INFPath .\CertReq.inf -CSRPath .\CertReq.req
 
Description
-----------
This command generates the certificate request .inf and .req (CSR) files for a client
authentication certificate whose private key is protected with the Windows Hello for
Business gesture.
 
.EXAMPLE
C:\PS> .\Generate-CertificateRequest.ps1 -INFPath .\CertReq.inf -CSRPath .\CertReq.req -WindowsCA -CertificateTemplate SCEPCertificate
 
Description
-----------
This command generates the certificate request .inf and .req (CSR) files for a client
authentication certificate whose private key is protected with the Windows Hello for
Business gesture.
 
Here the WindowsCA switch indicates that a Windows Enterprise Certificate Authority will be
used and that the certificate template for the request is called "SCEPCertificate".
 
#>


[CmdletBinding(DefaultParametersetName='None')] 
param( 
    [Parameter(Position=0,Mandatory=$false)] [string]$INFPath = "$env:USERDNSDOMAIN\Desktop\WHfBCertificate.inf", 
    [Parameter(Position=1,Mandatory=$false)] [string]$CSRPath = "$env:USERDNSDOMAIN\Desktop\WHfBCertificate.req", 
    [Parameter(ParameterSetName='Extra',Mandatory=$false)][switch]$WindowsCA,      
    [Parameter(ParameterSetName='Extra',Mandatory=$true)][string]$CertificateTemplate
)

# Initialize variables
$UPN = $null
$keyContainer = $null
$Signature = '$Windows NT$'

$template =
@"
[RequestAttributes]
CertificateTemplate = $certificateTemplate
"@


if ($WindowsCA -eq $false)
{
    $template = $null
}

# Check whether this version of Windows will allow use of DSRegCmd.exe
$OSVersoin = ([environment]::OSVersion.Version).major
$OSBuild = ([environment]::OSVersion.Version).Build

if (($OSVersoin -ge 10) -and ($OSBuild -ge 1511)){
    $dsReg = dsregcmd /status    # Retrieve DSRegCmd.exe /status data
}
else{
    # DSRegCmd.exe will not work.
    Write-Output "The device has a Windows down-level OS version." -ForegroundColor Red
    ''
    Write-Output "Recommended action: Run this test on current OS versions e.g. Windows 10, Server 2016 and above." -ForegroundColor Yellow
    ''
    ''
    Write-Output "Script completed successfully." -ForegroundColor Green -BackgroundColor Black
    ''
    ''
    exit
}

# Retrieve the current user's UPN from $dsReg
$exAccName = $dsReg | Select-String "Executing Account Name"
$exAccAliases = (($exAccName.ToString() -split ":")[1].Trim() -split ",")
foreach ($exAccAlias in $exAccAliases)
{
    if ($exAccAlias -like "*@*")
    {
        $UPN = $exAccAlias.Trim()
    }
}
if ($UPN -eq $null)
{
    Write-Output "The UPN for the current user could not be retrieved." -ForegroundColor Red
    ''
    ''
    Write-Output "Script completed successfully." -ForegroundColor Green -BackgroundColor Black
    ''
    ''
    exit
}

# Build the Subject string
$subject = '"' + "CN=$UPN" + '"'

# Build the SAN string
$san = '"' + "UPN=$UPN&" + '"'

# Retrieve the current user's WHfB Key Container from certutil.exe
$certUtl = certutil -user -csp "Microsoft Passport Key Storage Provider" -key
foreach ($certRow in $certUtl)
{
    if ($certRow -like "*$UPN")
    {
        $keyContainer = $certRow.Trim()
    }
}
if ($keyContainer -eq $null)
{
    Write-Output "Windows Hello for Business is not deployed to this device." -ForegroundColor Red
    ''
    ''
    Write-Output "Script completed successfully." -ForegroundColor Green -BackgroundColor Black
    ''
    ''
    exit    
}

# Build certificate request .inf file
$INF =
@"
[Version]
Signature = $Signature
  
[NewRequest]
Subject = $subject
ProviderName = "Microsoft Passport Key Storage Provider"
KeyContainer = $keyContainer
UseExistingKeySet = TRUE
RequestType = PKCS10
 
[EnhancedKeyUsageExtension]
OID = 1.3.6.1.4.1.311.20.2.2 ; Smart Card Logon
OID = 1.3.6.1.5.5.7.3.2 ; Client auth
 
$template
 
[Extensions]
2.5.29.17 = {text}
_continue_ = $san
"@


Write-Output "Certificate Request is being generated"
''
$INF | out-file -filepath $INFPath -force
certreq -new $INFPath $CSRPath
''
Write-Output "Certificate Request has been generated"
''