Scala

Two-way SSL (client certificates) with Scalatest

At work we recently added the option to authenticate machine to machine communication using client certificates (two-way ssl). While this was relatively easy to set up and access programatically from different programming languages, we ran into some difficulties getting our integration test up and running. We wanted to have a couple of tests to make sure the information from the certificate was correctly parsed and mapped to an internal client id, and how the system reacts to invalid certificates and a couple of other edge cases.

Since we use Scalatest for all our integration testing we just wanted to add the private keystore and the trust store to scalatest and be done with it. However, the standard fluent API provided by Scalatest doesn’t offer it (or we couldn’t find it). After some looking around we came to the following setup which works for us in our integration test suite:

import java.io.{File, FileInputStream}
import java.security.KeyStore

import com.jayway.restassured.RestAssured
import com.jayway.restassured.config.SSLConfig
import com.jayway.restassured.http.ContentType
import com.jayway.restassured.response.Response
import org.apache.http.conn.ssl.{SSLConnectionSocketFactory, SSLSocketFactory}
import org.scalatest._

object SSLTest {

  def doSSLTest() = {

    // load the corresponding keystores
    val privateKeyStoreLocation = new FileInputStream(new File("src/test/resources/keystores/testing-client.p12"));
    val keyStore = KeyStore.getInstance("PKCS12");
    keyStore.load(privateKeyStoreLocation, "secret".toCharArray());

    val certKeyStoreLocation = new FileInputStream(new File("src/test/resources/keystores/ca-chain.cert.jks"));
    val trustStore = KeyStore.getInstance("jks");
    trustStore.load(certKeyStoreLocation, "secret".toCharArray());

    // manually create a new sockerfactory and pass in the required values
    val clientAuthFactory = new org.apache.http.conn.ssl.SSLSocketFactory(keyStore, "secret", trustStore);
    // don't check on hostname
    clientAuthFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

    // set the config in rest assured
    val config = new SSLConfig().`with`().sslSocketFactory(clientAuthFactory).and().allowAllHostnames();
    RestAssured.config = RestAssured.config().sslConfig(config);

    RestAssured
      .given.contentType(ContentType.JSON)
      .when
      .request
      .post("https://theurl")
  }



}

Note that some of these classes are actually deprecated, and could be replaced with other relevant classes from the apache commons library used here.

Reference: Two-way SSL (client certificates) with Scalatest from our JCG partner Jos Dirksen at the Smart Java blog.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button