Creating an offline certificate authority using OpenSSL and Creating trust with Group Policy
Build the system:
Offline vs. Online:
Due to the nature of what one can do with the power of a trusted CA, I am not a fan of online CAs. Others think that offline CAs an ancient idea.
I’m not going to become a victim of an argument focusing on how systems and active directory aren’t secure if someone can access your GPOs and push out trusted CAs to your clients; kerberos key distribution is already online; and what about AD in general… that has to be online, doesn’t it?
Offline === Offline. What’s the best risk reduction procedure? If something doesn’t exist then there is no risk. So just focus on physical security of the system, and the physical security of the CA private key and you are good to go!
Harden the install:
You may choose to do this before or after you have finished setting up the CA. The main purpose of this is to make sure that your private key is very secure.
Restrict root logons by physical console only:
echo "tty1" > /etc/securetty chmod 700 /root
Set a logout timeout of one minutes:
echo "TMOUT=60" >> /etc/bashrc echo "readonly TMOUT &> /dev/null" >> /etc/bashrc echo "export TMOUT &> /dev/null" >> /etc/bashrc
Clear command history on logout:
echo "echo > ~/.bash_history" >> /etc/bash.bash_logout echo "history -c" >> /etc/bash.bash_logout
Configure the CA directory structure and some configuration files:
mkdir -m 0700 /root/ca /root/ca/certs /root/ca/crl /root/ca/newcerts /root/ca/private touch /root/ca/index.txt echo 00 > /root/ca/crlnumber echo 1000 > /root/ca/serial sed s@"/etc/pki/CA"@"/root/ca"@g -i /etc/pki/tls/openssl.cnf sed s@"$dir/crl.pem"@"$dir/crl/crl.pem"@g -i /etc/pki/tls/openssl.cnf echo "crlDistributionPoints=URI:http://CRLSERVER/janus.crl" > /root/ca/opensslx509.conf
Generate the Root CA certificate/key pair:
The first step is to generate a private key and the public key. “Key” is synonymous with certificate.
openssl genrsa -des3 -out /root/ca/private/cakey.pem 4096 chmod 400 /root/ca/private/cakey.pem openssl req -new -x509 -extensions v3_ca -key /root/ca/private/cakey.pem -out /root/ca/cacert.pem -days 3650 #ten year long Root CA public certificate
Securely backup /root/ca/private/cakey.pem. As in, guard it with your life. This is the stamp-of-approval for all certificates you are signing going forward. Some people store this on encrypted media, like a removable USB thumbdrive that is itself encrypted.
Creating a CRL distribution point:
One of the problems I came across when researching this implementation was that most of the technical write ups are not clear about a very important point, distributing the certificate revocation list. So, I will discuss CRLs and configuring a CRL distribution point before we generate our CA certificates.
If you were to roll out a CA on Windows server, you would see that there are two CRL distribution points:
One that’s served within the Active Directory LDAP, and is an octet string value (aka hex):
ldap://CN=CA_CERT_NAME,CN=CA_SERVER,CN=CDP,CN=Public%20Key%20Services,CN=Services,CN=Configuration,DC=DOMAIN,DC=local objectClass=cRLDistributionPoint Attribute=certificateRevocationList
The other is via an HTTP URL:
I will simply be using HTTP and be presenting the CRL via a URL as http://CRLSERVER/ca.crl.
If you do not have an HTTP server, please configure one, or use `openssl s_server` (but not on this box, since it’s offline). It’s worth noting that it is up to the clients to check the CRL as they wish, but they hopefully will all time and the complete URI of your CRL should always be accessible. If the original server goes away, no worries; just use a CNAME and/or filter on HTTP HEADER content or some other magic. Just make sure that the CRL is available at the path you’ve described.
Note that the CRL is public knowledge and doesn’t need to be secured (not that I’m implying that the web server doesn’t, just the file itself).
We will be creating a very simple config file for use with the `openssl x509 -extfile` parameter.
echo "crlDistributionPoints=URI:http://CRLSERVER/ca.crl" > /root/ca/opensslx509.conf
Copy the public certificate to a DC to distribute via GPO:
1) Copy the /root/ca/certs/ca.cer or the contents to a DC.
2) Open gpmc.msc and navigate to:
Computer Configuration/Policies/Windows Settings/Security Settings/Public Key Policies/Trusted Root Certification Authorities
3) Right-click and import ca.cer into “Trusted Root Certification Authorities.” This will push the CA to the local stores of any target clients.
Sign a certificate request (producing a certificate which includes the CRL):
openssl ca -days 3650 -extfile /root/ca/opensslx509.conf -out /root/ca/certs/therequestorscert.cer -in ~/therequest.csr
Do not delete generated certificates from your server. Copy them to the destination.
Revoke a certificate and create a new CRL:
In order to maintain a proper CRL, all the issued certs should remain on your server.
openssl ca -revoke /root/ca/certs/therequestorscert.cer -keyfile /ca/private/cakey.pem -cert /root/ca/certs/ca.cer #revoke the certificate if [[ $(cat /root/ca/crlnumber) =~ ^[0-9]+$ ]]; then export crlvernumber=$(/root/ca/crlnumber); fi # /root/ca/crlnumber contains the version of the CRL openssl ca -gencrl -crl_reason [unspecified, keyCompromise, CACompromise, affiliationChanged, superseded, cessationOfOperation, certificateHold, removeFromCRL] -keyfile /root/ca/private/cakey.pem -cert /root/ca/certs/ca.cer > /root/ca/crl/crl.$(/root/ca/crlnumber) if [[ $(cat /root/ca/crlnumber) =~ ^[0-9]+$ ]]; then echo $(($(cat /root/ca/crlnumber)+1)); else cat /root/ca/crlnumber; fi > /root/ca/crlnumber #increments /root/ca/crlnumber after to process as to avoid writing older CRLs