Skip to main content

AD CS server setup (CES/CEP)

Windows-server-side preparation for CertAutoPilot's AD CS integration: install the CA and the CES/CEP role services with username/password authentication, verify the IIS endpoints, create and publish an enrollment template, and set up a least-privilege service account. Once the server side is ready, configure the CertAutoPilot side on Microsoft AD CS.

Prerequisites

  • Windows Server 2019 or 2022 (Standard or Datacenter).
  • Active Directory Domain Services configured and running; the CA server is domain-joined.
  • Administrator access to the server.
  • A valid TLS certificate for IIS (self-signed is acceptable for testing).

Architecture

CertAutoPilot ──HTTPS──► IIS ──► CES (Certificate Enrollment Web Service)

CEP ◄──────┘ (Certificate Enrollment Policy)


Active Directory
Certificate Services

CertAutoPilot communicates with two Microsoft web services, both hosted on IIS:

  • CEP (Certificate Enrollment Policy) — discovers the certificate templates available to the caller (MS-XCEP).
  • CES (Certificate Enrollment Service) — submits certificate requests (MS-WSTEP).

Authentication is WS-Security UsernameToken inside the SOAP message, over HTTPS.

Step 1 — Install AD CS

Add the role

Open Server Manager → Add Roles and Features:

  1. Select Role-based or feature-based installation and pick your server.
  2. Check Active Directory Certificate Services; add required features when prompted.
  3. Under Role Services, select:
    • Certification Authority (required)
    • Certificate Enrollment Web Service (CES)
    • Certificate Enrollment Policy Web Service (CEP)
  4. Complete the wizard.

Configure the Certification Authority

Click the notification flag in Server Manager → Configure Active Directory Certificate Services:

  1. Credentials — use a Domain Admin account.
  2. Role Services — select Certification Authority.
  3. Setup TypeEnterprise CA (integrates with AD).
  4. CA TypeRoot CA for standalone environments, or Subordinate CA if you have an existing PKI.
  5. Private Key — create a new private key.
  6. Cryptography — RSA 2048 or higher, SHA256.
  7. CA Name — pick a meaningful name (e.g. contoso-ca).
  8. Validity Period — 5–10 years for a Root CA.

Step 2 — Configure CES and CEP

Return to Server Manager → Configure Active Directory Certificate Services, once for each role service:

CES:

  1. Role Services — Certificate Enrollment Web Service.
  2. CA for CES — the CA you just created.
  3. Authentication TypeUser name and password.
  4. Select the IIS SSL certificate if prompted.

CEP:

  1. Role Services — Certificate Enrollment Policy Web Service.
  2. Authentication TypeUser name and password.
  3. Select the same SSL certificate.
warning

The authentication type must be User name and password on both CES and CEP for CertAutoPilot's username/password profile — the client authenticates with a WS-Security UsernameToken inside the SOAP message.

After both are configured, verify in IIS Manager:

Default Web Site
├── <CA-Name>_CES_UsernamePassword ← CES endpoint
└── ADPolicyProvider_CEP_UsernamePassword ← CEP endpoint

Step 3 — Verify IIS

SSL binding

IIS Manager → Default Web Site → Bindings: ensure an HTTPS binding exists on port 443 and the certificate matches the server hostname. Or via PowerShell:

netsh http show sslcert ipport=0.0.0.0:443

Authentication settings

The CES and CEP applications must keep Anonymous Authentication enabled (the default). WCF performs the real authentication at the message level via WS-Security — not at the IIS/HTTP level.

Get-WebConfigurationProperty -PSPath "IIS:\Sites\Default Web Site\<CA-Name>_CES_UsernamePassword" `
-Filter "system.webServer/security/authentication/anonymousAuthentication" -Name enabled
# Should return: True
warning

Do not disable Anonymous Authentication on the UsernamePassword CES/CEP applications. If IIS challenges the request before WCF sees it, enrollment breaks with opaque 401 errors.

Note the endpoint URLs

You will paste these into the CertAutoPilot profile:

ServiceURL pattern
CEShttps://<server>/<CA-Name>_CES_UsernamePassword/service.svc
CEPhttps://<server>/ADPolicyProvider_CEP_UsernamePassword/service.svc
note

CertAutoPilot automatically appends the /CES or /CEP suffix to URLs ending in service.svc, so pasting the base service URL is fine.

Step 4 — Create a certificate template

Duplicate and configure

On the CA server, open Server Manager → Tools → Certificate Templates Console (certtmpl.msc), right-click an existing template (e.g. Web Server) → Duplicate Template, then set:

General tab

  • Template display name, e.g. CertAutoPilot Web Server.
  • Template name, e.g. certautopilot-web-server (no spaces).
  • Validity period 1–2 years; renewal period e.g. 6 weeks.

Subject Name tab

  • Select Supply in the request.
warning

"Supply in the request" is mandatory. It lets CertAutoPilot put the subject (CN) and SANs into the CSR. With "Build from Active Directory" the CA rejects CSRs that carry subject information.

Cryptography tab

  • Provider Category: Key Storage Provider.
  • Algorithm: RSA, minimum key size 2048.
note

Many AD CS templates do not accept ECDSA keys. If you need ECDSA, the template's cryptography settings must explicitly allow it; otherwise issue RSA 2048/3072/4096 certificates from this template.

Security tab

  • Add the service account CertAutoPilot will use and grant Read and Enroll.

Extensions tab

  • Application Policies: include Server Authentication (1.3.6.1.5.5.7.3.1).
  • Key Usage: Digital Signature, Key Encipherment.

Publish the template

  1. Open the Certification Authority console (certsrv.msc).
  2. Expand your CA → right-click Certificate TemplatesNewCertificate Template to Issue.
  3. Select the new template and click OK.

Verify:

certutil -CATemplates | findstr "certautopilot"

Service account

Create a dedicated, least-privilege enrollment account — never use a Domain Admin:

New-ADUser -Name "svc-certautopilot" `
-UserPrincipalName "svc-certautopilot@contoso.local" `
-Path "OU=Service Accounts,DC=contoso,DC=local" `
-AccountPassword (Read-Host -AsSecureString "Password") `
-Enabled $true `
-PasswordNeverExpires $true `
-CannotChangePassword $true

Then grant it Read and Enroll on the template (certtmpl.msc → template → Security tab).

Next: configure CertAutoPilot

With the server side done, create the AD CS provider profile in CertAutoPilot (endpoints, service-account credentials, TLS trust) and sync templates — see Microsoft AD CS — then issue a certificate via the issuance walkthrough.

Server-side troubleshooting

Symptoms as seen from CertAutoPilot's connection test / template sync, with server-side causes:

Connection test fails

ErrorCauseSolution
TLS validation failedIIS SSL certificate not trustedAdd the issuing CA cert to the profile's TLS trust (or skip-verify for lab testing)
Endpoint unreachableNetwork/firewall issueVerify port 443 is open and IIS is running
Authentication failed (HTTP 401)Wrong credentialsVerify username format (DOMAIN\user) and password
Authentication failed (HTTP 403)User lacks permissionsGrant Enroll on the template to the service account

Template sync fails

ErrorCauseSolution
InvalidSecurityWS-Security header rejectedVerify CES/CEP were configured with the UsernamePassword binding
Empty policies / template missingTemplate not enrollable by the callerSee the 3-step checklist below
SOAP faultCEP service errorCheck the Windows Event Log on the CA server

A newly added template not appearing after Sync almost always needs all three of the following — duplicating a template alone does nothing. Work through them in order, then re-Sync:

  1. Publish it to the CAcertsrv.msc → CA → Certificate Templates → right-click → New → Certificate Template to Issue. (Duplicating ≠ publishing.)

  2. Grant Enroll (not just Read) to the service account — Template → Security → allow Enroll. CEP returns only templates the caller can enrol, so Read alone is not enough.

  3. Refresh the CEP policy cache — the policy web service caches its template list in memory. Recycle the CEP/CES app pool (least disruptive; only the enrollment front-end blips for a few seconds — the CA engine, issued certs, and CRLs are untouched):

    Restart-WebAppPool -Name "<CEP/CES app pool>" # e.g. WSEnrollmentPolicyServer

    iisreset also works. With multiple DCs, allow AD replication too (repadmin /syncall). Full checklist: New template doesn't appear after Sync.

Templates requiring approval go pending

If the template's Issuance Requirements tab requires CA certificate manager approval, requests land in Pending instead of being issued immediately. CertAutoPilot polls for these and completes them once an operator approves the request in certsrv.msc → Pending Requests. For fully automated issuance, leave approval disabled on the template.

Certificate issuance fails

ErrorCauseSolution
Denied by Policy ModuleTemplate rejects the requestCheck template settings (key type, subject-name policy)
The request is invalidCSR format issueUse an RSA 2048 key type
Template not foundTemplate not publishedPublish the template via the CA console

CES tracing

For deep diagnostics, enable verbose WCF tracing on the CES application:

# Enable CES verbose tracing
$wc = "C:\Windows\SystemData\CES\<AppName>\web.config"
(Get-Content $wc) -replace 'switchValue="Off"', 'switchValue="Verbose"' | Set-Content $wc
iisreset

# After reproducing the issue:
Get-Content "C:\Windows\SystemData\CES\<AppName>\Traces\Traces-EnrollmentServer.xml" |
Select-String "error|invalid|fault" -CaseSensitive:$false

# Disable tracing afterward:
(Get-Content $wc) -replace 'switchValue="Verbose"', 'switchValue="Off"' | Set-Content $wc
iisreset

Security best practices

  1. Dedicated service account for enrollment — never Domain Admin.
  2. Minimum permissions — Enroll on specific templates only; restrict template access to required users/groups.
  3. A properly trusted TLS certificate on IIS in production — avoid self-signed.
  4. Enable auditing on the CA to track all certificate issuance.
  5. Rotate the service-account password regularly and update the CertAutoPilot profile when you do.

See also