Ssl – Certificate Authentication from Salesforce.com through a reverse proxy

apache-2.2authenticationreverse-proxyssl

I am attempting to allow Salesforce.com to connect to a biztalk instance that sits inside our corporate network. In between, is a reverse proxy and a series of firewalls.

When a standard HTTP request is made against the reverse proxy, the biztalk server responds correctly. It is important to note, that the reverse proxy itself appears to be working correctly.

What I need to do is enable security, limiting access to this web service to authorized clients. Initially, this is just Salesforce.com.

Salesforce.com has provided their SSL Certificate for authentication, andI have placed this certificate in the httpd.conf file with the SSLCACertificateFile Directive.

    SSLVerifyClient require
    SSLVerifyDepth 1
    SSLCACertificateFile /opt/apache/veri/auth.crt

When SalesForce connects and these directives are in use, the error "javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated" is generated.

Removing the SSLVerifyClient require, and normal operations resume.

Best Answer

Here's the problem:

SSLCACertificateFile /opt/apache/veri/auth.crt

As you can see in the apache documentation, SSLCACertificateFile means the path to the issuing CA certificate for the client certificate, not to the client certificate itself. There is no way to require a particular client certificate as such. What you can do, however, is to require that the certificate be issued by a particular CA and then verify the CN of the certificate.

So, you need to ask your client to send you the public part of the certificate that signed their certificate. You also need to check what CN their certificate contains:

$ openssl x509 -in path/to/clientcert.crt  -noout -text|grep Subject|grep CN
        Subject: C=US, ST=Something, L=Something, O=Organization Name, OU=SomeOU, CN=host.name.example.com

Then change your configuration to look like this:

SSLVerifyClient require
SSLRequire %{SSL_CLIENT_S_DN_CN} eq "host.name.example.com" 
SSLVerifyDepth 1
SSLCACertificateFile /opt/apache/veri/auth.crt

This tells Apache that it will accept an SSL connection but only if the hostname in the certificate is host.name.example.com and the certificate has been signed by the certificate authority whose certificate is in /opt/apache/veri/auth.crt.

There is more information at the mod_ssl documenation at Apache with several examples of how you can use SSLRequire to test for variables in client certificates.