Setup EZCA ADCS Agent

Prerequisites

  1. Setup IIS
  2. Create Certificate Templates In CA

Introduction

For EZCA to connect to your ADCS CAs it is required for a domain joined machine to run the EZCA certificate agent web service. This web service receives authenticated requests from EZCA and then requests the certificate on behalf of EZCA. In this page we will set up the Agent, from registering the gMSA to getting the Agent operational. CA Agent

Creating the gMSA

To have a fully password-less infrastructure we recommend having a gMSA (Group Managed Service Accounts) as the domain identity for the EZCA agent. Fist the domain admin has to create the gMSA by running the following commands (where ezcagMSA is the name of the gMSA. agent.yourdmoain is the DNS name of your agent, and ezcaAgents is the domain group that the agent is part of):

You can add all the agents to the same gMSA by adding them to the group that has access to the password.

Add-KdsRootKey -EffectiveImmediately
#wait 10 hours (this is made by Microsoft to ensure replication, for test environment you can bypass with Add-KdsRootKey –EffectiveTime ((get-date).addhours(-10))   
#Ref https://social.technet.microsoft.com/Forums/ie/en-US/82617035-254f-4078-baa2-7b46abb9bb71/newadserviceaccount-key-does-not-exist?forum=winserver8gen
New-ADServiceAccount -Name ezcagMSA -DNSHostName agent.yourdmoain -KerberosEncryptionType AES256 -PrincipalsAllowedToRetrieveManagedPassword ezcaAgents

Registering the gMSA in the Agent

In each agent we have to register the gMSA, to do this we fist have to install the AD-Domain-Services PowerShell Modules and restarting the computer by running:

Get-WindowsFeature AD-Domain-Services
Install-WindowsFeature AD-DOMAIN-SERVICES
Restart-Computer

After the computer is restarted we add the gMSA and test, that is working by running these two commands:

$gmsaName = 'ezcagMSA'
Install-AdServiceAccount $gmsaName 
Test-AdServiceAccount $gmsaName

Creating the Site

Next we have to create the site in IIS, to do this run the following script replacing the variables with your gMSA name and certificate subject name:

You can download the signed version of this script from here

#usage .\InstallIISSite.ps1  -iisAppPoolName "YOURPOOLNAME" -iisAppName = "SITENAME" -directoryPath "PATHTOSITEFILES" -gMSAName 'YOURDOMAIN\ezcagMSA$' -certificateSubject 'YOUR SSL CERTIFICATE SUBJECT' -appInsights "YOUR APP Insights Key" -testTemplate "ADCS Test Template"
param ($iisAppPoolName = "ezcaPool", $iisAppName = "ezca", $directoryPath = "C:\ezca",
$gMSAName, $certificateSubject, $appInsights,  $testTemplate = "EZCATestTemplate")
Import-Module WebAdministration

if($null -eq $gMSAName -or $gMSAName -eq '')
{
    Write-Host "Error: No gMSA name provided. Please provide a valid gMSA name Format: domain\gMSA$" -ForegroundColor Red
    exit 1
}
if($null -eq $certificateSubject -or  $certificateSubject  -eq '')
{
    Write-Host "Error: No certificate subject provided. Please provide a valid certificate subject name" -ForegroundColor Red
    exit 1
}
$directoryPath = $directoryPath.TrimEnd('\')
$originalPath = Get-Location
#navigate to the app pools root
cd IIS:\AppPools\

#check if the app pool exists
if (!(Test-Path $iisAppPoolName -pathType container))
{
    #create the app pool
    $appPool = New-Item $iisAppPoolName
    $appPool.processModel.userName = $gMSAName 
    $appPool | Set-ItemProperty -Name "managedRuntimeVersion" -Value "" 
    Set-ItemProperty IIS:\AppPools\$iisAppPoolName -name processModel.identityType -Value SpecificUser 
    Set-ItemProperty IIS:\AppPools\$iisAppPoolName -name processModel.userName -Value $gMSAName

}

#navigate to the root of the site
cd IIS:\Sites\

#check if the site exists
if (Test-Path $iisAppName -pathType container)
{
    return
}
$cert = (Get-ChildItem cert:\LocalMachine\My   | where-object { $_.Subject -like "*$certificateSubject*" }  | Select-Object -First 1).Thumbprint
if($null -eq $cert -or $cert -eq '')
{
    Write-Host "Error: No certificate found for the provided certificate subject. Please provide a valid certificate subject name, and make sure your certificate is in the the following cert store: Cert:\LocalMachine\My" -ForegroundColor Red
    exit 1
}
#create the site
Start-IISCommitDelay
$TestSite =New-IISSite -Name $iisAppName -PhysicalPath  $directoryPath  -BindingInformation "*:443:" -CertificateThumbPrint $cert -CertStoreLocation "Cert:\LocalMachine\My" -Protocol https -Passthru
$TestSite.Applications["/"].ApplicationPoolName =$iisAppPoolName
Stop-IISCommitDelay

# Download Site
cd $originalPath 
Invoke-WebRequest -Uri https://www.keytos.io/Downloads/WindowsAgentWeb/EZCAAgent.zip  -OutFile ezcaAgent.zip
Expand-Archive -LiteralPath ezcaAgent.zip -DestinationPath $directoryPath
$webAppSettings = Get-Content -Raw -Path "$($directoryPath)\appsettings.json" 
$webAppSettings = $webAppSettings.Replace('$SUBJECTNAME$', $gMSAName.Split('\')).Replace("EZCATestTemplate",$testTemplate).Replace('$GMSA$', $gMSAName.Replace("\","\\")).Replace('$APPINSIGHTS_CONNECTION_STRING$',$appInsights)
$webAppSettings | Out-File -FilePath "$($directoryPath)\appsettings.json" -Force
Remove-Item -Path ezcaAgent.zip

Creating the Agent Certificate

Once the site is set up, the last step before testing it is creating the gMSA’s agent certificate. This certificate is used to sign each request for the CA to issue the certificate to the agent on behalf of the user/computer requesting the certificate. To do this, an automated task periodically rotates certificates to mitigate the risk of certificate expiration related outages.

This Certificate will have very similar permissions to a PKI administrator. We strongly recommend having the private key of this certificate protected by an HSM. This example will use the native crypto provider to ensure compatibility with most set ups.

  1. First, Download the Agent Certificate Requester Binary.
  2. Once downloaded, replace the variables with your environments information and run the following from a PowerShell window with administrator rights:
    $gmsaName = 'DOMAIN\GMSANAME$'
    $caName = "CA.DNS\CA NAME"
    $pathToBinary = 'c:\ezcaTools\AgentCertificateRequester.exe'
    $templateName = "YOURTEMPLATENAME"
    $cryptoProvider = "Microsoft Enhanced Cryptographic Provider v1.0"
    $appInsightsKey = "" #(Optional) Enter App Insights Key to receive alerts on errors during runs
    ## Do Not Change Below This Line
    $gmsaShort = $gmsaName.Split('\')[1]
    $logsPath = $pathToBinary.Replace('AgentCertificateRequester.exe','logs.txt')
    $action = New-ScheduledTaskAction -Execute 'PowerShell.exe' -Argument "$($pathToBinary) -ca $($caName) --userName $($gmsaShort) -t $($templateName) -ai $($appInsightsKey) -c $($cryptoProvider)| Out-File -FilePath $($logsPath)"
    $trigger = New-ScheduledTaskTrigger -At 11:00 -Weekly -WeeksInterval 3 -DaysOfWeek Monday
    $principal = New-ScheduledTaskPrincipal -UserID $gmsaName -LogonType Password
    Register-ScheduledTask ezCACertRotation -Action $action -Trigger $trigger -Principal $principal
    
  3. After setting up the task, open task manager and verify that it has successfully run and the certificate has been created.