Sunday, November 03, 2013

Client Certificate Authentication Issues with Apache and OS X Mavericks

Found some good tutorials online but took a few days of troubleshooting for me to figure out why they were not working.  Still don't understand SSL and cryptography as much as I would like to.  Posting this incase anyone else runs into similar issues.

The 3 tutorials I found via googling were:

  • Apache
    • http://www.impetus.us/~rjmooney/projects/misc/clientcertauth.html
    • http://linuxconfig.org/apache-web-server-ssl-authentication
  • Nginx
    • http://nategood.com/client-side-certificate-authentication-in-ngi
I will recap the commands here for additional info on how it works read either of those.

# Create the CA Key and Certificate for signing Client Certs 
openssl req -config ./openssl.cnf -newkey rsa:2048 -nodes -keyform PEM -keyout ca.key -x509 -days 3650 -extensions certauth -outform PEM -out ca.cer
# Create the Server Key, CSR, and Certificate 
openssl genrsa -out server.key 2048

openssl req -config ./openssl.cnf -new -key server.key -out server.req

# We're self signing our own server cert here. This is a no-no in production. 
openssl x509 -req -in server.req -CA ca.cer -CAkey ca.key -set_serial 100 -extfile openssl.cnf -extensions server -days 365 -outform PEM -out server.cer
rm server.req

 # Create the Client Key and CSR I made a client.cnf file for attributes to match the client
openssl genrsa -out client.key 2048
openssl req -config ./client.cnf -new -key client.key -out client.req

# Sign the client certificate with our CA cert. Unlike signing our own server cert, this is what we want to do. 
openssl x509 -req -in client.req -CA ca.cer -CAkey ca.key -set_serial 101 -extfile openssl.cnf -extensions client -days 365 -outform PEM -out client.cer
openssl pkcs12 -export -inkey client.key -in client.cer -out client.p12
rm client.key client.cer client.req
This is where I ran into problems with some of the tutorials. Testing with CURL to connect to NGINX worked based on the tutorial at nategood.com worked.

curl -v -s -k --key client.key --cert client.cert https://example.com

But connecting following the first apache tutorial did not and the second one needed some additional steps.

There seems to be 2 reasons why:
  • OS X Mavericks hacked up CURL to not work with client certificates - http://curl.haxx.se/mail/archive-2013-10/0036.html
  • CURL prefers certificates to be combined in PEM format with Data Bags included - http://honglus.blogspot.in/2012/03/fix-curl-client-certificate-error-curl.html

# Install CURL via Homebrew (assuems you have brew installed and up to date) openssl is not required but the OS X version is old 
brew install openssl curl

# Convert the certificate to pkcs12 and back to pem 
openssl pkcs12 -in client.p12 -out client.pem -clcerts

Here is the apache config
...
SSLCACertificateFile /var/www/conf/ssl.crt/ca.crt
...
    SSLRequireSSL 
    SSLVerifyClient require 
    SSLVerifyDepth 10 

... 
Now I can connect with (NOTE: do not use the built in curl)
/usr/local/Cellar/curl/7.33.0/bin/curl -v -s -k --key client.pem --cert client.pem https://example.com