5000164 is here
My writing is my life.
Scala の SSL / TLS 通信の中身を見る

Scala の通信の中身が見たい

Scala で API を叩くコードを書いた。
ちゃんと API を叩けているのか知りたい、リクエストとレスポンスが見たいと思った。

プロキシーを通す

  • Charles を使う

    • Postman も試してみたけどレスポンスが自動保存されないっぽい気がして、連続で API を叩いて内容がどんどん変わっていく今回の用途では使えなかった
  • HTTP 通信のライブラリとして sttp を使用していたので プロキシーの設定方法 を参考にして下記のように設定する

    • HttpURLConnectionBackend のデフォルト引数が options: SttpBackendOptions = SttpBackendOptions.Default となっていて、なにも設定しなければシステムのプロキシー設定を反映してくれるので HttpURLConnectionBackend(options = SttpBackendOptions.httpProxy("localhost", 8888)) というように明示的に設定する必要はなかった

      • Charles は起動時に自動でシステムのプロキシー設定を書き換えてくれるので、設定がそのまま反映される
val backend: SttpBackend[Id, Nothing] = HttpURLConnectionBackend()

これだけで、 HTTP 通信の中身は見られるようになる。

SSL / TLS 通信の中身を見えるようにする

SSL / TLS 通信の中身を見るための手順としては

  • Charles の証明書を信頼したキーストアを生成する
  • 生成したキーストアをアプリケーションから読み込む
  • Charles の SSL Proxy を有効にする

となる。

Charles の証明書を信頼したキーストアを生成する

まず Charles の証明書を取得する。
これはアプリケーションのメニューの Help > SSL Proxying > Save Charles Root Certificate... から取得できる。
拡張子は Binary certificate (.cer) で保存する。
保存したら取得した証明書を信頼したキーストアを生成する。
この時に普段使用されるキーストアを別の場所にコピーしてから作業を行うことで環境を汚さないようにした。
普段使用されるキーストアは jdk の中にあり、自分の場合は $(/usr/libexec/java_home)/lib/security/cacerts にあった。

keytool -keystore cacerts -importcert -alias charles -file charles-ssl-proxying-certificate.cer

また、この時に keytool -list -keystore cacerts のようにして内容を表示して追加されたかどうか確認することができる。

生成したキーストアをアプリケーションから読み込む

先ほど作成したキーストアをアプリケーションから読み込む。
実行環境としては IntelliJ IDEA で Scala を動かしている。
設定方法が環境変数に指定する方法しかわからなかったので環境変数に設定を行う。
下記のような内容を実行時の VM parameters に設定する。

-Djavax.net.ssl.keyStore=/path/to/cacerts -Djavax.net.ssl.keyStorePassword=changeit -Djavax.net.ssl.trustStore=/path/to/cacerts -Djavax.net.ssl.trustStorePassword=changeit

/path/to/cacerts には先ほど作成したキーストアへのパスを指定する。

2018.5.28 追記

sbt から実行する場合は

SBT_OPTS="-Djavax.net.ssl.keyStore=/path/to/cacerts -Djavax.net.ssl.keyStorePassword=changeit -Djavax.net.ssl.trustStore=/path/to/cacerts -Djavax.net.ssl.trustStorePassword=changeit" sbt run

のようにする。

Charles の SSL Proxy を有効にする

証明書を設定することで通信を行えるようにはなるが、このままでは通信の内容を見ることはできない。
通信の内容を見るために Charles の SSL Proxy の設定を有効にする。
メニューの Proxy > SSL Proxying Settings... から設定画面を開き、 Enable SSL Proxying を有効にして対象のドメインを追加する。
これで SSL / TLS の通信の内容を見ることができるようになる。

感想

なにをどうすれば通信の中身が見えるようになるのか全然わからない状態で調べ始めたけど、調べたらなんとかなってよかった。
通信の中身が見えるの便利。

ハマったことのメモ

  • Scala に javaOptions を設定する方法がわからなかった

    • build.sbt に書いても動かなかった

      • IntelliJ IDEA 経由で実行してたからっぽい? sbt run したら動いた
  • 下記の方法で javaOptions の中身が表示できるけど仕組みはわかってない

    • これのおかげで javaOptions に設定できたと思ってたけどできてなかった、というところが問題だと気付くことができた
// import what we need
import java.lang.management.ManagementFactory

import scala.collection.JavaConverters._

// get a RuntimeMXBean reference
val runtimeMxBean = ManagementFactory.getRuntimeMXBean

// get the jvm's input arguments as a list of strings
val listOfArguments = runtimeMxBean.getInputArguments.asScala

// print the arguments using my logger
for (a <- listOfArguments) println(s"ARG: $a")

参考になったリンク