Skip to content

How to Record and Replay an HTTPS Transaction

Shangshang Feng edited this page Mar 8, 2017 · 3 revisions

The process for recording and replaying an HTTPS transaction with Flashback is very similar to that used for HTTP transactions. However, special care needs to be given to the security certificates used for the SSL component of HTTPS. In order for Flashback to act as a man-in-the-middle proxy, it is necessary to create a Certificate Authority (CA) certificate. This certificate will be used during the creation of the secure channel between client and Flashback, and will allow Flashback to inspect the data in HTTPS requests it proxies. This certificate should then be stored as a trusted source so that the client will be able to authenticate Flashback when making calls to it.

For instruction on how to create a certificate, wed found the following resource to be quite helpful: https://jamielinux.com/docs/openssl-certificate-authority/introduction.html.

Once the security certificate is accounted for, the only difference between HTTP and HTTPS in terms of setup for recording is the addition of a few additional parameters. rootCertificateInputStream: this can be either a stream or file path that indicates the CA certificate’s filename rootCertificatePassphrase: this is the passphrase created for the CA certificate. certificateAuthority: these are the CA certificate’s properties

The code used to record an HTTPS transaction with Flashback, including the above terms, is below.

// Specify scene file path
String filePath = "/hello/world/flashback";
String sceneName = "playbackMe";
SceneMode sceneMode = SceneMode.RECORD;
//Optional
String proxyHost = "localhost";
int port = 1234;
//This three fields are required to record/playback Https traffic
InputStream rootCertificateInputStream = ...;
String rootCertificatePassphrase = "";
CertificateAuthority certificateAuthority = ...;

// Create scene config which contains most of scene properties
SceneConfiguration sceneConfiguration = new SceneConfiguration(filePath, sceneMode, sceneName);

// Initialize FlashbackRunner with Scene, MatchRule etc
try (FlashbackRunner flashbackRunner = new FlashbackRunner.Builder()
     .host(proxyHost)
     .port(port)
     .rootCertificateInputStream(rootCertificateInputStream)
     .rootCertificatePassphrase(rootCertificatePassphrase)
     .certificateAuthority(certificateAuthority)
     .mode(sceneMode)
     .sceneAccessLayer(
    new SceneAccessLayer(SceneFactory.create(sceneConfiguration), MatchRuleUtils.matchEntireRequest()))
     .build()) {
  flashbackRunner.start();

  //Write client code below 
  //Before you start, make sure client code is running in the process that 
  //point to trust store which can trust certificate that signd by CA certificate
  //you created.
  System.setProperty("javax.net.ssl.trustStore", "dummy cert store");
  System.setProperty("javax.net.ssl.trustStorePassword", "dummy password");
  //Client code can be as simple as any standard Http call. I use Apache HttpClient as an example.
  //Just make sure your request go through proxy that we specified above(host, port)
  HttpHost host = new HttpHost(proxyHost, port);
  String url = "https://www.google.com/";
  HttpClient client = HttpClientBuilder.create().setProxy(host).build();
  HttpGet request = new HttpGet(url);
  HttpResponse httpResponse = client.execute(request);
  //End of client code
}

Then you can verify HTTPS transaction from the scene in the location you specified

{
  "NAME" : "playbackMe",
  "HTTPEXCHANGELIST" : {
    "HTTPEXCHANGE1" : {
      "UPDATETIME" : "28 Jul 2016 19:22:17 GMT",
      "HTTPREQUEST" : {
        "HTTPMETHOD" : "GET",
        "HTTPURI" : "https://www.example.org/",
        "HTTPHEADERS" : {
          "Host" : "www.example.org",
          "Proxy-Connection" : "Keep-Alive",
          "Connection" : "Keep-Alive",
          "User-Agent" : "Apache-HttpClient/4.3.1 (java 1.5)",
          "Accept-Encoding" : "gzip,deflate"
        },
        "BINARYHTTPBODY" : ""
      },
      "HTTPRESPONSE" : {
        "HTTPSTATUSCODE" : 200,
        "HTTPHEADERS" : {
          "X-Cache" : "HIT",
          "Server" : "ECS (ewr/1445)",
          "Last-Modified" : "Fri, 09 Aug 2013 23:54:35 GMT",
          "Date" : "Thu, 28 Jul 2016 19:22:17 GMT",
          "Accept-Ranges" : "bytes",
          "Cache-Control" : "max-age=604800",
          "Etag" : "\"359670651+gzip\"",
          "x-ec-custom-error" : "1",
          "Content-Encoding" : "gzip",
          "Vary" : "Accept-Encoding",
          "Expires" : "Thu, 04 Aug 2016 19:22:17 GMT",
          "Content-Length" : "606",
          "Content-Type" : "text/html"
        },
        "ENCODEDHTTPBODY" : {
          "HTTPBODYENCODING" : "gzip",
          "STRINGHTTPBODY" : "<!doctype html>\n<html>\n<head>\n    <title>Example Domain</title>\n\n    <meta charset=\"utf-8\" />\n    <meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <style type=\"text/css\">\n    body {\n        background-color: #f0f0f2;\n        margin: 0;\n        padding: 0;\n        font-family: \"Open Sans\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n        \n    }\n    div {\n        width: 600px;\n        margin: 5em auto;\n        padding: 50px;\n        background-color: #fff;\n        border-radius: 1em;\n    }\n    a:link, a:visited {\n        color: #38488f;\n        text-decoration: none;\n    }\n    @media (max-width: 700px) {\n        body {\n            background-color: #fff;\n        }\n        div {\n            width: auto;\n            margin: 0 auto;\n            border-radius: 0;\n            padding: 1em;\n        }\n    }\n    </style>    \n</head>\n\n<body>\n<div>\n    <h1>Example Domain</h1>\n    <p>This domain is established to be used for illustrative examples in documents. You may use this\n    domain in examples without prior coordination or asking for permission.</p>\n    <p><a href=\"http://www.iana.org/domains/example\">More information...</a></p>\n</div>\n</body>\n</html>\n"
        }
      }
    }
  }
}

Replaying an HTTPS transaction with Flashback uses the same process as recording. The only difference being that the scene mode is set to “playback”. This is demonstrated by the code below.

// Specify scene file path
String filePath = "/hello/world/flashback";
String sceneName = "playbackMe";
SceneMode sceneMode = SceneMode.PLAYBACK;
//Optional
String proxyHost = "localhost";
int port = 1234;
//This three fields are required to record/playback Https traffic
InputStream rootCertificateInputStream = ...;
String rootCertificatePassphrase = "";
CertificateAuthority certificateAuthority = ...;

// Create scene config which contains most of scene properties
SceneConfiguration sceneConfiguration = new SceneConfiguration(filePath, sceneMode, sceneName);

// Initialize FlashbackRunner with Scene, MatchRule etc
try (FlashbackRunner flashbackRunner = new FlashbackRunner.Builder()
     .host(proxyHost)
     .port(port)
     .rootCertificateInputStream(rootCertificateInputStream)
     .rootCertificatePassphrase(rootCertificatePassphrase)
     .certificateAuthority(certificateAuthority)
     .mode(sceneMode)
     .sceneAccessLayer(
    new SceneAccessLayer(SceneFactory.create(sceneConfiguration), MatchRuleUtils.matchEntireRequest()))
     .build()) {
  flashbackRunner.start();

  //Write client code below 
  //Before you start, make sure client code is running in the process that 
  //point to trust store which can trust certificate that signd by CA certificate
  //you created.
  System.setProperty("javax.net.ssl.trustStore", "dummy cert store");
  System.setProperty("javax.net.ssl.trustStorePassword", "dummy password");
  //Client code can be as simple as any standard Http call. I use Apache HttpClient as an example.
  //Just make sure your request go through proxy that we specified above(host, port)
  HttpHost host = new HttpHost(proxyHost, port);
  String url = "https://www.google.com/";
  HttpClient client = HttpClientBuilder.create().setProxy(host).build();
  HttpGet request = new HttpGet(url);
  HttpResponse httpResponse = client.execute(request);
  //End of client code
}

Clone this wiki locally