KotlinでgRPC。grpc-javaのTLS with JDKとTLS with OpenSSLの使い方をまとめた。


grpc-java/SECURITY.mdを読み進めるとTLSを有効にしたgRPCサーバの起動には2つのプロトコルプロバイダーを選択できる。 JDKOpenSSLがその2つである。それぞれを有効にする方法は異なりドキュメントも豊富ではない。この機会にまとめていきたいというのが今回のモチベーション。

TLS with JDK

まずはJDKからみていきたい。grpc-java/SECURITY.mdにも記載があるとおり、この方式は推奨されていない。 JavaのTLS実装にALPNがサポートされるのはJava9からでありJava8(Java < 8)を利用している場合は、JVMオプションにjavaagentを加える。加えたjavaagentjetty-alpn-agentを指定する。 起動までの流れとしては次ようになる。

1
2
3
4
mkdir -p /var/lib
wget -q -O /var/lib/jetty-alpn-agent.jar https://repo.maven.apache.org/maven2/org/mortbay/jetty/alpn/jetty-alpn-agent/2.0.6/jetty-alpn-agent-2.0.6.jar

java $JAVA_OPTS -javaagent:/var/lib/jetty-alpn-agent.jar -jar /usr/local/your-project/lib/app-name.jar

これでTLS with JDKで起動できる。

TLS with OpenSSL

次にOpenSSLである。grpc-java/SECURITY.mdにも記載があるとおりstaticなnetty-tcnativeを使わない場合はOpenSSL version >= 1.0.2Apache APR library (libapr-1) version >= 1.5.2.が必要になる。 DockerコンテナでJVMを起動する場合は事前にインストールをしておく。

1
apt-get install -y ca-certificates openssl libc6 libapr1

libc6はprotoBufferを生成する際に必要となる。コンテナ起動時にビルドのタスクに.protoからprotoBufferを生成している。

OpenSSLのハマりポイントがありalpineをコンテナイメージのベースにしていたが上手く起動できなかった。ubuntuベースにするとサクッと起動した。 alpineで起動すると次のようなエラーに遭遇する。netty-tcnativeを使うためにalpineで何かが足りていないのだろう。今後深追いしていきたい。

1
2
3
4
5
6
7
8
Caused by: java.lang.UnsatisfiedLinkError: /tmp/libnetty-tcnative3270913869898400045.so: Error relocating /tmp/libnetty-tcnative3270913869898400045.so: SSL_add0_chain_cert: symbol not found
        at java.lang.ClassLoader$NativeLibrary.load(Native Method)
        at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941)
        at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1824)
        at java.lang.Runtime.load0(Runtime.java:809)
        at java.lang.System.load(System.java:1086)
        at io.netty.util.internal.NativeLibraryUtil.loadLibrary(NativeLibraryUtil.java:36)
        ... 21 more

ubutuを許容できるのであればubuntuベースでOpenSSLを利用するのがよさそう。

最後に必要なnetty-tcnativeはドキュメントのGetting netty-tcnative from Gradleが参考になる。

これでTLS with OpenSSLが起動できる。

JDKとOpenSSLを有効にしたDockerfileをまとめた

ここまでJDKOpenSSLについてまとめてきたがコードの断片しかなく参考にならないため、それぞれのDockerfileと動作確認環境をシュッと起動できるdocker-composeをまとめたので詳細はgithubを参照してほしい。

READMEに動作確認手順をまとめているが、docker-composeでJDKとOpenSSLが有効になったgRPCサーバを起ち上げ、gRPCクライアントを含むアプリの起動時にサーバの環境変数を切り替えている。

ここまでgrpc-javaについて触れていたけどgithubに置いているコードはkotlinで書いている。適宜javaに置き換えて参照いただきたい。

grpc-javaはそこまでドキュメントが豊富とは言いづらい。積極的にアウトプットしていきたい。