In the IVOA security standards, requests to RESTful service can be authenticated by HTTPS with client certificates. This is the less-common form of HTTPS authentication in which the client is authenticated to the service. The authentication is performed by the web-server; for Java web-services this is typically Apache Tomcat.
The IVOA use of HTTPS matches the IETF standards except for two points:
These extra requirements mean that HTTPS code in the JDK, and in web servers is insufficient for the IVOA standard. The security facade provides classes to fix this.
The details in HTTPS in the client are handled by the JDK class java.net.HttpsURLConnection, which can be obtained from a java.net.URL for an HTTPS URL.
import java.net.URL; import java.net.HttpsURLConnection; URL u = new URL("https://some.where/some/thing"); HttpsURLConnection c = (HttpsURLConnection) u.openConnection();
The connection can now be set up to suit the IVOA standard using a SecurityGuard.
import org.astrogrid.security.SecurityGuard; SecurityGuard sg = new SecurityGuard(); sg.signOn(...); sg.configureHttps(c);
The signOn() call obtains the certificates and key needed to authenticate the connection. See the guide to signing on to the IVO for details.
The configureHttps() call does two things sets the HttpsURLConnection to trust all identity certificates sent to the client by the service. This effectively disables authentication of the service by the client. By doing so, it allows the client to work with self-signed server-certficates which would normally be rejected by the HttpsURLConnection.
The configureHttps() call also associates with the connection the certificate chain and key obtained by the SecurityGuard when the user signed on to the IVO. I.e., it authenticates the connection in the user's name, not with some arbitrary identity chosen by the JDK.
The configureHttps() call needs an HttpsURLConnection to set up the authentication. If it gets instead an HttpURLConnection (the superclass of HttpsURLConnection), then it does nothing and returns sliently. This is by design: it allows you to call configureHttps() on all HTTP connections without distinguishing the HTTPS ones in the application code.
The authentication is done by the web server before the web service is informed of the request. The service can receive the results of authentication in a specialized sub-class of SecurityGuard.
import org.astrogrid.security.HttpsServiceSecurityGuard; HttpsServiceSecurityGuard sg = new HttpsServiceSecurityGuard(); // request is the HttpServletReqiest passed by the servlet container sg.loadHttpsAuthentication(request);
If authentication was successful, the loadHttpAuthentication() call will load into the security guard
If the authentication was unsuccessful, then the guard will not contain the identity certificate and X500Principal. The certficate chain may or may not be present, depending on how the servlet container is configured. Note that failed authentication may cause the HTTPS request to be rejected without the web service being called at all. The web.xml configuration of the web application determines this.
The security-facade packages org.astrogrid.security.rfc3820.tomcat5 and org.astrogrid.security.rfc3820.tomcat6 contain an implementation of SSL that supports RFC3820 (proxy certificates). This can be added to a Tomcat installation to bring that installation up to IVOA standards. The former package works with Tomcat 5.5 and the latter with Tomcat 6.0.
The SSL code is an intimate part of the Tomcat server and the jars must be added to the Tomcat installation itself. For Tomcat 5.5, put the jars in Tomcat's server/lib directory. For Tomcat 6.0, put them in Tomcat's lib directory. Simply including the jars within a web-application doesn't work.
The following jars must be added.
Previous versions of the security library needed Globus and Crytix jars. Starting with v2010.1, these are no longer needed for the SSL implementation and should be removed from Tomcat. (Classes in those jars are still needed by some other parts of the security libary and the jars should not be removed from web applications.)
Operation of HTTPS with client authentication requires two sets of cryptographic credentials: a private key and identity-certficate for the host; and a set of trust anchors against which to check the client credentials. There are many ways to encode these, but Tomcat only supports a few options. The SSL implementation in the security facade supports the same encodings as standard Tomcat.
All the installed credentials must be in key-store files of JKS format (binary ".jks" files). PKCS#12 format (binary ".p12" files) is not supported, nor is the PEM format (the one with listable, base-64 encoded credentials, as used by OpenSSL). The host credentials may be in the same key-store as the trust anchors, or the trust anchors may be in one key-store and the host credentials in another. The credentials may not spread across more than two key-stores, and the host's private key and certificate must be in the same keystore.
In a JKS store, each credential entry has an "alias" which must be known to retrieve the credentials. An entry under one alias may be the private key and certificate for a party - the host, in this case - or the trust anchor for one certificate authority.
Tomcat needs to be able to pick out the entry for the host credentials. The default alias for these is "tomcat". If they are stored under a different alias then that alias must be declared when configuring Tomcat. Tomcat does not care what aliases are set for the trust-anchor entries.
JKS stores have passwords to protect the credentials. Tomcat expects to unlock the store or stores with a password. The default password is "changeit". If a different password is set, then it must be declared in the Tomcat configuration. If two key-stores are used the password should be the same for both.
Private keys within JKS stores may encrypted and the encryption unlocked by a own password. Tomcat expects either that the host's private key does not have a password or that the key-encryption password is the same as the password for the store.
Tomcat must be configured to use the AstroGrid implementation. Simply adding the extra jars to Tomcat does not activate the extra code.
In Tomcat's server.xml file, there are Connector elements. Typically, there will be one HTTP connector bound to port 8080. For HTTPS, there must be another connector bound to another port, 8443 by default. For an HTTPS connection with the RC3820 support, the configuration follows this pattern.
<Connector port="8443" acceptCount="100" connectionTimeout="20000" disableUploadTimeout="true" maxSpareThreads="75" maxThreads="150" minSpareThreads="25" scheme="https" secure="true" clientAuth="true" sslProtocol="TLS" SSLEnabled="true" keystoreFile="/home/agrid/ag01.jks" truststoreFile="/home/agrid/ag01.jks" SSLImplementation="org.astrogrid.security.rfc3820.tomcat5.JSSEImplementation"/>
for Tomcat 5.5, or
<Connector port="8443" acceptCount="100" connectionTimeout="20000" disableUploadTimeout="true" maxSpareThreads="75" maxThreads="150" minSpareThreads="25" scheme="https" secure="true" clientAuth="true" sslProtocol="TLS" SSLEnabled="true" keystoreFile="/home/agrid/ag01.jks" truststoreFile="/home/agrid/ag01.jks" SSLImplementation="org.astrogrid.security.rfc3820.tomcat6.JSSEImplementation"/>
for Tomcat 6.0.
The SSLImplementation attribute names the class that introduces the SSL implementation. If this attribute is ommited (or misspelt!) then Tomcat defaults silently to its native implementation.
The other important attributes work as follows.
The documentation for the Tomcat SSL implementation offers attributes to configure the type of store, implying that PKCS#12 stores can be used. This doesn't work (as of Tomcat 5.5.20) in either Tomcat's implementation or the AstroGrid extension.