Sign website certs with your intranet Windows CA

03/16/2024

If you have sites/services/web appliances in a domain environment running on your intranet or home lab, and you’d like them to have valid certificates so that you can browse without having to click Advanced in your browser every time you visit the site, then this guide is for you!

If your sites are public-facing, this guide is not specifically for you. Instead, you should look into using a tool like WinACME or equivalent to get cert’d up via a public CA.

My lab environment for domain: tlu.techlevelup.net
1. Windows Server 2022 domain controller (standard setup with DNS + DHCP)
2. Windows Server 2022 domain member server with AD CS installed
3. A site without a valid signed Cert. (In my case, it’s a TrueNAS Scale server!)

This guide assumes you already have a windows domain environment with a Domain Controller. So, we will begin with setting up our domain member server as a Certificate Authority. Do not attempt to make your DC a CA.

1. Using Server Manager, install the AD CS roles shown below

2. Note that you will need to install the CA role first, then you will be able to install & configure the other two, as you will find out when you attempt to install all 3 at once. During installation, follow the Microsoft Learn guide to set up Certificate Enrollment Web Services*.

*Also note that CES (Certificate Enrollment Web Services) is not to be confused with Certificate Web Enrollment, which is an entirely different role. CES allows automated certificate renewal, while Cert Web Enrollment allows you to manually upload a .csr request to your CA via https / IIS to get a signed certificate.

3. During installation of CES, you will be asked whether you want to use a built-in app pool identity, or use a domain service account. I used a service account because it is Microsoft-recommended. I also selected Integrated Windows Authentication as the authentication method since I will only be requesting certificates using domain accounts.

4. Make sure you pay attention to the requirements for the service account. The domain account must be a member of the local IIS_IUSRS group on your Domain Member server which is the CA. You must also register a Service Principal name for the service account using the setspn command.

For example, in my case, I used the command setspn -s http/windows1 tlu.techlevelup.net\SAadcs
(where windows1 is the hostname of my windows domain member server, and SAadcs is the domain user account I created to act as the service account (SA) for CES).

5. Continuing to follow the Microsoft Learn article, open ADUC and double-click on the SA you just created, navigating to the newly-present Delegation tab to add the services shown below.

6. Next, you will be prompted to choose a certificate for securing the CES service. You will need to pause here (just leave the installation screen alone for now) and then follow this guide to create your certificate.

Once you have created your certificate, continue where you left off with the CES installation and select the new certificate you just created.

7. After installation is complete, follow the Microsoft Learn article to configure Certificate Enrollment Policy Web Service (CEP). Part of this configuration includes creating a Group Policy object and deploying it to your clients. This will allow you to specify a certificate template when requesting a certificate later on. As part of following the aforementioned guide, you will also be directed to this guide to perform other prerequisite steps. Since the steps in these guides are exactly what I followed, I will not repeat them here.

After installation of ADCS is complete, there are a couple more things we can do to make our lives easier:

8a. On your new CA, open mmc.exe -> File -> Add Snap in -> Certificate Templates. Find the certificate that you created in step 6 -> Right-click -> Properties -> General tab and increase the validity period. I chose 5 years, but you can set it higher or lower if you want. For production certs, 2 years is the recommended maximum.

8b. On the Subject Name tab, I recommend selecting Supply in the request, so that we don’t have to worry about having DNS entries already present for the device/website/service that we are trying to get a cert for.

8c. Following the 2nd half of Jacob Fredriksson’s guide to increase the validity period limit for issued certificates, open PowerShell and run the following commands (adjust validity limit as you so desire):

certutil -setreg ca\ValidityPeriod "Years"
certutil -setreg ca\ValidityPeriodUnits "5"
net stop certsvc; net start certsvc

Now comes the fun part! Let’s get ourselves a signed certificate! Note that while there are several methods and PowerShell modules which will allow you to request and sign certificates, the below are what I found to be the easiest to use.

1. From another domain computer, open PowerShell as an administrator, using an account that has permissions to enroll certificates using the Certificate template you created before (see the guide linked in step 6).

2. Install the PowerShell script RequestCertificate.ps1

Install-Script request-certificate

3. Next, install the PSPKI module (you might not need it, but it will come in handy eventually)

Install-module PSPKI

4. Now, I’m going to request a certificate for my TrueNAS Scale server! You will obviously need to adjust depending on the Subject and SANs that you want to appear in your cert. You should specify a password if you will need to export your key and/or convert it from .pfx to another format

Request-Certificate -CN "nas.techlevelup.net" -SAN dns="nas.tlu.techlevelup.net",dns="nas.techlevelup.net" -Country "US" -State "VA" -Organisation "TechLevelUp" -TemplateName "SSLCertificates" -KeyLength 2048 -Export -ExportPath C:\users\trevorDomainAdmin\desktop\ -Password (ConvertTo-SecureString 'passwordGoesHere' -AsPlainText -Force)

In my case, I have multiple CAs in my environment, so I was prompted to select a CA/CES service to use. I selected the https CES URI that was configured in IIS (step 7 above).

You will now have a signed .pfx certificate that you can use freely! Depending on what format your application/device requires, you might be okay with the .pfx cert. However, in my case, TrueNAS Scale requires the encrypted private key and the actual certificate to be provided separately.

5. To convert a pfx file to a readable format, there are a couple options.
One is to use the PSPKI module we installed before:

Convert-PfxToPem -InputFile C:\users\trevorDomainAdmin\desktop\nas.techlevelup.net.pfx -IncludeChain -OutputFile C:\users\trevorDomainAdmin\desktop\nas.techlevelup.net.pem

The other option, if your private key needs to be in an encrypted format, is to use openssl (ie, in a Linux terminal). For example:

openssl pkcs12 -in nas.techlevelup.net.pfx -out nas.techlevelup.net.pem

In either case, you will be prompted for the password you supplied in step 4 above, and then voila! A beautiful .pem file will land at the location you specified, which you can view in Notepad.

If you used PowerShell, you’ll see it in the following format if you used the -includecertificatechain parameter.

If you used openssl, your .pem key will look like this:

To verify the certificate was created to our specifications, we can use an SSL decoder tool like this one on sslhopper.com. Make sure to exclude your private key!

As we can see, the cert is using 2048-bit encryption, has the proper SANs, and is good for 5 years.

Apply the new cert to TrueNAS Scale server

Now that we have our complete cert including the private key and cert chain, we can proceed to give our NAS a flashy new cert.

1. Navigate to Credentials -> Certificates

2. In the Certificates section, click Add. Enter a name, and select Import Certificate.

3. Paste in the Certificate and encrypted private key, including the BEGIN and END lines, and then enter the passphrase you used before.

4. Set the new certificate as the website cert by going to System Settings -> General -> GUI and select it from the dropdown:

After the web service restarts, we can see the cert is now good for 5 years!