Ssl – Can you use install a Subject Alternative Name (SAN) server certificate on a Windows 2012 R2/2016 Server to enable LDAPs

active-directoryldapssl

Answering a post from r/sysadmin but I don't have enough karma to self answer:

Can you use install a Subject Alternative Name (SAN) server certificate on a Windows 2012 R2/2016 Server to enable LDAPs?

OR, do all DCs need their own SSL cert?

My cursory reading leads me to believe each DCs needs its own certificate and one cannot just stuff all the DC names in the Alternative Name field of a single SAN cert and then just install it on all DCs.

Best Answer

Previously, the DCs used a specially formatted, common (across all the DCs) self-signed certificate to enable LDAPS for the APCs in the data center to authenticate. Cisco UCS would not accept the self-signed certificate for creating 'Trust Points'. In order to enable the same functionality for UCS it was determined that the certificate used must be chained. Testing indicated that it does not matter if the root certificate to which the host certificate is chained is a valid CA or if it was a self-signed CA. As such, we decided to create a new, self-signed CA and then sign the DC LDAP certificate. This is fairly standard with exception to the special requirement of Subject Alternate Names (SANs) necessary for LDAPS to function across multiple domain controllers accessed by the domain name.

Best efforts were made to generate the needed certificate via Windows tools but, if it's even possible, it's so poorly documented that we determined it would be expeditious to generate them on a linux machine and copy them over to the domain afterwards. The method below allows for generating the certificates without setting up a complete CA structure by using the "mini CA" functionality of "openssl x509" (https://www.openssl.org/docs/apps/x509.html#SIGNING-OPTIONS).

Generate the private key for the CA certificate and the CA certificate itself per standard procedure:

openssl genrsa -des3 -out ldapCA.key 4096
openssl req -x509 -new -nodes -key ldapCA.key -days 3650 -out ldapCA.pem

Create a certificate configuration file for the host LDAP certificate that contains the v3_req section needed to support SANs:

[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no

[req_distinguished_name]
C = US
ST = NC
L = XXX
O = YYY
OU = ZZZ
CN = 

[v3_req]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1 = 
DNS.2 = 
DNS.3 = 
DNS.4 = 
DNS.5 = 

After repeated failures to generate the correct certificate using the request configuration above, we found that the x509 option for openssl does not copy extensions in from the CSR (http://openssl.6102.n7.nabble.com/Unable-to-create-Version-3-certificates-with-subjectAltName-using-my-own-CA-td46753.html#a46755)

OpenSSL has two ways to create a cert from a CSR: 
'ca' # the original most complete way 
'x509 -req' # a simplified way without the 'database' etc. 

Only 'ca' fully uses the config file settings and in particular copy_extensions. 'x509 -req' can use the config file for
extensions but nothing else. 

Use 'ca' if you want to copy extensions from the CSR. 

You *can* use 'x509 -req' and put extensions including SAN in the config file at 'x509 -req' time (not 'req -new' time),
and that's good for CA-related extensions like crldp, but you usually want SAN to vary for each cert. 

To remedy this we need to create a second file with the extensions only:<

basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = DNS:, DNS:, DNS:,DNS:,DNS:

It was unclear whether the same data needed to be in both the CSR and the extensions file but it works with it in both. At this point, we can generate the host certificate using the CA, CA key, certificate request file, and the extension file and then verify the resulting certificate:

openssl x509 -days 1460 -req -CA ldapCA.pem -CAkey ldapCA.key -CAcreateserial -in ldapSAN.csr -out ldapSAN.pem -extfile ext.txt
openssl x509 -text -noout -in ldapSAN.pem

The output of the verification should show that it is a v3 certificate, is signed by the CA, and should show the SAN section filled with the FQDN of each DC:

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:  ()
    Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=, ST=, L=, O=, OU=, CN=/emailAddress=
        Validity
            Not Before: Mar  5 16:36:10 2015 GMT
            Not After : Mar  4 16:36:10 2019 GMT
        Subject: C=, ST=, L=, O=, OU=, CN=
        Subject Public Key Info:
            [...]
        X509v3 extensions:
            X509v3 Basic Constraints: 
                CA:FALSE
            X509v3 Key Usage: 
                Digital Signature, Non Repudiation, Key Encipherment
            X509v3 Extended Key Usage: 
                TLS Web Server Authentication
            X509v3 Subject Alternative Name: 
                DNS:, DNS:, DNS:, DNS:, DNS:
    Signature Algorithm: sha1WithRSAEncryption
         [...]

In order to import the certificates and use them on the DCs we have to export the host certificate with the private key in pkcs12(pfx) format:

openssl pkcs12 -export -out ldapSAN.pfx -inkey ldapSAN.key -in ldapSAN.pem -certfile ldapCA.pem

Finally, we install the public version of the CA certificate, in this case ldapCA.pem, in the Trusted Root Certification Authorities store of the Machine Account of each domain controller. This can be done with remote administration tools, locally on each server, or though GPO. We then install the host certificate and private key on each server. This must be done locally as pfx import with private key information is not possible remotely:

CERTUTIL -f -p <password> -importpfx ldapSAN.pfx

At this point, the DCs may just pick up the certificate automatically (http://support.microsoft.com/kb/321051):

Finally, if a Windows Server 2008 or a later version domain controller finds multiple certificates in its store, it
automatically selects the certificate whose expiration date is furthest in the future. Then, if your current certificate is
approaching its expiration date, you can drop the replacement certificate in the store, and AD DS automatically switches
to use it.

In our case, be cause the previous certificates had an expiration date after the new ones, we had to delete the old certificates before each domain controller would use the new one. You can verify the certificate in use by the LDAP service with the following (NAGIOS has a check for this as well):

openssl s_client -connect <FQDN of DC>:636 -showcerts

The output will contain similar information to the certificate verification we did above.

At this point you can provide the public certificates to any clients that need them. Some may require only the CA, some may require only the host certificate, and some may require a single file with the entire chain.

Both UCS and APC have been reconfigured by SR to connect with the new certificates.

w00t