How to Set Up a PKI Infrastructure with AD CS on Windows Server 2012 R2

Public Key Infrastructure (PKI) built on Active Directory Certificate Services (AD CS) provides the digital certificate foundation for enterprise security: SSL/TLS certificates for web servers and internal services, S/MIME for email encryption, smart card authentication, code signing, and IPsec encryption. A properly designed two-tier PKI hierarchy — an offline Root CA and an online Subordinate/Issuing CA — is the industry-standard approach that balances security with operational practicality. This guide walks through deploying a complete two-tier enterprise PKI on Windows Server 2012 R2.

Prerequisites

– Two Windows Server 2012 R2 servers: one for the Root CA (can be workgroup/offline), one for the Subordinate CA (domain member)
– Active Directory domain for the Issuing CA
– Enterprise Admin privileges for publishing CA certificates to AD
– Planned CA names, validity periods, and CDP/AIA paths
– A dedicated IIS server (or the Subordinate CA server) to host CRL Distribution Points
– DNS entries for the CDP URL (e.g., pki.corp.local)

Step 1: Design the PKI Architecture

Before installation, document your PKI design decisions. These cannot be easily changed after deployment:

# PKI Design Decisions:
# Root CA:
#   Name: Corp-Root-CA
#   Type: Standalone Root CA (NOT domain member — kept offline)
#   Validity: 20 years
#   Key size: 4096-bit RSA
#   Hash: SHA-256
#   CRL Validity: 1 year
#
# Subordinate/Issuing CA:
#   Name: Corp-Issuing-CA-01
#   Type: Enterprise Subordinate CA (domain member)
#   Validity: 10 years (signed by Root CA)
#   Key size: 2048-bit RSA (for issued certs) or 4096-bit for the CA key
#   Hash: SHA-256
#   CRL Validity: 1 week (published every day)
#   OCSP: enabled
#
# CDP URL: http://pki.corp.local/CertEnroll/.crl
# AIA URL: http://pki.corp.local/CertEnroll/_.crt

Write-Host "PKI design documented. Proceed with installation."

Step 2: Install the Offline Root CA

# ON THE ROOT CA SERVER (offline, workgroup server — NOT domain joined)

# Install AD CS role
Install-WindowsFeature -Name AD-Certificate -IncludeManagementTools

# Create the CAPolicy.inf configuration file (defines CA settings before install)
$capolicy = @"
[Version]
Signature="$Windows NT$"

[PolicyStatementExtension]
Policies=InternalPolicy
Critical=False

[InternalPolicy]
OID=1.2.3.4.1455.67.89.5
Notice="Legal Policy Statement"

[Certsrv_Server]
RenewalKeyLength=4096
RenewalValidityPeriod=Years
RenewalValidityPeriodUnits=20
CRLPeriod=Years
CRLPeriodUnits=1
CRLDeltaPeriod=Days
CRLDeltaPeriodUnits=0
LoadDefaultTemplates=0
AlternateSignatureAlgorithm=0

[CRLDistributionPoint]
Empty=True

[AuthorityInformationAccess]
Empty=True
"@

$capolicy | Out-File "C:WindowsCAPolicy.inf" -Encoding ASCII

# Install the Root CA as Standalone Root
Install-AdcsCertificationAuthority `
    -CAType StandaloneRootCa `
    -CACommonName "Corp-Root-CA" `
    -CADistinguishedNameSuffix "DC=corp,DC=local" `
    -CryptoProviderName "RSA#Microsoft Software Key Storage Provider" `
    -KeyLength 4096 `
    -HashAlgorithmName SHA256 `
    -ValidityPeriod Years `
    -ValidityPeriodUnits 20 `
    -DatabaseDirectory "C:WindowsSystem32CertLog" `
    -LogDirectory "C:WindowsSystem32CertLog" `
    -Force

Write-Host "Root CA installed"
Get-CertificationAuthority | Format-List Name, Active

Step 3: Configure CDP and AIA on the Root CA

# Configure CRL Distribution Point (CDP) on Root CA
$crlPath = "http://pki.corp.local/CertEnroll/"
$rootCaName = "Corp-Root-CA"

# Remove default CDP/AIA and add custom HTTP-based locations
Get-CACRLDistributionPoint | Remove-CACRLDistributionPoint
Get-CAAuthorityInformationAccess | Remove-CAAuthorityInformationAccess

# Add CDP locations
Add-CACRLDistributionPoint `
    -Uri "C:WindowsSystem32CertSrvCertEnroll%3%8%9.crl" `
    -AddToCertificateCDP -PublishToServer

Add-CACRLDistributionPoint `
    -Uri "http://pki.corp.local/CertEnroll/%3%8%9.crl" `
    -AddToCertificateCDP

# Add AIA location
Add-CAAuthorityInformationAccess `
    -Uri "http://pki.corp.local/CertEnroll/%1_%3%4.crt" `
    -AddToCertificateAia

# Restart the CA service to apply changes
Restart-Service CertSvc

# Publish the Root CA certificate and CRL
certutil -crl

# Export Root CA certificate for transfer to the Subordinate CA
certutil -ca.cert "C:RootCACorpRootCA.crt"

# Export the Root CRL for publication
certutil -exportcrl "C:RootCACorpRootCA.crl"

Step 4: Publish Root CA to Active Directory

# Transfer CorpRootCA.crt to a domain-joined machine and run:
# (Run from a domain-joined server with Enterprise Admin)

certutil -dspublish -f "C:PKICorpRootCA.crt" RootCA

# Publish Root CA CRL to AD
certutil -dspublish -f "C:PKICorpRootCA.crl" Corp-Root-CA

# Copy cert and CRL to the IIS web share for HTTP-based CDP
Copy-Item "C:PKICorpRootCA.crt" "C:inetpubwwwrootCertEnroll" -Force
Copy-Item "C:PKICorpRootCA.crl" "C:inetpubwwwrootCertEnroll" -Force

# Verify publication to AD
certutil -viewstore -enterprise Root

# Verify CRL is reachable via HTTP
Invoke-WebRequest "http://pki.corp.local/CertEnroll/CorpRootCA.crl" -UseBasicParsing |
    Select-Object StatusCode

Step 5: Install the Enterprise Subordinate (Issuing) CA

# ON THE SUBORDINATE CA SERVER (domain member server)
Import-Module ServerManager

# Install AD CS role
Install-WindowsFeature -Name AD-Certificate, ADCS-Cert-Authority, ADCS-Web-Enrollment, 
    ADCS-Online-Cert, Web-Server -IncludeManagementTools

# Create CAPolicy.inf for the Subordinate CA
$subcaPolicy = @"
[Version]
Signature="$Windows NT$"

[Certsrv_Server]
RenewalKeyLength=4096
RenewalValidityPeriod=Years
RenewalValidityPeriodUnits=10
CRLPeriod=Weeks
CRLPeriodUnits=1
CRLDeltaPeriod=Days
CRLDeltaPeriodUnits=1
LoadDefaultTemplates=1
"@
$subcaPolicy | Out-File "C:WindowsCAPolicy.inf" -Encoding ASCII

# Install Subordinate CA — this generates a certificate signing request
Install-AdcsCertificationAuthority `
    -CAType EnterpriseSubordinateCa `
    -CACommonName "Corp-Issuing-CA-01" `
    -CADistinguishedNameSuffix "DC=corp,DC=local" `
    -CryptoProviderName "RSA#Microsoft Software Key Storage Provider" `
    -KeyLength 4096 `
    -HashAlgorithmName SHA256 `
    -OutputCertRequestFile "C:SubCACorpIssuingCA.req" `
    -Force

Write-Host "Subordinate CA CSR generated at C:SubCACorpIssuingCA.req"
Write-Host "Transfer this file to the Root CA for signing"

Step 6: Sign the Subordinate CA Certificate on the Root CA

# ON THE ROOT CA — sign the Subordinate CA's certificate request
# Transfer CorpIssuingCA.req to the Root CA

certreq -submit -attrib "CertificateTemplate:SubCA" `
    "C:SubCACorpIssuingCA.req" `
    "C:SubCACorpIssuingCA.crt"

# If certreq doesn't work, use the CA MMC:
# Certification Authority > corp-root-ca > Submit a new request

# The Root CA issues the SubCA certificate
# Transfer CorpIssuingCA.crt back to the Subordinate CA server

# ON THE SUBORDINATE CA — install the signed certificate
certutil -installcert "C:SubCACorpIssuingCA.crt"

# Start the Subordinate CA
Start-Service CertSvc
Set-Service CertSvc -StartupType Automatic

# Verify the Subordinate CA is running
Get-CertificationAuthority | Format-List Name, Active, Certificate*

Step 7: Configure CDP and AIA on the Subordinate CA

# Configure CDP and AIA on the Subordinate CA
Get-CACRLDistributionPoint | Remove-CACRLDistributionPoint
Get-CAAuthorityInformationAccess | Remove-CAAuthorityInformationAccess

# Add the file-based CDP (local publication)
Add-CACRLDistributionPoint `
    -Uri "C:WindowsSystem32CertSrvCertEnroll%3%8%9.crl" `
    -AddToCertificateCDP -PublishToServer

# Add the HTTP-based CDP (in issued certificates)
Add-CACRLDistributionPoint `
    -Uri "http://pki.corp.local/CertEnroll/%3%8%9.crl" `
    -AddToCertificateCDP

# Add Delta CRL
Add-CACRLDistributionPoint `
    -Uri "http://pki.corp.local/CertEnroll/%3%8%9+.crl" `
    -AddToCertificateCDP

# Add AIA (CA certificate location)
Add-CAAuthorityInformationAccess `
    -Uri "http://pki.corp.local/CertEnroll/%1_%3%4.crt" `
    -AddToCertificateAia

# Add OCSP AIA
Add-CAAuthorityInformationAccess `
    -Uri "http://pki.corp.local/ocsp" `
    -AddToCertificateOcsp

Restart-Service CertSvc
certutil -crl  # Publish CRL

Write-Host "Subordinate CA CDP/AIA configured"

Step 8: Configure and Publish Certificate Templates

Import-Module ADCSAdministration

# View available certificate templates
Get-CATemplate | Select-Object Name | Sort-Object Name | Format-Table -AutoSize

# Add commonly needed templates to the Issuing CA
$templatesToAdd = @(
    "WebServer",              # SSL server certificates
    "Workstation",            # Computer certificates
    "User",                   # User certificates (S/MIME, EFS)
    "SmartcardLogon",         # Smart card authentication
    "ClientAuth",             # Client authentication
    "CodeSigning"             # Code signing
)

foreach ($template in $templatesToAdd) {
    try {
        Add-CATemplate -Name $template -Force
        Write-Host "Added template: $template" -ForegroundColor Green
    } catch {
        Write-Warning "Could not add $template`: $($_.Exception.Message)"
    }
}

# Verify templates are published
Get-CATemplate | Select-Object Name | Format-Table -AutoSize

Verification

# Verify full PKI chain
Write-Host "=== PKI Infrastructure Verification ===" -ForegroundColor Cyan

# Check Subordinate CA service
Get-Service CertSvc | Select-Object Status, StartType

# Verify CA certificate chain
certutil -verify -urlfetch "C:SubCACorpIssuingCA.crt"

# Check CRL validity
certutil -verify "http://pki.corp.local/CertEnroll/Corp-Issuing-CA-01.crl"

# Request a test certificate to verify end-to-end
certreq -new -machine test_cert.inf test_cert.csr
certreq -submit test_cert.csr test_cert.cer

# Verify the cert chains to Root CA
certutil -verify test_cert.cer

# Check AD publishing
certutil -viewstore -enterprise Root | Select-String "Corp-Root-CA"
certutil -viewstore -enterprise CA   | Select-String "Corp-Issuing"

Summary

A two-tier PKI infrastructure with AD CS on Windows Server 2012 R2 provides the certificate authority backbone for enterprise security services. The offline Root CA signs only the Subordinate CA certificate and is then secured offline, limiting exposure if the Root CA were ever compromised. The online Enterprise Subordinate CA handles all day-to-day certificate issuance, integrates with Active Directory for auto-enrollment, and publishes CRLs to an HTTP-accessible location. Proper CDP and AIA configuration ensures that every issued certificate includes verifiable revocation information and CA certificate download locations, which are essential for PKI to function correctly across all clients and services.