Windows Server 2012 R2 Two-Tier PKI CA Pt. 2

1-5-2014 2-43-05 PM Now that our root Windows Server 2012 R2 certificate authority is installed and published to Active Directory from Part 1, it is time to bring online our subordinate CA. The subordinate CA will be our online issuing CA, since it will be the CA which issues all certificates, be they for users, computers, ESXi hosts, etc. The VM will be joined to the domain, and be online 100% of the time.

As with the offline root, you should perform hardening of this VM as well. Enabling the Windows firewall (or a third party one), anti-virus software, Microsoft EMET, and following Microsoft security baseline settings are all strongly recommended. If you have security software that can monitor file changes or system integrity, that too would be a great idea. Auditing tools such as Splunk, for real time alerting, would be ideal for defense in depth.

Install Windows Server 2012 R2 Subordinate CA

1. Use Notepad and create a file called CAPolicy.inf in C:\Windows on your subordinate VM. Use the code snippet below, but change the URL to match that previously used in configuring your offline root.

Signature="$Windows NT$"
Notice="Legal Policy Statement"

4. Run the following PowerShell command. Change the CACommonName as needed. The command will completely instantly.

Add-WindowsFeature Adcs-Cert-Authority -IncludeManagementTools
Add-WindowsFeature Adcs-web-enrollment
Install-AdcsCertificationAuthority -CAType EnterpriseSubordinateCA -CACommonName "IssuingCA-D002MISC01" -KeyLength 2048 -HashAlgorithm SHA256 -CryptoProviderName "RSA#Microsoft Software Key Storage Provider"

5. Copy the resulting request (see the yellow information text from the last command for the path and file name) to the offline CA.

6. On the offline CA type the following command, using your filename:

certreq -submit D002MISC01.contoso.local_IssuingCA-D002MISC01.req

7. You will now see that the request is pending. Take note of the RequestId, as it will be unique to you.

1-4-2014 7-47-29 PM

8. Open the CA Manager snap-in on your offline root and issue the pending certificate.

1-4-2014 7-48-25 PM 9. While still on the offline CA, enter the following command to download the new certificate. Replace “2” with your request ID, and change the filename as you see fit.

certreq -retrieve 2 c:\D002MISC01.contoso.local_IssuingCA-D002MISC01.crt

10. Copy the certificate file to the online subordinate CA. Note: Do NOT place it in the pki directory. Run the commands below to install the new certificate. Once the certificate is installed, delete the file and empty the trashcan.

Certutil –installcert a:\ D002MISC01.contoso.local_IssuingCA-D002MISC01.crt
start-service certsvc
copy c:\Windows\system32\certsrv\certenroll\*.cr* d:\pki\

Configure Subordinate CDPs

1. Next up we need to configure the proper CRLs for our subordinate CA. Enter the following commands in an elevated Powershell on your subordinate CA.

$crllist = Get-CACrlDistributionPoint; foreach ($crl in $crllist) {Remove-CACrlDistributionPoint $crl.uri -Force};
Add-CACRLDistributionPoint -Uri C:\Windows\System32\CertSrv\CertEnroll\%3%8%9.crl -PublishToServer -PublishDeltaToServer -Force
Add-CACRLDistributionPoint -Uri http://www.contoso.local/pki/%3%8%9.crl">http://www.contoso.local/pki/%3%8%9.crl -AddToCertificateCDP -Force
Add-CACRLDistributionPoint -Uri file://\\D002Misc01.contoso.local\pki\%3%8%9.crl" file://\\D002Misc01.contoso.local\pki\%3%8%9.crl -PublishToServer -PublishDeltaToServer -Force
$aialist = Get-CAAuthorityInformationAccess; foreach ($aia in $aialist) {Remove-CAAuthorityInformationAccess $aia.uri -Force};
Add-CAAuthorityInformationAccess -AddToCertificateAia http://www.contoso.local/pki/%1_%3%4.crt" http://www.contoso.local/pki/%1_%3%4.crt -Force
Certutil -setreg CA\CRLPeriodUnits 2
Certutil -setreg CA\CRLPeriod "Weeks"
Certutil -setreg CA\CRLDeltaPeriodUnits 1
Certutil -setreg CA\CRLDeltaPeriod "Days"
Certutil -setreg CA\CRLOverlapPeriodUnits 12
Certutil -setreg CA\CRLOverlapPeriod "Hours"
Certutil -setreg CA\ValidityPeriodUnits 5
Certutil -setreg CA\ValidityPeriod "Years"
certutil -setreg CA\AuditFilter 127
restart-service certsvc
certutil -crl

CA Delegation

1. Now that our online subordinate CA is up and running, for the most part, it is a good idea to delegate who has rights to manage the CA and issue certificates. I’m going to create two roles: One that can manage all aspects of the CA, and another that can just mint specific certificates. In AD create two groups: Role_CA Manager and Role_Issue Certificates. Or use whatever names you like.

2. On your subordinate CA, launch the CA MMC Snap-in. Right click on the CA name, open the properties, and select the Security tab, and add the Role_CA Manager group. Give it Manage CA permissions. If you want, you can remove rights from Domain Admins or Enterprise Admins, should you want to more tightly control CA access (which you should).

windows server 2012 r2 certificate authority


At this point in the configuration there are no published templates. So in the following post we will configure a couple of templates, and I’ll show you how to delegate permissions so that other administrators can mint their own certificates. In this installment we’ve done the bulk of the subordinate CA configuration. At this point the CA is now functional, although no templates have been configured. So coming up in the next installment is, among other things, the process to configure templates and computer autoenrollment. Check out Part 3 here.

Print Friendly, PDF & Email

Related Posts

Notify of
Newest Most Voted
Inline Feedbacks
View all comments
January 10, 2014 11:09 pm

Hey Derek. I believe your note in Step 10 of installing the Subordinate CA about the retrieved certificate being a private key is incorrect. The private key for the CA certificate is never actually copied to the filesystem (or any certificate for that matter). Unless you explicitly export it as part of a PFX file, it lives forever in a protected section of the registry. It's not contained in the request file you submit to the offline CA. And the resulting signed certificate you get from the offline CA is just the public key for the subordinate CA. You can… Read more »

May 6, 2014 10:14 pm

Great series,
VERY helpful for those of us new to this word. I will say though, I have rebuilt my lab several times and every time I get hung up on the:
Add-CACRLDistributionPoint -Uri file://\D002Misc01.contoso.localpki%3%8%9.crl" file://\D002Misc01.contoso.localpki%3%8%9.crl

I have walked through your lab at least 5 times and every time I use this, I get an error about path not found. How critical is it to have this in there or what could be the problem with that line?

Thanks for the walk-through….it's a great help!

May 21, 2014 1:47 pm
Reply to  Rich

I think there's an issue caused by the hyperlink. I removed the duplicate part of those lines to make them read Add-CACRLDistributionPoint -Uri file://D002Misc01.contoso.localpki%3%8%9.crl only

January 13, 2015 12:38 am
Reply to  GuyNamedGuest

can we remove the duplicates from line 3,4,6 ?

October 6, 2014 8:47 am

Hi, great guide, I had issues running the PKI share from my sub CA; everything could access it apart from the sub CA, kept asking for credentials and wouldn't accept any.

Fix was to add an spn for it:
setspn -S HOST/pki.contoso.local D002Misc01

Restart, then kerberos worked properly 🙂

November 18, 2014 10:59 am

When trying to run:
install-adcswebenrollment i get an error:
"the group or resource is not in the correct state to perform the requested operation. 0x8007139f (WIN32: 5023 ERROR_INVALID_STATE)"

I also noticed that steps 2 and 3 are missing from the article. Could it be that the error message I get is related to something done in these steps?


January 12, 2015 11:48 pm

PS C:> $crllist=Get-CACrlDistributionPoint; foreach ($crl in $crllist) {Remove-CACrlDistributionPoint $crl.uri -Force};

Get-CACrlDistributionPoint : CCertAdmin::GetConfigEntry: The parameter is incorrect. 0x80070057 (WIN32: 87
At line:1 char:10
+ $crllist=Get-CACrlDistributionPoint; foreach ($crl in $crllist) {Remove-CACrlDis …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-CACrlDistributionPoint], ArgumentException
+ FullyQualifiedErrorId : System.ArgumentException,Microsoft.CertificateServices.Administration.Commands.CA.GetCrl

Thomas Brooks
April 7, 2020 10:41 am

I think there are several errors in how the script was posted onto the “Configure Subordinate CDPs” Script. =================================================================== $crllist = Get-CACrlDistributionPoint; foreach ($crl in $crllist) {Remove-CACrlDistributionPoint $crl.uri -Force}; Add-CACRLDistributionPoint -Uri C:\Windows\System32\CertSrv\CertEnroll\%3%8%9.crl -PublishToServer -PublishDeltaToServer -Force ERROR============================================== Add-CACRLDistributionPoint -Uri http://www.contoso.local/pki/%3%8%9.crl“> http://www.contoso.local/pki/%3%8%9.crl -AddToCertificateCDP -Force POSSIBLE_CORRECTION================================ Add-CACRLDistributionPoint -Uri “http://www.contoso.local/pki/%3%8%9.crl” -AddToCertificateCDP -Force ERROR============================================== Add-CACRLDistributionPoint -Uri file://\\D002Misc01.contoso.local\pki\%3%8%9.crl” file://\\D002Misc01.contoso.local\pki\%3%8%9.crl -PublishToServer -PublishDeltaToServer -Force POSSIBLE_CORRECTION================================ Add-CACRLDistributionPoint -Uri “file://\\D002Misc01.contoso.local\pki\%3%8%9.crl” -PublishToServer -PublishDeltaToServer -Force $aialist = Get-CAAuthorityInformationAccess; foreach ($aia in $aialist) {Remove-CAAuthorityInformationAccess $aia.uri -Force}; ERROR============================================== Add-CAAuthorityInformationAccess -AddToCertificateAia http://www.contoso.local/pki/%1_%3%4.crt” http://www.contoso.local/pki/%1_%3%4.crt -Force POSSIBLE_CORRECTION================================ Add-CAAuthorityInformationAccess -AddToCertificateAia “http://www.contoso.local/pki/%1_%3%4.crt” -Force Certutil -setreg CA\CRLPeriodUnits 2 Certutil -setreg CA\CRLPeriod “Weeks” Certutil -setreg CA\CRLDeltaPeriodUnits 1 Certutil -setreg CA\CRLDeltaPeriod “Days”… Read more »