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上で起動するなどしてから、自己責任でリンクをクリックして下さい。

広告

OpenAM起動時のJVMオプションについて

OpenAMを稼働するJavaコンテナ(Tomcatなど)にJVMオプションを指定して起動していると、トラブルがあった場合でも解析ができ、原因を突き止められる可能性が高くなります。ということで、参考までにGitHubにOpenAM用のTomcat環境変数設定ファイルを公開しておきました。

k-tamura/setenv-for-openam

  • setenv.sh (Linux用)
  • setenv.bat (Windows用)

$CATALINA_HOME/bin/にコピーして、実行権限を付与しておけば、自動的に読み込まれます。

各オプションについて、簡単に説明しておきます。

JITコンパイラのタイプ

JITコンパイラはサーバーコンパイラを選択します。通常、長時間起動するアプリケーションにおいて、-clientよりも性能が高くなります。

-server

Javaヒープサイズ

OpenAM管理ガイドのチューニングのセクションに書いてある通り、組み込みOpenDJを使用する場合(デフォルト)は最低でも2GBに設定します。また、Tomcat Expertによると、この2つの値は同じにした方がいいようです。

-Xms2048m
-Xmx2048m

Permanent領域/Metaspaceのサイズ

JDK 7以前の場合はPermanent領域のサイズを、

-XX:PermSize=256m
-XX:MaxPermSize=256m

JDK 8以降の場合はMetaspaceのサイズを設定します。

-XX:MetaspaceSize=256m
-XX:MaxMetaspaceSize=256m

ForgeRock社の推奨値は、両方とも256MBです。

その他、OpenAM固有の推奨値

OpenAM管理ガイドのチューニングのセクションに書いてあったその他の推奨値を必要に応じて設定します。

-Dsun.net.client.defaultReadTimeout=60000
-Dsun.net.client.defaultConnectTimeout=30000
-Dhttps.protocols=TLSv1,TLSv1.1,TLSv1.2

GC(ガベージコレクション)

GCのアルゴリズムやログ出力について設定します。GCのアルゴリズムはいくつかありますが、OpenAM管理ガイドのチューニングのセクションに書いてある通り、CMS(Concurrent Mark Sweep)を指定します。性能面の影響は小さいので、GCログの詳細も出力するようにします。

-Xloggc:$CATALINA_HOME/logs/gc.log
-XX:+UseConcMarkSweepGC
-XX:+UseCMSCompactAtFullCollection
-XX:+CMSClassUnloadingEnabled
-XX:+PrintHeapAtGC
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=5
-XX:GCLogFileSize=10M

-XX:+PrintGCTimeStamps」を付加すると、JVMを起動してからの時間が「17.890」のようにGCログに出力されますが、見づらいので「-XX:+PrintGCDateStamps」を付加して「2017-01-13T18:34:16.743」のような日時が出力されるようにしています(後者の方がごくわずかなオーバーヘッドが発生します)。

ヒープダンプの出力

OutOfMemoryErrorが発生したときにヒープダンプを出力するようにします。

-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=$CATALINA_HOME/logs/

致命的なエラーの出力

JavaVMのクラッシュやJNIで呼び出したライブラリでのエラーなど、致命的なエラーがあった場合に、エラーファイルを出力します。この機能自体はデフォルトで有効ですが、出力先を変更したい場合は明示的に設定します。

-XX:ErrorFile=$CATALINA_HOME/logs/hs_err_pid%p.log

JFR(Java Flight Recorder)の有効化

商用利用のためにOracleのJava上でTomcatを動作させる場合は、Java Flight Recorder(JFR)も有効にします。JFRは、実行中のJavaアプリケーションに関する診断およびプロファイリングのためのデータを収集するツールです。記録中のオーバーヘッドはほとんどなく、性能面の影響は小さいので、常に有効化しておいていいと思います。

-XX:+UnlockCommercialFeatures
-XX:+FlightRecorder

JFRを有効にするには、-XX:+UnlockCommercialFeaturesオプションの追加も必要です。

 


参考

http://www.tomcatexpert.com/blog/2011/11/16/setting-measurement-garbage-collection-apache-tomcat

http://www.tomcatexpert.com/blog/2011/11/22/performance-tuning-jvm-running-tomcat

https://backstage.forgerock.com/#!/docs/openam/13/admin-guide/chap-tuning

Javaパフォーマンス Scott Oaks 著、Acroquest Technology株式会社 監訳、寺田 佳央 監訳、牧野 聡 訳


 

OpenAMの新しい監査ログについて (2)

前回は、OpenAM 13.0.0で刷新された監査ログの概要について説明しました。最新のOpenAMでは、監査ログをCSVファイルに出力したり、SyslogやElasticSearchなどへの転送ができるようになっています。詳細については以下のページを参照下さい。

OpenAMの新しい監査ログについて (1)

今回はそれらの機能の一つであるJDBC監査ロギングについて書きます。JDBC監査ロギングは、OracleやMySQLなどのRDBMSに、OpenAMの監査ログを登録(INSERT)する機能です。

まず最初に言っておくと、このJDBC監査ロギングはOpenAM 13.0.0ではまともに動作しません…(新規に開発した機能は、最初のリリースでの動作が安定しないことがありますが、この機能はちょっと酷過ぎました…)。したがって、JDBC監査ロギングを利用する場合は、13.5.0以降(14.0.0のナイトリービルド)を使うか、いくつかのバグのパッチ(以下)を適用する必要があります。

設定手順

ここでは、MySQLに監査ログを登録する設定をします。おおまかな設定手順は、以下の通りです。

  1. JDBCドライバーをlibディレクトリにコピーする
  2. MySQLに、OpenAMの監査ログ用のテーブルを作成する
  3. OpenAMの管理コンソールで監査ログの設定を追加する

もう少し詳しく説明します。

※なお、MySQLのインストールや初期設定はしてあるものとします(省略します)。

手順1. JDBCドライバーをlibディレクトリにコピーする

JDBCドライバーを次のページからダウンロードしてきます。

https://dev.mysql.com/downloads/connector/j/

ダウンロードしたら、TomcatかOpenAMのlibディレクトリにコピーして下さい。

$ cp mysql-connector-java-5.1.38-bin.jar /usr/share/tomcat7/lib/

手順2. MySQLに、OpenAMの監査ログ用のテーブルを作成する

次に、MySQLにOpenAMの監査ログ用のデータベースを作成し、適当なユーザーでOpenAMからアクセスできるようにします。

$ mysql -u root -p 
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 5.1.73 Source distribution

Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> CREATE DATABASE audit;
Query OK, 1 row affected (0.22 sec)

mysql> GRANT ALL PRIVILEGES ON audit.* TO root@'192.168.1.0/255.255.255.0' IDENTIFIED BY 'password';
Query OK, 0 rows affected (0.04 sec)

mysql> select user,host,password from mysql.user; 
+------+---------------------------+-------------------------------------------+
| user | host                      | password                                  |
+------+---------------------------+-------------------------------------------+
| root | localhost                 | *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 |
| root | openam02.example.co.jp    | *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 |
| root | 127.0.0.1                 | *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 |
| root | 192.168.1.0/255.255.255.0 | *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 |
+------+---------------------------+-------------------------------------------+
4 rows in set (0.03 sec)

完了したら、OpenAMのwarファイルの中にあるaudit.sqlを実行して、監査ログ用のテーブルを作成します。

mysql> source /var/lib/tomcat7/webapps/openam/WEB-INF/template/sql/mysql/audit.sql
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 1 row affected, 1 warning (0.00 sec)
Database changed
Query OK, 0 rows affected (0.09 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)

mysql> exit

手順3. OpenAMの管理コンソールで監査ログの設定を追加する

管理コンソールの 設定 > グローバル > 監査ロギング で、監査イベントハンドラのセクションの「新規」ボタンをクリックし「JDBC」を選択すると、JDBC用の監査ログを制御するハンドラが追加されます。

auditjdbcsettings1

「データベースの種類」はMySQLを選択し、「JDBCドライバー URL」から「データべースパスワード(確認)」までの項目に適切な値を入力して下さい。

auditjdbcsettings2

設定に問題がなければ、以下のように監査ログが4つのテーブルに登録されます。

audittables

大量の監査ログを捌くための仕組み

監査ログの設定後、OpenAMのログインや設定変更、ログアウトなどを行ってみると、あっという間にたくさんの監査ログレコードが登録されているのが分かります。実際の運用となり、ユーザー数が多くなると、さらに大量に登録されることになります。大量なログの高速な登録を実現するために、OpenAMは以下のような仕組みを実装しています。

afw4

ポイントとなるのは、以下の技術です。

  • 監査イベントバッファリング
  • ライタースレッド
  • ExecuteBatch()
  • HikariCP

ユーザーがOpenAMにログインしたり、自身の情報を更新すると、監査イベント(ログデータ)は、バッファ変数に一時的に保存されます(監査イベントバッファリング)。このログデータは監査ログINSERT用のSQLのプリペアドステートメントに結びつけられて、ライタースレッドによりexecuteBatch()メソッドで複数件まとめてデータベースに登録されます。

この時、データベースへのアクセスに使用しているコネクションプールのライブラリには、Commons DBCPやC3P0ではなく、HikariCPというものが使用されています。HikariCPは、軽量なJDBCコネクションプールのライブラリで、高速な処理性能を持っていることが特徴です。ただし、それだけではなく、シンプルな実装であるがゆえに信頼性や安定性も高いようです。

hikaricp-bench-2-4-0

HikariCPについて興味がある方は、以下を参照してみて下さい。

https://github.com/brettwooldridge/HikariCP

Java EEエージェントのビルド

Java EEエージェントのビルドもOpenAMサーバーと同様にmvnコマンドを実行するだけで完了します。

ビルド環境の整備

ビルドに必要なソフトウェアは、JDKとMavenです。前提ソフトウェアのバージョンについて、公式な情報は公開されていませんが、OpenAMのビルドができるバージョンを使えば問題はないはずです。

Java JDK Maven
1.7 以上 3.1.0 以上

ただし、1つ注意すべき点があります。WebSphere ASとWebLogic Server用のエージェントのビルドには、サーバーベンダーが提供する非公開のライブラリが必要です。これらの依存関係を解決するには、各サーバーソフ トウェアに含まれるライブラリを取得し、mvnコマンド実行時に参照できるようにしておく必要があります。詳細に関しては、Java EEエージェントのソースコードに添付されているreadme.mdファイルを参照してください。

手順. Java EEエージェントのビルド

まずは、ビルド用のディレクトリを作成し、そこに移動します。

$ mkdir jeeagent_build
$ cd jeeagent_build/

ソースコードはForgeRock社のBitbucketサーバー上で公開されています。ここでは、バージョン3.5.0のソースコードを圧縮したファイルをダウンロードします。

https://stash.forgerock.org/projects/OPENAM/repos/jee-agents/browse?at=refs%2Ftags%2F3.5.0

ダウンロードが完了したら、圧縮ファイルを解凍してください。

$ unzip jee-agents-master\@36016b991ff.zip 
Archive:  jee-agents-master@36016b991ff.zip
36016b991ff2aeb694a5d09e062591704f9eec45
 extracting: .gitignore              
   creating: jee-agents-agentapp/
  inflating: jee-agents-agentapp/pom.xml  

  .......

  inflating: pom.xml                 
  inflating: readme.md

解凍したら圧縮ファイルは削除します。

$ rm jee-agents-master\@36016b991ff.zip 
rm: remove 通常ファイル `jee-agents-master@36016b991ff.zip'? yes

ディレクトリ構成は、以下のようになっています。各サーバー毎のエージェントモジュールやサンプルアプリケーション(sampleapp)用のモジュールが、ディレクトリ毎に分かれて配置されています。

$ ll
合計 1828
drwxr-xr-x  3 root root    4096  9月 16 23:26 2016 jee-agents-agentapp
drwxr-xr-x  4 root root    4096  9月 16 23:26 2016 jee-agents-appserver
drwxr-xr-x 12 root root    4096  9月 16 23:26 2016 jee-agents-distribution
drwxr-xr-x  5 root root    4096  9月 16 23:26 2016 jee-agents-jboss
drwxr-xr-x  4 root root    4096  9月 16 23:26 2016 jee-agents-jetty
drwxr-xr-x  3 root root    4096  9月 16 23:26 2016 jee-agents-jsr196
drwxr-xr-x  3 root root    4096  9月 16 23:26 2016 jee-agents-library
drwxr-xr-x 15 root root    4096  9月 16 23:26 2016 jee-agents-sampleapp
drwxr-xr-x  3 root root    4096  9月 16 23:26 2016 jee-agents-sdk
drwxr-xr-x  3 root root    4096  9月 16 23:26 2016 jee-agents-tomcat
drwxr-xr-x  3 root root    4096  9月 16 23:26 2016 jee-agents-weblogic
drwxr-xr-x  4 root root    4096  9月 16 23:26 2016 jee-agents-websphere
drwxr-xr-x  2 root root    4096  9月 16 23:26 2016 legal
-rwxr-xr-x  1 root root   33221  9月 16 23:26 2016 pom.xml
-rw-r--r--  1 root root    2097  9月 16 23:26 2016 readme.md
$

全体のpom.xmlがあるので、ここでmvnコマンドを実行すれば、ビルドが開始されますが、前述した商用のサーバーのライブラリが存在しないの で、ビルドエラーとなってしまいます。Tomcatエージェントだけをビルドしたいということでれば、以下のようにpom.xmlを編集し、Tomcat以外のサーバー用のmoduleタグをコメントアウトすればビルドできるようになります。

    <modules>
        <module>jee-agents-sdk</module>
        <module>jee-agents-library</module>
        <module>jee-agents-agentapp</module>
        <module>jee-agents-tomcat</module>
<!-- ここから
        <module>jee-agents-jboss</module>
        <module>jee-agents-jetty</module>
        <module>jee-agents-appserver</module>
        <module>jee-agents-weblogic</module>
        <module>jee-agents-websphere</module>
        <module>jee-agents-jsr196</module>
ここまでコメントアウト -->
        <module>jee-agents-sampleapp</module>
        <module>jee-agents-distribution</module>
    </modules>

mvn clean installコマンドでビルドを実行します。テストを省略する場合は、-DskipTests=trueオプションを付加してください。

$ mvn -DskipTests=true clean install
[INFO] Scanning for projects...
[WARNING] 

  .......

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1:00.510s
[INFO] Finished at: Sun Sep 25 09:42:15 JST 2016
[INFO] Final Memory: 64M/349M
[INFO] ------------------------------------------------------------------------

数分で、ビルドは完了します。jee-agents-distribution/jee-agents-distribution-tomcat- v6/target/以下に、Tomcatエージェントの圧縮ファイル(tomcat_v6_agent_4.0.0-SNAPSHOT.zip)が作成 されているはずです。

$ ll jee-agents-distribution/jee-agents-distribution-tomcat-v6/target/
合計 33888
drwxr-xr-x 2 root root     4096  9月 25 09:41 2016 archive-tmp
-rw-r--r-- 1 root root       27  9月 25 09:41 2016 build_date.js
-rw-r--r-- 1 root root 34692736  9月 25 09:41 2016 tomcat_v6_agent_4.0.0-SNAPSHOT.zip

OpenAMをRESTでセットアップする

OpenAMのJIRAを眺めていたら、RESTでOpenAMの初期設定(セットアップ)をすることができることに気付きました。OpenAMのwarファイルをサーブレットコンテナにデプロイして、以下のようにURL エンコードした各種パラメータを/openam/config/configuratorエンドポイントにPOSTすると、数秒後に初期設定が完了します。

# curl --request POST "http://openam.example.com:8080/openam/config/configurator" \
 --header "Content-Type:application/x-www-form-urlencoded" \
 --data-urlencode "SERVER_URL=http://openam.example.com:8080" \
 --data-urlencode "DEPLOYMENT_URI=openam" \
 --data-urlencode "BASE_DIR=/opt/tomcat7/openam" \
 --data-urlencode "locale=en_US" \
 --data-urlencode "PLATFORM_LOCALE=en_US" \
 --data-urlencode "ADMIN_PWD=p@s2word" \
 --data-urlencode "ADMIN_CONFIRM_PWD=p@s2word" \
 --data-urlencode "AMLDAPUSERPASSWD=Passw0rd" \
 --data-urlencode "AMLDAPUSERPASSWD_CONFIRM=Passw0rd" \
 --data-urlencode "COOKIE_DOMAIN=.example.co.jp" \
 --data-urlencode "DATA_STORE=embedded" \
 --data-urlencode "DIRECTORY_SSL=SIMPLE" \
 --data-urlencode "DIRECTORY_SERVER=localhost" \
 --data-urlencode "DIRECTORY_PORT=50389" \
 --data-urlencode "DIRECTORY_ADMIN_PORT=4444" \
 --data-urlencode "DIRECTORY_JMX_PORT=1689" \
 --data-urlencode "ROOT_SUFFIX=dc=openam,dc=forgerock,dc=org" \
 --data-urlencode "DS_DIRMGRDN=cn=Directory Manager" \
 --data-urlencode "DS_DIRMGRPASSWD=p@s2word" \
 --data-urlencode "acceptLicense=true"

Configuration complete!

GUIを使うと入力の手間やミスがあるので、動作検証などで何回もセットアップするような場合にこの方法は便利です。設定ツール(openam-configurator-tool.jar)を使って、同様にサイレントインストールをすることもできますが、設定ツールはダウンロードとインストールをしないといけないので、RESTの方が少しだけ簡単にできます。

ただし、この方法は今のことろOpenAMのインストールガイドにも載っていない、非公式なもののようです。初期化処理の途中経過が分からない点や例外処理が弱い点も考慮して、非公式のままにしているのだと思います。エラーレスポンスもスタックトレース付きのHTML形式で返ってきていました…

# curl --verbose --request POST "http://openam.example.com:8080/openam/config/configurator" \
 --header "Content-Type:application/x-www-form-urlencoded" \
 --data-urlencode "SERVER_URL=http://openam.example.com:8080" \
 --data-urlencode "DEPLOYMENT_URI=openam" \
 --data-urlencode "BASE_DIR=/opt/tomcat7/openam" \
 --data-urlencode "locale=en_US" \
 --data-urlencode "PLATFORM_LOCALE=en_US" \
 --data-urlencode "ADMIN_PWD=p@s2word" \
 --data-urlencode "ADMIN_CONFIRM_PWD=p@s2word" \
 --data-urlencode "AMLDAPUSERPASSWD=p@s2word" \
 --data-urlencode "AMLDAPUSERPASSWD_CONFIRM=p@s2word" \
 --data-urlencode "COOKIE_DOMAIN=.example.co.jp" \
 --data-urlencode "DATA_STORE=embedded" \
 --data-urlencode "DIRECTORY_SSL=SIMPLE" \
 --data-urlencode "DIRECTORY_SERVER=localhost" \
 --data-urlencode "DIRECTORY_PORT=50389" \
 --data-urlencode "DIRECTORY_ADMIN_PORT=4444" \
 --data-urlencode "DIRECTORY_JMX_PORT=1689" \
 --data-urlencode "ROOT_SUFFIX=dc=openam,dc=forgerock,dc=org" \
 --data-urlencode "DS_DIRMGRDN=cn=Directory Manager" \
 --data-urlencode "DS_DIRMGRPASSWD=p@s2word" \
 --data-urlencode "acceptLicense=true"

* About to connect() to openam.example.com port 8080 (#0)
* Trying 172.105.126.221... connected
* Connected to openam.example.com (172.105.126.221) port 8080 (#0)
> POST /openam/config/configurator HTTP/1.1
> User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.13.1.0 zlib/1.2.3 libidn/1.18 libssh2/1.2.2
> Host: openam.example.com:8080
> Accept: */*
> Content-Type:application/x-www-form-urlencoded
> Content-Length: 572
>
< HTTP/1.1 500 Internal Server Error
< Server: Apache-Coyote/1.1
< Content-Type: text/html;charset=utf-8
< Content-Language: en
< Content-Length: 2474
< Date: Thu, 25 Aug 2016 05:58:34 GMT
< Connection: close
<
<html><head><title>Apache Tomcat/7.0.57 - Error report</title><style><!--H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}HR {color : #525D76;}--></style> </head><body><h1>HTTP Status 500 - AMSetupFilter.doFilter</h1><HR size="1" noshade="noshade"><p><b>type</b> Exception report</p><p><b>message</b> <u>AMSetupFilter.doFilter</u></p><p><b>description</b> <u>The server encountered an internal error that prevented it from fulfilling this request.</u></p><p><b>exception</b> <pre>javax.servlet.ServletException: AMSetupFilter.doFilter
com.sun.identity.setup.AMSetupFilter.doFilter(AMSetupFilter.java:141)
org.forgerock.openam.audit.context.AuditContextFilter.doFilter(AuditContextFilter.java:51)
</pre></p><p><b>root cause</b> <pre>com.sun.identity.setup.ConfiguratorException: Default Agent Password cannot be the same as Administrator password.
com.sun.identity.setup.ServicesDefaultValues.validateURLAccessAgentPassword(ServicesDefaultValues.java:443)
com.sun.identity.setup.ServicesDefaultValues.validatePassword(ServicesDefaultValues.java:353)
com.sun.identity.setup.ServicesDefaultValues.setServiceConfigValues(ServicesDefaultValues.java:125)
com.sun.identity.setup.AMSetupServlet.processRequest(AMSetupServlet.java:466)
com.sun.identity.setup.AMSetupServlet.doPost(AMSetupServlet.java:439)
javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
org.forgerock.openam.validation.ResponseValidationFilter.doFilter(ResponseValidationFilter.java:44)
com.sun.identity.setup.AMSetupFilter.doFilter(AMSetupFilter.java:125)
org.forgerock.openam.audit.context.AuditContextFilter.doFilter(AuditContextFilter.java:51)
* Closing connection #0
</pre></p><p><b>note</b> <u>The full stack trace of the root cause is available in the Apache Tomcat/7.0.57 logs.</u></p><HR size="1" noshade="noshade"><h3>Apache Tomcat/7.0.57</h3></body></html>

OpenAMの新しい監査ログについて (1)

OpenAM 13.0.0では、監査ログの仕組みが刷新され、ForgeRock製品共通の出力形式に統一されています。また、次の監査ログ機能が提供されました。

  • CSV監査ロギング
  • Syslog監査ロギング
  • JDBC監査ロギング

さらに、OpenAM 13.5.0からは、次の機能も追加されています。

  • JMS監査ロギング
  • ElasticSearch監査ロギング

従来からある(12.0.x以前の)監査ログに代わって、デフォルトではCSV監査ロギング機能が有効になっており、[OpenAMの設定ディレクトリ]/[コンテキスト名]/log (例えば、/opt/tomcat7/openam/openam/log) ディレクトリに以下のようなファイルを出力します。

イベント ファイル名 説明
Access access.csv すべてのアクセスに対して、誰が、いつ、何をしたのかを出力します。
Activity activity.csv 13.xでは、エンドユーザーのセッションの状態の変更のみがログに記録されます。今後のリリースでは、ユーザーの信頼できるデバイス、UMAポリシー、OAuth 2.0のトークンなどへの変更が記録される予定です。
Authentication authentication.csv いつ、どのようにユーザーが認証されたか、また認証に関連するイベントを出力します。
Configuration config.csv 誰が、いつ、OpenAMの設定変更をしたかを出力します。設定の変更を行った対象を示すuserIdは、config.csvにはキャプチャされませんが、access.csvのtransactionIdから追跡できます。

この中の一つのaccess.csvを表示してみると、以下のような情報が出力されています。

"_id","timestamp","eventName","transactionId","userId","trackingIds","server.ip","server.port","client.ip","client.port","request.protocol","request.operation","request.detail","http.request.secure","http.request.method","http.request.path","http.request.queryParameters","http.request.headers","http.request.cookies","http.response.headers","response.status","response.statusCode","response.detail","response.elapsedTime","response.elapsedTimeUnits","component","realm"
"9c651f8b-d475-4be6-ab49-a4267125c751-491","2016-08-08T13:30:04.634Z","AM-ACCESS-OUTCOME","9c651f8b-d475-4be6-ab49-a4267125c751-489",,"[""""]","192.168.1.101","8080","192.168.1.12","47108","CREST","ACTION","{""action"":""validate""}","false","POST","http://openam01.example.co.jp:8080/openam/json/sessions","{""_action"":[""validate""]}","{""accept"":[""application/json, text/javascript, */*; q=0.01""],""accept-api-version"":[""protocol=1.0,resource=1.1""],""host"":[""openam01.example.co.jp:8080""],""origin"":[""http://openam01.example.co.jp:8080""],""referer"":[""http://openam01.example.co.jp:8080/openam/XUI/""],""user-agent"":[""Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/51.0.2704.79 Chrome/51.0.2704.79 Safari/537.36""],""x-nosession"":[""true""],""x-password"":[""anonymous""],""x-requested-with"":[""XMLHttpRequest""],""x-username"":[""anonymous""]}","{""JSESSIONID"":""F1B35FF947BFD9EF7C9DDC026A1C15F4"",""amlbcookie"":""01"",""i18next"":""ja""}",,"SUCCESSFUL",,,"298","MILLISECONDS","Session","/"
"9c651f8b-d475-4be6-ab49-a4267125c751-496","2016-08-08T13:30:04.870Z","AM-ACCESS-OUTCOME","9c651f8b-d475-4be6-ab49-a4267125c751-494",,"[""428f5cd47cea8c1d01""]",,,"192.168.1.12","47108",,,,"false","POST","http://openam01.example.co.jp:8080/openam/json/authenticate","{}","{""accept"":[""application/json, text/javascript, */*; q=0.01""],""accept-api-version"":[""protocol=1.0,resource=2.0""],""host"":[""openam01.example.co.jp:8080""],""origin"":[""http://openam01.example.co.jp:8080""],""referer"":[""http://openam01.example.co.jp:8080/openam/XUI/""],""user-agent"":[""Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/51.0.2704.79 Chrome/51.0.2704.79 Safari/537.36""],""x-nosession"":[""true""],""x-password"":[""anonymous""],""x-requested-with"":[""XMLHttpRequest""],""x-username"":[""anonymous""]}","{""JSESSIONID"":""F1B35FF947BFD9EF7C9DDC026A1C15F4"",""amlbcookie"":""01"",""i18next"":""ja""}",,"SUCCESSFUL",,,"4","MILLISECONDS","Authentication","/"
"9c651f8b-d475-4be6-ab49-a4267125c751-507","2016-08-08T13:30:08.698Z","AM-ACCESS-OUTCOME","9c651f8b-d475-4be6-ab49-a4267125c751-499","id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org","[""428f5cd47cea8c1d01""]",,,"192.168.1.12","47108",,,,"false","POST","http://openam01.example.co.jp:8080/openam/json/authenticate","{}","{""accept"":[""application/json, text/javascript, */*; q=0.01""],""accept-api-version"":[""protocol=1.0,resource=2.0""],""host"":[""openam01.example.co.jp:8080""],""origin"":[""http://openam01.example.co.jp:8080""],""referer"":[""http://openam01.example.co.jp:8080/openam/XUI/""],""user-agent"":[""Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/51.0.2704.79 Chrome/51.0.2704.79 Safari/537.36""],""x-nosession"":[""true""],""x-password"":[""anonymous""],""x-requested-with"":[""XMLHttpRequest""],""x-username"":[""anonymous""]}","{""JSESSIONID"":""F1B35FF947BFD9EF7C9DDC026A1C15F4"",""i18next"":""ja"",""amlbcookie"":""01""}",,"SUCCESSFUL",,,"8","MILLISECONDS","Authentication","/"

従来の監査ログの1つであったamSSO.access(以下)と比較してみると、出力される情報量が増えているのが分かります。

#Version: 1.0
#Fields: time Data ContextID LoginID IPAddr LogLevel Domain MessageID LoggedBy NameID ModuleName HostName 
"2016-08-08 22:29:54" /usr/share/tomcat7/openam/openam/log/|/usr/share/tomcat7/openam/openam/log/|File|File|OFF|OFF|INACTIVE|ACTIVE|INFO|INFO 4690fe938b6fdd2b01 "cn=dsameuser,ou=DSAME Users,dc=openam,dc=forgerock,dc=org" "Not Available" INFO dc=openam,dc=forgerock,dc=org LOG-3 "cn=dsameuser,ou=DSAME Users,dc=openam,dc=forgerock,dc=org" "Not Available" amSSO.access 192.168.1.101 
"2016-08-08 22:30:04" id=amadmin 2436c2b623da170301 id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org 192.168.1.12 INFO dc=openam,dc=forgerock,dc=org SESSION-4 "cn=dsameuser,ou=DSAME Users,dc=openam,dc=forgerock,dc=org" "Not Available" amSSO.access 192.168.1.12 
"2016-08-08 22:30:08" id=amadmin 428f5cd47cea8c1d01 id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org 192.168.1.12 INFO dc=openam,dc=forgerock,dc=org SESSION-1 "cn=dsameuser,ou=DSAME Users,dc=openam,dc=forgerock,dc=org" "Not Available" amSSO.access 192.168.1.12 

新しい監査ログの設定は、管理コンソールの 設定 > グローバル > Audit Loggingで確認できます。

GlobalAuditConfig

information なお、13.0.0より前のバージョンで提供されていたロギング機能(管理コンソールの設定 > システム > ログ)は13.xでも利用できますが、デフォルトで非アクティブな状態になっており、今後のリリースでは廃止される予定になっています。

Screenshot from 2016-08-08 22-11-59

次回は、13.0.0で追加されたJDBC監査ログ機能について、調べた結果をまとめます。

OpenAMをビルドする

 OpenAMのビルドはとても簡単です。基本的には、OpenAMのソースコードをダウンロードして、Mavenのコマンドを実行するだけです。ただし、注意すべき点がいくつかあります。

注意点

  • OpenAMと、Java、Maven、Gitのバージョンを確認すること
  • Windows上でのビルドは失敗する可能性があるので、LinuxかMac上で実施すること
  • ビルドするだけであれば、-DskipTests=trueオプションを付けること(テストはスキップする)

ビルド環境の整備

 OpenAM 11.0.0以降のビルドに必要なソフトウェアは、JDK、Maven、Gitですが、OpenAMのバージョンによって若干異なります。

OpenAM Java JDK Maven Git
OpenAM 13.0.0 1.7 以上 3.1.0 以上 1.7.6 以上
OpenAM 12.0.0 1.6 以上 3.3.1 以下 1.7.6 以上
OpenAM 11.0.0 1.6 または 1.7 3.0.5 1.7.6 以上

Mavenのビルドコマンドを実行する前に、これらのバージョンを確認しておきましょう。

$ mvn -version
Apache Maven 3.1.0 (893ca28a1da9d5f51ac03827af98bb730128f9f2; 2013-06-28 11:15:32+0900)
Maven home: /opt/apache-maven-3.1.0
Java version: 1.7.0_101, vendor: Oracle Corporation
Java home: /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.101.x86_64/jre
Default locale: ja_JP, platform encoding: UTF-8
OS name: "linux", version: "2.6.32-642.el6.x86_64", arch: "amd64", family: "unix"

$ git --version
git version 2.2.0

参考までに、今回使った環境は以下の通りです。

  • CentOS 6.8
  • OpenJDK 1.7.0.101
  • Apache Maven 3.1.0
  • Git 2.2.0

ソースコードの取得

 ソースコードはForgeRock社のBitbucketサーバーからgit cloneで取得してくることもできますが、アカウントをつくってログインしないといけないので、GitHubからダウンロードします。ダウンロードしたら、解凍して出来たディレクトリに移動して下さい。

$ wget --no-check-certificate https://github.com/ForgeRock/openam/archive/13.0.0.zip
$ unzip 13.0.0.zip
$ cd openam-13.0.0

Mavenによるビルド

 以下のコマンドを実行すると、ビルドが始まります。

$ export MAVEN_OPTS="-Xmx1024m -XX:MaxPermSize=512m"
$ mvn -DskipTests=true clean install

マシンの性能によりますが、30分くらいはかかると思います。完了すると、openam-server/target/にOpenAM-13.0.0.warが作成されます。

非公式日本語版OpenAMのビルド

 次のページにも書きましたが、私がつくった非公式日本語版OpenAMも簡単にビルドできます。

https://github.com/k-tamura/openam1300-japanese-properties/blob/master/README.jp.md

Java、Maven、Gitがインストールされていれば、以下のコマンドを実行するだけです。

$ wget --no-check-certificate https://raw.githubusercontent.com/k-tamura/openam1300-japanese-properties/master/build-openam-jp.sh
$ chmod +x build-openam-jp.sh
$ ./build-openam-jp.sh

※レビュー未実施なので、日本語訳が間違っていたり、分かりにくい部分はあるかもしれません。

ということで、ビルドはとても簡単なので試してみて下さい。