Googleが提供しているサービスの1つに、Google App Engine(GAE)があります。ユーザーがJava言語、またはPython言語で開発したWebアプリケーションを、Googleのインフラで動作させることができるサービスです。どのようなアプリケーションでも動作させることができるわけではなく、一部機能制限があります。
この記事では、Java言語でのセキュリティー関連プログラミングでのハマりどころについて、まとめてみたいと思います。
GAEはある程度まで無料で使えますが、アプリケーションのリクエスト数、通信帯域、CPU時間などのリソース消費が一定量を超える場合、課金対象となります(予めリソースを購入しておかないとエラーになります)。このような課金管理のためもあってか、GAEでは一見意外に見える機能に、利用制限がかかっています。
GAEのJava環境の制限
GAEのJava環境の制限については、Java サーブレット環境のページにまとまっています。
まず、新規にプロセスやスレッドを生成することはできません。アプリケーションで明示的に生成しようとするとエラーになりますし、利用ライブラリがスレッドを生成するようなものだった場合もエラーになります。またファイルへの出力はできません(アプリケーションに含めた定義ファイルなどの読み込みはOK)。他ホストへのソケット通信も一部に限定されます。
その他制限として特徴的なのは、Java標準ライブラリのうち、アプリケーションで利用可能なクラスがホワイトリストとして定義されていることです。このリストに載っていないクラスは、利用できません。
このホワイトリスト方式、セキュリティー的には良いことなんですが、困ることもあります。さて我々があるアプリケーションを作りたくなったとして、そこで利用するクラスはGAEで使えるのでしょうか。この長大なリストに含まれていればOKなんですが。。。しかし、いちいち目視チェックなんてできませんね。
また、「クラスは利用できません」とは言っても、実際にそのことが判明するのは、GAE上でアプリケーションを動作させ、まさにそのクラスを利用しようとしたタイミングです。GAE用のSDKを使ってローカルで開発・動作させている段階では問題なく動作してしまいますし、GAE上に配備してからも、動作中にそのクラスを読み込まない限りはエラーになりません。というわけで、ハマりどころを知らないと、開発時に苦労することになります。
ハマりどころ
そこで過去、GAE用のJava言語でのセキュリティー関連ライブラリ、アプリケーションを開発してきて、ハマったところについて整理してみました。開発の参考にしてください。
-
SSL関連クラスに注意
-
java.net.ssl.*はホワイトリストに載っていないので、使えません。 クラスを読み込もうとしたタイミングで、SecurityException例外が上がります。他ホストへのソケット通信が基本的に制限されている(Googleが用意した専用API経由でのみ許可されている)ので、自身がGAE用に開発するアプリケーションでSSLが使えないのは当たり前なのですが、利用するライブラリでSSL関連クラスを読み込んでいたりすると、読み込んだタイミングでエラーになります。
-
AES鍵長192bitは使えません
-
一般にJava動作環境にはデフォルトで、一部の国向けの米国輸出規制対策として、鍵長他の制限が入っています。通常の開発であれば、例えばSunのJava動作環境であれば「JCE Unlimited Strength Jurisdiction Policy Files」を追加ダウンロードし、制限を解除して使うのですが、GAEのJava環境ではその制限がかかったままのようです。そのためAESに限らず、128bitより長い鍵長は利用できません。3DESはOKです。
-
JCEプロバイダ追加は可能です
-
java.security.Securityがホワイトリストに載っているので、java.security.Security.addProviderによるプロバイダ追加が可能なのは当たり前ですが、Web上で「GAE上でJCE Providerは使えない」と書いている例も見られるので一応。例えばBouncyCastleプロバイダを追加して利用することもできます。
ただし、フル機能が使えない場合はあります。私が把握しているのは、ひとつ前に書いた輸出規制対策に触れてしまう場合です。例えばAdd support for BouncyCastle JCE providerで書かれている問題は、おそらくこれ(128bitより長い鍵長を利用しようとして内部エラーになっている)だと思います。逆にいえば、これにひっかからない限り、問題なく使えるはずです。
(2010-04-21追記:ここから)
この項目ですが、確認方法が間違っていました。(少なくとも現時点で)JCEプロバイダ追加はできません。私の勘違いでした。
java.security.Security.addProviderがOKても、その前にjava.security.Provider(のサブクラスであるBouncyCastleProviderなど全てのJCE provider)を インスタンス化する際、"putProviderProperty.XX"名義のアクセスチェックで、 SecurityException例外が上がります。 GAEのJava環境では独自のセキュリティーマネージャーがインストールされて起動するのですが、 セキュリティーポリシーとして、putProviderPropertyとinsertProviderなど、providerが必要とする権限が付与されていません。そのためjarとしてBouncyCastleの機能を利用することはできても、JCE providerとして利用することはできません。 上記Add support for BouncyCastle JCE providerも報告者の指摘通りです。 私が確認した時は、providerの生成で不用意に例外を無視してしまっており、指定のprovider機能が使われず、確認になっていませんでした。。。
現時点では、GAEにデフォルトでインストールされているJCE providerを使うしかありません。何が使えるかについては、追って調査の上、記事にしたいと思います。
(追記ここまで)
ちなみに「SSL禁止」は徹底していて、現時点では、"ssl"という文字列を含むアプリケーションを作ることができません。「sarion-ssl.appspot.com」「java-openssl.appspot.com」などのアプリケーションを登録しようとすると、すべて、取得済みなどの理由でその名前は使えない、というエラーになります。さすがに取得済みということはないはずなので、制限がかかっているようです。
こんなところまで。。。とも思いますが、「https://ssl-foobar-bank.appspot.com/」というアプリケーションが作られると困るなど、何か理由があるのかもしれません。(とはいえ、問題になりそうもないので、深い理由があるわけではないと思います)



コメント