How To Setup EZCA ACME Agent

Prerequisites

  1. Register Agent in EZCA

Introduction - Setup Internal ACME Agent To Issue Certificates To Your Local Network

For EZCA to validate the local domain ownership, we have to install a local agent in your network. This web service will receive all ACME request and validate the domain ownership on behalf of EZCA. In this step we will set up the agent.

How To Setup The Server

Install IIS Windows feature

In a Windows Server open an Administrator PowerShell window and run the following command:

Install-WindowsFeature -name Web-Server -IncludeManagementTools

Instal Web deploy

Once IIS is installed, download web-deploy from the official Microsoft site and open the installer.

  1. Once the installer is open, click next on the first page.
  2. Read and accept terms and conditions.
  3. On the next page click “Complete” IIS Setup
  4. Click “Install”

Install .NET Hosting Bundle

  1. Download the latest .NET hosting bundle from Microsoft.
  2. Click Install.

How To Setup The ACME Agent Certificate

Creating and Installing ACME Certificate

The ACME Agent requires a certificate to authenticate to EZCA. This certificate will be automatically rotated by the health API, meaning once it is setup, you will not have to manually renew it.

The certificate must be issued by the CA that this ACME agent will be connected to.

  1. Navigate to Domains. Domains Menu
  2. Click the “Request Certificate” button on the domain you set in your agent registration. Domains Menu
  3. This will pre-populate the Subject Name and Subject Alternate Names with the selected domain. Create Certificate in EZCA
  4. If this certificate requires more subject alternate names (Usually for other domains that might use this certificate), add them in the DNS Names section.
  5. By Default, EZCA will request the certificate to be the maximum validity allowed by your administrators. If you want to decrease the lifetime of the certificate, adjust the validity slider.
  6. Make sure the “Import CSR” Option is Selected. Import CSR
  7. Click the “How to create a CSR Locally” Link. Create Certificate
  8. Select Windows Create Certificate
  9. Download the .inf file Create Certificate
  10. Edit the the following values in the .inf file:
    Exportable = FALSE
    MachineKeySet = TRUE
    
  11. open cmd.exe as an Administrator
  12. Navigate to your downloads folder and run the following command where INFFILENAME is the file name you just downloaded and CSRFILENAME is the file where you want the certificate signing request to be saved:
    certreq.exe -new <INFFILENAME>.inf <CSRFILENAME>.csr
    
  13. Go Back to the EZCA portal.
  14. Close out the instructions dialog.
  15. Click on the “Upload CSR” button. Create Certificate
  16. Select the newly created CSR file Create Certificate
  17. Click the “Request Certificate” button at the top right of the form. Create Certificate
  18. Your Certificate has been created successfully. Create Certificate
  19. Download the certificate.
  20. Open the downloaded certificate.
  21. Click “Install Certificate” Create Certificate
  22. Select Local Machine. Create Certificate
  23. Follow the wizard to install this certificate in the local computer store.

How To Create the ACME CA Agent Site

Next we have to create the site in IIS, to do this run the following script replacing the variables:

  1. certificateSubject The subject Name of the SSL Certificate for your Site.

    This certificate must be different than the certificate we just created for authentication. As previously mentioned, the authentication certificate is automatically managed by EZCA and IIS binding will not be updated.

  2. acmeCertificateSubject The subject Name of the SSL Certificate we created in the previous step to authenticate with EZCA.
  3. appInsights The connection string for the application insights where you want this agent to report the telemetry.
  4. agentURL The URL where computers on your network can find this agent.

    You can download the signed version of this script from here

#usage .\InstallIISSite.ps1  -iisAppPoolName "YOURPOOLNAME" -iisAppName = "SITENAME" -directoryPath "PATHTOSITEFILES" -certificateSubject 'YOUR SSL CERTIFICATE SUBJECT' -acmeCertificateSubject 'SSL Certificate Subject name for Authentication with EZCA' -appInsights "YOUR APP Insights Key" -agentURL "https://acmeagent.same.domain/"
param ($iisAppPoolName = "ezcaACMEPool", $iisAppName = "ezcaACME", $directoryPath = "C:\ezcaACME",
 $certificateSubject, $acmeCertificateSubject, $appInsights,  $agentURL)
Import-Module WebAdministration


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
}

if($null -eq $acmeCertificateSubject -or  $acmeCertificateSubject  -eq '')
{
    Write-Host "Error: No EZCA certificate subject provided. Please provide a valid certificate subject name" -ForegroundColor Red
    exit 1
}
if($null -eq $agentURL -or  $agentURL  -eq '')
{
    Write-Host "Error: No Agent URL provided, please provide the DNS name for this agent" -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 | Set-ItemProperty -Name "managedRuntimeVersion" -Value "" 
}

#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
if ((Test-Path $directoryPath -pathType container) -eq $false)
{
    New-Item -Path $directoryPath -ItemType Directory
}
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://download.keytos.io/Downloads/EZCAACME/ACMEAgent.zip  -OutFile ezcaAgent.zip
Expand-Archive -LiteralPath ezcaAgent.zip -DestinationPath $directoryPath
$webAppSettings = Get-Content -Raw -Path "$($directoryPath)\appsettings.json" 
$webAppSettings = $webAppSettings.Replace('$SUBJECTNAME$', $acmeCertificateSubject).Replace('$AGENTURL$',$agentURL).Replace('$APPINSIGHTS_CONNECTION_STRING$',$appInsights)
$webAppSettings | Out-File -FilePath "$($directoryPath)\appsettings.json" -Force
Remove-Item -Path ezcaAgent.zip
  1. Verify the site is up by going to https://YourSite/api/Health/Overall Agent Health
  2. Once the agent is up and running you are ready to start requesting ACME certificates.

Troubleshooting

Below you will find common exceptions or errors and how to fix them

Domain Validation Failure

ACME validation is carried out through DNS, ensure that the ACME Server has http access into the server requesting the certificate.

Exception ‘Keyset does not exist’

If when creating a new ACME account the request fails with an internal server error and when looking at the Application Insights you see a Cryptographic Exception “Keyset does not exist” this means that the identity running the application pool in IIS does not have permission to read the certificate’s private key. Please ensure that the Application’s pool identity has the correct permissions.

Certificate Not Being Available When Calling The Test API

If when calling the test API you get an error that the certificate is not available, and you have verified that it is in the right store and that the application running the pool in IIS (by default IIS_IUSRS) has permission to the certificate, make sure that the certificate chain (including the root certificate) is in the trusted root store.