Pythonアプリでのメールヘッダーインジェクション対策について

Pythonでメール送信機能を実装する場合、標準ライブラリであるsmtplibを利用することが最も一般的な方法のようです。以下のような関数をつくって、それを呼び出せばメールが送信できます。

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

def sendEmail(mail_to, mail_from, subject, content):
    msg = MIMEMultipart('alternative')
    msg['To'] = mail_to
    msg['From'] = mail_from
    msg['Subject'] = subject
    msg.attach(MIMEText(content))

    smtp_server = smtplib.SMTP('smtp.gmail.com', port=587)
    smtp_server.starttls()
    smtp_server.login('xxxxxxxx@gmail.com', 'xxxxxxxx')
    smtp_server.sendmail(mail_from, mail_to, msg.as_string())

簡単ですが、これで問題はないのでしょうか。メールヘッダーインジェクションの脆弱性に配慮する必要はないのでしょうか?


ということで、調べてみました。まずは、正常なメール送信の動作確認のために、以下の実装のスクリプトをつくって(sendmail.pyというファイル名にしました)、メールを送信してみましょう。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

def sendEmail(mail_to, mail_from, subject, content):
    msg = MIMEMultipart('alternative')
    msg['To'] = mail_to
    msg['From'] = mail_from
    msg['Subject'] = subject
    msg.attach(MIMEText(content))
    smtp_server = smtplib.SMTP('localhost', port=2525)
    smtp_server.sendmail(mail_from, mail_to, msg.as_string())

print("Sending an Email.")
try:
    sendEmail('to@example.com', 'from@example.com', 'Test', 'Mail Header Injection Test')
    print("Complete.")
except Exception as e: 
    print("ERROR:" + str(e))

と、その前に、メール送信のために、SMTPサーバーが必要です。今回は単なる検証目的なので、FakeSMTPというテスト用途のSMTPサーバーを使用します。Javaで実装されているので、WindowsでもLinuxでも同様に簡単に起動します。ここからダウンロードして、以下のコマンドで実行します。

$ java -jar fakeSMTP-2.0.jar -s -p 2525

この場合、2525番のポートでSMTPサーバーを起動します。

起動したら、先程作成したsendmail.pyを実行してメールを送信します。

$ python sendmail.py

問題がなければ、「Sending an Email.」、「Complete.」と表示されて、以下のようにFakeSMTPサーバーにメールが送信されているはずです。

Screenshot from 2018-05-09 14-53-26

メールをクリックすると、内容が確認できます。見てのとおり、特に問題はありません。

            Wed, 09 May 2018 14:51:50 +0900 (JST)
Content-Type: multipart/alternative;
 boundary="===============7314347251575062497=="
MIME-Version: 1.0
To: to@example.com
From: from@example.com
Subject: Test

--===============7314347251575062497==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit

Mail Header Injection Test
--===============7314347251575062497==--

では、メールヘッダーインジェクションの脆弱性を攻撃できるか検証してみましょう。

sendmail.pyの次の行を、

sendEmail('to@example.com', 'from@example.com', 'Test', 'Mail Header Injection Test')

次のように変更します。

sendEmail('to@example.com', 'from@example.com', 'Test\nbcc: all@example.com', 'Mail Header Injection Test')

件名「Test」の後に、「\nbcc: all@example.com」を追加することで、改行を入れてメールヘッダーとしてbccを追加できるか確認してみます。これができれば、メールヘッダーインジェクションの脆弱性を攻撃される可能性があることになります(メールヘッダーインジェクションがどういうものかについては、いろいろなサイトで解説されているので、このページでは言及しません)。ちなみに、all@example.comはメールが受信可能な適当なメールアドレスと考えて下さい。

では、再度sendmail.pyを実行してメールを送信します。

$ python sendmail.py

新しいバージョンのPythonを使用している場合は、以下のように表示されるはずです(このブログではPython 3.6を使用しています)。

$ python sendmail.py
Sending an Email.
ERROR:header value appears to contain an embedded header: 'Test\nbcc: all@example.com'

メールヘッダー値に別のメールヘッダーを埋め込もうとしたことを検知した旨のエラーメッセージが出力されます。つまり、Python 3.6標準のsmtplibに対しては、メールヘッダインジェクションは攻撃できないということになります。

この検知機能は、いつから実装されているのでしょうか?

GitHubのPythonのリポジトリで、先程のエラーメッセージ「header value appears to contain an embedded header」を検索してみると、このコミットが見つかりました。どうやら、Python 3.1.4から実装されているようです。なので、3.1.3以前のバージョンを使っていなければ、問題は無さそうです(Python 2.x系も最新の2.7には実装(バックポート)されていました)。

ただし、調査していたときに気になるバグレポートを見つけました。

Issue#32606: Email Header Injection Protection Bypass

これによると、「bcc」と「:」の間に空白があるような値を使うことで、メールヘッダーインジェクションの脆弱性を攻撃できるとのことです。つまり、以下のうち前者は検知機能でエラーになるが、後者はスルーしてしまう、ということです。

・’Test\nbcc: all@example.com’ → エラー
・’Test\nbcc :all@example.com’ → スルー

では、さっそく検証してみましょう。sendmail.py'Test\nbcc: all@example.com'の箇所を'Test\nbcc :all@example.com'に修正して、実行します。

$ python2 sendmail.py
Sending an Email.
Complete.

送信できたようです。FakeSMTPが受信したメールをクリックすると、以下のように「bcc :all@example.com」はチェックされること無く、メールヘッダーに付加されてしまいました。

        Wed, 09 May 2018 16:35:27 +0900 (JST)
Content-Type: multipart/alternative;
 boundary="===============6879493970155011648=="
MIME-Version: 1.0
To: to@example.com
From: from@example.com
Subject: Test
bcc :all@example.com

--===============6879493970155011648==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit

Mail Header Injection Test
--===============6879493970155011648==--

ただし、先程のバグレポートのコメントにもあるように、RFC 5322ではメールヘッダーのキーの直後には「:」を付けるのが正しい仕様のようです。したがって、「bcc :all@example.com」付きのメールが送信されるかどうかは、SMTPサーバーがRFC 5322を正しく実装しているか次第ということになります。

ということで、SMTPサーバーが「bcc :all@example.com」を「bcc: all@example.com」と変わらず解釈してメールが送信できるかどうかを確認してみましょう。

例えば、GoogleのSMTPサーバーの場合はどうでしょうか?次のようにsendmail.pyを修正し、実行します。

smtp_server = smtplib.SMTP('smtp.gmail.com', port=587)
smtp_server.starttls()
smtp_server.login('xxxxxxxx@gmail.com', 'xxxxxxxx')

bcc宛にはメールが送信されませんでした。Googleはメールヘッダーの「bcc :all@example.com」を無視したことになります。

次に、MSNのSMTPサーバーを検証してみましょう。次のようにsendmail.pyを修正し、実行します。

smtp_server = smtplib.SMTP('smtp-mail.outlook.com', port=587)
smtp_server.starttls()
smtp_server.login('xxxxxxxx@hotmail.com', 'xxxxxxxx')

bcc宛にメールが送信されました。MSNはメールヘッダーの「bcc :all@example.com」をもとにall@example.comにメールを送信したことになります。

このように、RFCを正確に実装していないSMTPサーバーを利用しているPythonプログラムには、メールヘッダーインジェクションの脆弱性が存在するということが言えます。


ところで、何でこんなことを調べたかというと、以前公開したバグだらけのWebアプリケーションのDjango2ベースのクローンをつくっているからです。まだ開発途中ですが、メールヘッダーインジェクションも実装したので、興味がある方はぜひ、チェックしてみて下さい。

EasyBuggy clone built on Django

広告

Keycloakの内部DBにアクセスするには

Keycloakの内部DBにアクセスするにはどうすればいいでしょうか?簡単なので、その方法を紹介します(※今回はKeycloakの超小ネタです)。

その前に、Keycloakの内部DBについて簡単に説明します。Keycloakには、デフォルトでH2というRDBMSが組み込まれています。Keycloakを起動すると、このDBの中にKeycloakの管理コンソールで編集可能な設定データやユーザーデータが登録されます。ユーザーデータは外部のLDAPやActive Directoryで管理することもできますが、デフォルトはここで管理されます。

内部DBへのアクセス手順

任意のSQLクライアントでアクセスできると思いますが、H2には管理コンソールが付属しているので、これを使うのが簡単です。以下のコマンドを実行すると、ブラウザ上で操作可能なH2の管理コンソールが起動します。

$ cd keycloak/modules/system/layers/base/com/h2database/h2/main/
$ java -cp h2-1.4.193.jar org.h2.tools.Console

※h2-1.4.193.jarのバージョン部分は環境に応じて、変更して下さい。

このような画面が表示されるので、

2018-03-01 20.35.51 からのスクリーンショット

以下の値を入力して、「接続」ボタンをクリックして下さい。

入力項目
保存済設定 Generic H2 (Embedded)
設定名 Generic H2 (Embedded)
ドライバクラス org.h2.Driver
JDBC URL jdbc:h2:/opt/keycloak/standalone/data/keycloak;AUTO_SERVER=TRUE
ユーザ名 sa
パスワード sa

※「JDBC URL」は、環境やKeycloak(を起動するWildFly)の起動モードにより異なります。

接続してみると、テーブルがたくさんあることが分かります。テーブル名を見て分かるように、Keycloakの管理コンソールで設定した値はこれらのテーブルで管理されることになります。

2018-02-28 22.06.10 からのスクリーンショット

ちなみにスタンドアローン・モードの場合、KeycloakのDBアクセスの定義は、standalone/configuration/standalone.xmlにあります。

OpenAMはもはや「Open」ではないのか?

このブログでは、OpenAMについての記事を多く書いてきたのですが、ここ数ヶ月OpenAMの話題については触れていませんでした… というのも、OpenAMを開発しているForgeRock社が、昨年の春頃からOpenAMの公開を大幅に制限したことで、私のOpenAMに対するモチベーションが少し下がってしまったからです。

そのような状況のため、OpenAMはもはや「Open」ではないの?」と思われている方もいるかもしれませんが、そういうわけではありません。OpenAMはOSSです。このページからダウンロードして、利用することができます。CDDL 1.0ライセンスで、StashGItHubにソースコードも公開されています。

ただし、現在、ForgeRock社のサブスクリプションを購入せずに、ダウンロードサイトからダウンロードできるバージョンは、安定バージョンではないメジャーバジョンのみです(OpenAM 11.0.0/12.0.0/13.0.0、Web Agents 3.3.0/4.0.0/4.1.0、Java EE agents 3.1.0/3.3.0/3.5.0など)。また、これらのソースコードはStashに公開されていますが、一部の古いバージョンは公開されていません。安定バージョンはGitHubに公開されている11.0.3が最新です。

OpenAMの過去のメジャーバージョンのリリースは以下の通りでしたが、既に公開されていた13.5.0のソースコードも非公開となりました。

  • OpenAM 11.0.0 – 2013年11月
  • OpenAM 12.0.0 2014年12月
  • OpenAM 13.0.0 – 2016年1月
  • OpenAM 13.5.0 – 2016年7月

OpenAM 12.0.4のような安定バージョンや、新しいOpenAM 13.5.0を使用したい場合は、ForgeRock社のサブスクリプションを購入する必要があります(※私の理解が正しければ、サブスクリプションがなくても、以前ダウンロードした13.5.0のソースコードをビルドしていれば、それを利用することはできます、ただし、現在はMavenのリポジトリからOpenAM関連のライブラリが取得できないようになってしまっています…)。

OpenAM 14.0.0として開発されていたものは、「Access Management 5.0.0」という名称に変更され、2017年3月に非OSSとしてリリースされました。OpenではないAMということです。OpenAMの他にOpenDJなども同様で、以下のように「Open」が無くなり、バージョンは全て5.0.0に統一されています。

  • OpenAM 14.0.0 -> Access Manager 5.0.0
  • OpenDJ 4.0.0 -> Directory Services 5.0.0
  • OpenIDM 5.0.0 -> Identity Management 5.0.0
  • OpenIG 5.0.0 -> Identity Gateway 5.0.0

そして、このリリースは、ForgeRock社がビジネスモデルを変更したことも意味していました。もともとForgeRock社は、100%オープンソースを謳っていたんですが、100%オープンにすることのメリットよりもデメリットの方が大きいと判断したのではないかと想像しています。OpenAM(ForgeRock)が生き残るために必要な選択で、仕方なかったのかもしれません(実際のところは、私には分かりませんが)。

ForgeRock社のフォーラムに以下のようなコメントもありました。

Some ForgeRock sales reps gave me the heads up about this change, and they suggested it might have been due to integrators in Europe that create their own OpenAM releases based off the trunk which they sell themselves. I suppose this is similar to a RHEL/CentOS situation and that ForgeRock is trying to protect their investment as they are a 99% contributor of the source code, which is not the same for RHEL/CentOS.

莫大な費用をかけて、ForgeRock社がエンハンスするOpenAMを使って、何もコントリビュートしない外部の企業が利益を上げるという状況だったので、ForgeRock社とコミュニティはあまり良い関係性とは言えなかったと思います。2016年あたりから、ForgeRock社は徐々に非公開の範囲を増やしていきました。最初はマイナーバージョンのソースコードを非公開にし、ナイトリービルドのソースコードなども非公開にしていきました。そして、2017年の春には、外部のOpenAMユーザーがJIRAにバグを登録することすらできなくしました。

その当時の、OpenAMのユーザーの方とForgeRockのエンジニアであるPeterさんとの間で、以下のようなTwitterのやりとりがありました。

また、Stack Overflowでの「Is OpenAM free software?」という問いに対して、彼はこのような回答をしています。

これらの内容を要約すると、2017年4月3日以降は次のようなForgeRock版コミュニティ版に別れたことなります。

  • ForgeRock版
    • 前述の「Open」が付かない製品(Access Managerなど)
    • ソースコードは、オープンソースライセンスのもとでは提供されない
    • 使用するには、ForgeRock社のサブスクリプションを購入する必要がある
    • ForgeRockだけに属していないすべてのソースコード(例えば、Sunに属していたソースコード、またはオープンソースのコントリビューターが関わったソースコード)は、CDDLライセンスで継続して利用可能
    • 60日間のみ評価することができ
  • コミュニティ版
    • 「Open」が付く製品(OpenAMなど)
    • CDDL 1.0ライセンスのOSS
    • ソースコードはforgerock.github.ioに公開される
    • EOLとなったバージョンの最新メンテナンスリリースがForgeRock版の後にリリースされる予定
      • 今回は、AM5 -> OpenAM 11.0.3がリリースされた
      • 今後は、AM6 -> OpenAM 12.0.x、AM7 -> OpenAM 13.5.x、AM8 -> OpenAM 14.5とリリースされる予定(つまり、AMの最新バージョンがリリースされて約2年後にEOLとなってから、OpenAMとしてコミュニティ版がリリースされる)
    • 予定ではあるが、今後本当にそうなるかどうかは公言されているわけではない
    • メンテナンスリリースであるため、最初は安定しているが、その後のセキュリティパッチは提供されない

今後のOpenAMとのつきあい方

このブログを書いている際に次期バージョンがどうなるのか気になったので、Peterさんに聞いてみました。それによると、今年(2018年)の春に予定されている6.0.0リリースと同時に12.0.4もGitHubに公開される見込みだそうです(確約はできないようですが)。コミュニティ版のOpenAMが今後どのように公開されるのか不透明(というかForgeRock社次第)なので、未来のことについては明言は難しいですが、現状のOpenAMで事足りる場合は、継続してコミュニティ版を使ってもいいと考えます(脆弱性をどう対処するかによりますが)。何か困ったことがあれば、国内のOpenAMサポートをしている企業にサポートを依頼することもできます。私もサポートします。

Access Manager 5.0以降の新しい機能を使用したい場合や、脆弱性を早期に対策していきたいということであれば、ForgeRock社のサブスクリプションを購入する方がいいでしょう。ただし、結構高いです…

OpenAMのフォーク・プロジェクト

OpenAMがクローズな方向に進む中で、OpenAMをフォークしてOSSとして継続しようとする人たちも現れました。そして、このようなプロジェクトが立ち上がりました。そして、OpenAMは改名されて、GitHubに「WrenAM」という名前のOSSとして公開されました。

ただし、今のところ、このプロジェクトが軌道に乗っているようには見えません。状況をあまり把握できていないので、多くを語ることはできませんが、現時点では「うーん…」という印象です。

※注意:ライセンスなどに関して誤った理解があるかもしれません。正しい情報はForgeRock社にお問い合わせ下さい。

Cocha Iconsのトリセツ

先日、記事や設計書、プレゼン資料の作成に役立つネットワークアイコン集を公開しました。このアイコンは自由に使っていただいて構いませんが、悪用やセンスのひどすぎる使用は避けていただくようお願いします。以下に正しい使い方と誤った使い方の例を挙げておきます。

正しい使い方


グリッドを利用する

env.png

背景のグリッドを活用して適当な場所にアイコンを配置し、矢印はグリッドの方向に平行にしてください。

光の当たる方向を意識する

PowerPointの「左右反転」でアイコンの向きを変えることができます。

WS000024.JPG

ただし、光の当たる方向を意識して色を変更しないと統一感が崩れます。

gg.png

適当な大きさに拡大・縮小する

アイコンのサイズは適宜変更して下さい。

ss.png

動きをつける

jj.gif

動きをつけてみるのもいいと思います。動くバージョンのアイコンもいつか公開したいです。

誤った使い方


以下のような使い方はしないで下さい。

質感の異なるアイコンとの併用

ff.png

これはやめて欲しいです。

作者の意図に反する使い方

dd.png

できるだけ作者(私)の意図を汲んで下さい。

理解しがたい動きをつける

yrd

PowerPointってついつい遊んでしまいますよね…

遠近法の無視、悪用

big

部分的に巨大化しないで下さい。

犯罪にかかわる利用

vv.gif

ハッカーはインターネット・セキュリティの図説のみに利用して下さい。

最後に


使用する場合はGitHubにスターを付けて、以下の画像を作成物のどこかに付け加えていただくようお願いします。

mark.png

Qiitaの記事で使うのであれば、以下を本文の最後に埋め込んで下さい。

[![mark.png](https://github.com/k-tamura/cocha-icons/raw/master/mark.png)](https://github.com/k-tamura/cocha-icons)

HTMLの場合はこちら:

<a href="https://github.com/k-tamura/cocha-icons">
    <img src="https://github.com/k-tamura/cocha-icons/raw/master/mark.png" alt="mark.png" style="max-width:100%;">
</a>

TomcatのDBアクセスユーザーのパスワードを暗号化する

TomcatでDBにアクセスする場合、server.xmlcontext.xmlResource要素に以下のような設定をします。

<Resource name="jdbc/TestDB" auth="Container"
    type="javax.sql.DataSource"
    maxTotal="100" maxIdle="30" maxWaitMillis="10000"
    username="javauser" password="javadude"
    driverClassName="com.mysql.jdbc.Driver"
    url="jdbc:mysql://localhost:3306/javatest"/>

この時、password 属性の値には平文のパスワードを書くことになりますが、「これはセキュリティ上良くないのでは?」ということを聞かれて、少し調べてみました。

まず、何よりも先に読むのはユーザーガイドです。

Tomcat 8.5 – JNDI Datasource HOW-TO – Database Connection Pool (DBCP 2) Configurations

ここには、暗号化についての言及はなく、設定例には平文のパスワードが記載されています。

ということで、少し調べてみると、TomcatのWikiの中にそれについて書かれたページがありました。

Tomcat Wiki – Why are plain text passwords in the config files?

この中で、いくつか対策の例が上がっていますが、いずれもパスワードを安全に保持にする方法ではなく、“Security by Obscurity”(隠ぺいによるセキュリティの確保)であり、根本的な対策にはならないと書かれています。むしろ、server.xmlに対する読み取りアクセスをrootユーザーやTomcat実行ユーザーだけに限定することの必要性について言及しています。

このXMLファイルのパスワードを暗号化することにどれだけの効果があるかは分かりません。しかし、それでも、気休め程度でも、平文のパスワードではなく、暗号化されたパスワードを書いておきたい、という方はいるのではないかと思います。そんな方々のために簡単な解決策となるファクトリークラスをつくってみました。これを利用すると、前述のXMLのpassword=”javadude”password=”xe2J0sJ+WlEAX3L4v/EI3A==”のように暗号化されたパスワードを書けます。Tomcat 8.5で動作確認しましたが、他のバージョンでは若干のロジック修正が必要かもしれません(DBCP2のライブラリを使用しているので)。

使用方法

使用方法は以下の通りです。

  1. GitHubからファクトリークラスをgit cloneして下さい。
    $ git clone https://github.com/k-tamura/encrypt-db-password.git
  2. encrypt-db-password/src/main/java/org/t246osslab/tomcat/dbcp/dbcp2の中にあるEncryptionDataSourceFactoryのメソッド encrypt()decrypt() に暗号化、復号化の処理を実装します(実装してありますが、変更して下さい)。:
        public static String encrypt(String source) throws NoSuchAlgorithmException, NoSuchPaddingException,
                InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
            // TODO Remove the following code and write a processing of returning an encrypted string
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(KEY.getBytes(), ALGORITHM));
            return new String(Base64.getEncoder().encode(cipher.doFinal(source.getBytes())));
        }
    
        public static String decrypt(String encryptSource) throws NoSuchAlgorithmException, NoSuchPaddingException,
                InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
            // TODO Remove the following code and write a processing of returning an decrypted string
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(KEY.getBytes(), ALGORITHM));
            return new String(cipher.doFinal(Base64.getDecoder().decode(encryptSource.getBytes())));
        }
    
  1. mvnコマンドでビルドします。
    $ mvn clean package
  2. 生成した依存ライブラリを含むjarで平文のパスワードを暗号化します。
    $ java -jar target/encrypt-db-password-1.0.0-jar-with-dependencies.jar \
     -e [平文のパスワード]
  3. 以下のようにデータソースの定義(server.xmlなど)を編集します:
  4. <Resource name="jdbc/TestDB" auth="Container"
        ・・・
        password="[暗号化したパスワード]"
        factory="org.t246osslab.tomcat.dbcp.dbcp2.EncryptionDataSourceFactory" 
        ・・・
        url="jdbc:mysql://localhost:3306/javatest"/>   
    
  1. 依存ライブラリを含まないjarをTomcatのlibディレクトリにコピーします。
    $ cp target/encrypt-db-password-1.0.0.jar $CATALINA_HOME/lib/
  2. Tomcatを起動します。

Tomcatのバージョンによって、若干の変更が必要かもしれませんが、こんな手順でいいはずです。

EasyBuggy Bootのトリセツ

「EasyBuggy Boot」は、バグだらけのWebアプリケーション「EasyBuggy」のSpring Bootベースのクローンで、JavaのWebアプリケーションで起こりうる様々な問題を、非常に手軽に体験できるWebアプリケーションです。EasyBuggyと機能的な差異はほとんどありませんが、起動方法等に若干異なる部分があります。EasyBuggyよりも新しい技術が使われており、開発やデバッグがしやすくなっています。

easybuggy

EasyBuggy Bootの特徴

基本的にはEasyBuggyと同等の機能を持っているので、用途などはこちらのページを参照下さい。「EasyBuggy」と「EasyBuggy Boot」の主な構成の相違点は以下の通りです。

相違点 EasyBuggy EasyBuggy Boot
ベースとなる技術 Servlet 3.0.1 Spring Boot 1.5.6 (Servlet 3.0.1)
プレゼンテーション層 未使用 (一部 JSP 2.2 + JSTL 1.2) Thymeleaf 2.1.5 (一部 JSP 2.3 + JSTL 1.2)
DBクライアント/サーバー JDBC / Derby 10.8.3.0 Spring JDBC 4.3.9 / Derby 10.12.1.1 (Java 7の場合)、または10.13.1.1 (Java 8の場合)
LDAPクライアント/サーバー Apache DS Client API 1.0.0 / Server 1.5.5 Spring LDAP 2.3.1 / unboundid-ldapsdk 3.2.1
メール JavaMail 1.5.1 JavaMail 1.5.1 (Spring Boot Mailで導入されるJavaMail 1.5.6をオーバーライド)
開発ツール 無し Spring Boot Developer Tools 1.5.6
Java Java 6以上をサポート Java 7以上をサポート

スクリーンショット

以下はメインページで、ブラウザの言語設定によって日本語と英語が切り替えられるようになっています。見ての通り、いろいろなバグを確認できます。

68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f34333836392f34633864333931322d383736302d626363312d383834652d3465356131346536373131642e706e67

バグのリンクをクリックすると、そのバグが確認できます。

起動方法

EasyBuggyを起動して、http://localhost:8080にアクセスすると、メインページが表示されます。起動方法には次の3つがあります。

  • javaコマンドで起動
  • mvnコマンドで起動
  • warファイルをサーブレットコンテナにデプロイして起動

それぞれどのように使い分けるか説明します。

● javaコマンドで起動:

もっとも関単にEasyBuggyを起動する方法です。ROOT.warをダウンロードして、次のコマンドで起動します。

$ java -jar ROOT.war

この時、以下のようにJVMオプションを指定しておくと、問題が発生しやすく、またログを確認しやすくなります。

$ java -Xmx256m -XX:MaxMetaspaceSize=64m -XX:MaxDirectMemorySize=90m -XX:+UseSerialGC -Xloggc:logs/gc.log -Xloggc:logs/gc_%p_%t.log -XX:+PrintHeapAtGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=10M -XX:GCTimeLimit=15 -XX:GCHeapFreeLimit=50 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=logs/ -XX:ErrorFile=logs/hs_err_pid%p.log -XX:NativeMemoryTracking=summary -agentlib:jdwp=transport=dt_socket,server=y,address=9009,suspend=n -Dderby.stream.error.file=logs/derby.log -Dderby.infolog.append=true -Dderby.language.logStatementText=true -Dderby.locks.deadlockTrace=true -Dderby.locks.monitor=true -Dderby.storage.rowLocking=true -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=7900 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -ea -jar ROOT.war

● mvnコマンドで起動:

GitHubからEasyBuggy Bootをgit cloneして下さい。

$ git clone https://github.com/k-tamura/easybuggy4sb 
$ cd easybuggy4sb

その後、次のコマンドでビルドから、起動までが一気にできます。

$ mvn clean spring-boot:run

新しい機能を追加したり、ソースコードを変更して動作確認してみたい場合、このコマンドを実行すればビルドして、すぐに動作確認をすることができます。

● warファイルをサーブレットコンテナにデプロイして起動:

Tomcat以外のコンテナにもデプロイできます。ROOT.warをダウンロードして、PayaraやJettyなどにデプロイすれば、起動します。javaコマンドで起動したときと同様に、JVMオプションを指定することをお勧めします。

開発の方法

STS (Spring Tool Suite)を使用して、EasyBuggy Bootのソースコードを参照したり、開発、デバッグする方法についても載せておきます。STSはEclipseベースのIDEで、Springベースの アプリケーションの開発が簡単にできるようにカスタマイズされています。

  1. このページからSTSをダウンロードして下さい。
  2. GitHubからEasyBuggy Bootをgit cloneして下さい。
    $ git clone https://github.com/k-tamura/easybuggy4sb
    $ cd easybuggy4sb
    
  3. 以下のコマンドを実行します。このコマンドでSTSでの開発に必要なファイル(.projectファイルや.classpathファイル)が作成されます。また、依存するライブラリのソースコードも参照できます。
    $ mvn dependency:sources
    $ mvn eclipse:eclipse
    
  4. STSを起動します。
  5. パッケージエクスプローラからクローンしたプロジェクトをインポートします。「Existing Maven Projects」を選択して、「Next」をクリックして下さい。
    Screenshot-Import .png
    「Root Directory」にクローンしたプロジェクトへのパスを入力し、「Finish」をクリックします。
    Screenshot-Import Maven Projects .png
  6. パッケージエクスプローラのeasybuggy4sbプロジェクトを右クリックし、「Debug As」、「Spring Boot App」と選択すると、デバッグモードでEasyBuggy Bootが起動します。
    Screenshot-Spring - easybuggy4sb-src-main-java-org-t246osslab-easybuggy4sb-Easybuggy4sbApplication.java - Spring Tool Suite .png

ソースコードを修正すると、自動的にリロードされて、修正が反映されることも確認してみて下さい。

リモートデバッグする方法

リモートのEasyBuggy Bootをデバッグする場合は、次のデバッグ設定を追加することでデバッガーをアタッチできます。

  • Connection type: Standard (Socket Listen)
  • Host: localhost
  • Port: 9009

Screenshot-Debug Configurations

 ビルドの方法

以下のコマンドで、実行可能かつデプロイ可能なwarファイルを作成することができます。

$ mvn clean package

注意事項

OutOfMemoryError関連のリンク(特にネイティブメモリを操作するもの)をクリックすると、PCの動作が不安定になる可能性があります。CPUやメモリを制限したVM上で起動するなどしてから、自己責任でリンクをクリックして下さい。

Eclipseのショートカットが効かなくなったら

EclipseやSTSのショートカットが効かなくなったら、どのように対処すればいいでしょうか?ご存知では無い人のために、ここに記しておきます。

例えば、STSのインポートの編成(Ctrl+Shift+O)が効かなくなったとします(実際に私がそうだった…)。

そんなときは、Window > Preferences > General > keys で「Ctrl+Shift+O」で検索してみます。

1.png

ここに存在しなければ、もちろん機能しません。その場合は、「Restore Defaults」ボタンをクリックして元に戻しましょう。ここにあっても機能しない場合は、競合する別のコマンドが優先して機能してしまっています。なので、それらのコマンドに別のキーバインディングを割り当てるか、アンバインドします。

この変更を適用した後でもショートカットが効かない場合は、「Filters…」をクリックして、

2.png

「Filter uncategorized commands」などのチェックを外します。

3

こうすると、見えていなかった競合するキーバインディングが見つかるので、これも別のキーバインディングに変えましょう。

5

これでショートカットが機能するようになるはずです。