JIRAとOpenLDAPを連携させてみる

  • 投稿日:
  • by
  • カテゴリ:

JIRAという課題管理システムがシェアを伸ばしてるらしく、興味を持ったので、評価用ライセンスでインストールしてみた。
JIRAのユーザー管理にはLDAPが使えるとのことなので、ついでにOpenLDAPとの接続を試してみたので、その過程を記録する。

使用環境
OS: FreeBSD 9.2
packages: OpenJDK6, Tomcat6, openldap-server
JIRA version: 5.2.11

●slapd.confの設定
・inetOrgPerson, posixAccountクラス用のincludeを追加
include /usr/local/etc/openldap/schema/cosine.schema
include /usr/local/etc/openldap/schema/inetorgperson.schema
include /usr/local/etc/openldap/schema/nis.schema

・ベースDN設定

suffix "dc=raffine,dc=moriguchi,dc=jp"
ldapsearch等のコマンドの利便のため、ldap.confのBASEも同じにしておくと良い。

・ルートDN(特権DN)設定

rootdn "cn=Manager,dc=raffine,dc=moriguchi,dc=jp"
rootpw {SSHA}s/98X4C3ex/vtSrL3wzP0CyRub2ZdYoL
暗号化パスワード文字列は、slappasswdで作成できる。

●基本コンテナの作成
以下の内容を、init.ldifとして保存する。

dn: dc=raffine,dc=moriguchi,dc=jp
objectClass: dcObject
objectClass: organization
o: Raffine Moriguchi
dc: raffine

dn: cn=Manager,dc=raffine,dc=moriguchi,dc=jp
objectClass: organizationalRole
cn: Manager

dn: ou=People,dc=raffine,dc=moriguchi,dc=jp
objectClass: organizationalUnit
ou: People

dn: ou=Group,dc=raffine,dc=moriguchi,dc=jp
objectClass: organizationalUnit
ou: Group

次に、ldapaddコマンドで実行する。

ldapadd -x -D "cn=Manager,dc=raffine,dc=moriguchi,dc=jp" -W -f init.ldif
パスワードが覗かれたりシェルのヒストリーに残っても良ければ、"-W"を"-w (password)"としても良い。

●ユーザー情報の登録
以下をuser01.ldifとして保存し、ldapaddで実行

dn: cn=user01,ou=people,dc=raffine,dc=moriguchi,dc=jp
objectClass: inetOrgPerson
cn: user01
sn: User No.01
mail: user01@localhost
userPassword: user01

dn: cn=user02,ou=people,dc=raffine,dc=moriguchi,dc=jp
objectClass: inetOrgPerson
cn: user02
sn: User No.02
mail: user02@localhost
userPassword: user02

dn: cn=jira-users,ou=group,dc=raffine,dc=moriguchi,dc=jp
objectClass: groupOfUniqueNames
cn: jira-users
uniqueMember: cn=user01,ou=people,dc=raffine,dc=moriguchi,dc=jp
uniqueMember: cn=user02,ou=people,dc=raffine,dc=moriguchi,dc=jp

●JIRAへのディレクトリー追加
1. システム管理メニューの"Users"→"User Directories"の画面で"Add Directory"ボタンを押し、Directory TypeとしてLDAPを選択
2. Configure画面にて以下のように設定し、"Save and Test"ボタン押下
Name: LDAP server 1
Directory Type: OpenLDAPを選択
Hostname: localhost
Username: cn=Manager,dc=raffine,dc=moriguchi,dc=jp
Password: (ルートDNのパスワード)
Base DN: dc=raffine,dc=moriguchi,dc=jp
3. "Test basic connection: Succeeded"と表示されているのを確認し、再バインド用に、"For extended testing ..."の所で 
User name: user01
として"Test Settings"ボタン押下
4. システム管理メニューの"Users"→"User Directories"の画面でuser01とuser02が追加されていること、Groupがjira-usersであることを確認

●ユーザー情報の追加
以下をuser03.ldifとして保存し、ldapaddで実行

dn: cn=user03,ou=people,dc=raffine,dc=moriguchi,dc=jp
objectClass: inetOrgPerson
cn: user03
sn: User No.03
mail: user03@localhost
userPassword: user03

dn: cn=user04,ou=people,dc=raffine,dc=moriguchi,dc=jp
objectClass: inetOrgPerson
cn: user04
sn: User No.04
mail: user04@localhost
userPassword: user04
以下をuser03m.ldifとして保存し、ldapmodifyで実行
dn: cn=jira-users,ou=group,dc=raffine,dc=moriguchi,dc=jp
add: uniqueMember
uniqueMember: cn=user03,ou=people,dc=raffine,dc=moriguchi,dc=jp
uniqueMember: cn=user04,ou=people,dc=raffine,dc=moriguchi,dc=jp
ldapmodify -x -D "cn=Manager,dc=raffine,dc=moriguchi,dc=jp" -W -f user03m.ldif

●JIRAでの確認
"User Directory"画面で"LDAP server 1"の"Synchronize"をクリックし、
"User"画面でuser03やuser04が追加されていることを確認


●ユーザー情報の登録(Posix Schemaのテスト用)
以下をuser11.ldifとして保存し、ldapaddで実行

dn: uid=user11,ou=people,dc=raffine,dc=moriguchi,dc=jp
objectClass: posixAccount
objectClass: inetOrgPerson
cn: user11
uid: user11
uidNumber: 10011
gidNumber: 10918
homeDirectory: /home/user11
userPassword: user11
mail: user11@localhost
sn: User No.11

dn: uid=user12,ou=people,dc=raffine,dc=moriguchi,dc=jp
objectClass: posixAccount
objectClass: inetOrgPerson
cn: user12
uid: user12
uidNumber: 10012
gidNumber: 10918
homeDirectory: /home/user12
userPassword: user12
mail: user12@localhost
sn: User No.12

#dn: cn=jira-users,ou=group,dc=raffine,dc=moriguchi,dc=jp
#is already used by the above groupOfUniqueName object.
dn: gidNumber=10918,ou=group,dc=raffine,dc=moriguchi,dc=jp
objectClass: posixGroup
description: the default group in JIRA
gidNumber: 10918
cn: jira-users
memberUid: user11
memberUid: user12

posixAccountは補助型なので、他に何か構造型が必要であるが、その構造型としてinetOrgPersonを選んだのは、mail属性を使用するため。
posixGroupオブジェクトのRDNは"cn=jira-users"とするのが普通だと思うが、user01.ldifの例で既に使ってしまっており、それと共存させたので、gidNumberをRDNに用いた。
ou=PosixGroupというサブグループを作って、その下に置くのがbetterだと思うが、手を抜いた。
なお、10918としたのは、A=1, B=2とするとJ=10, I=9, R=18だから。

●JIRAへのディレクトリー追加(Posix Schema)
1. システム管理メニューの"Users"→"User Directories"の画面で、
"LDAP server 1"の"Disable"をクリック(※理由は後述)し、
"Add Directory"ボタンを押し、Directory TypeとしてLDAPを選択
2. Configure画面にて以下のように設定し、"Save and Test"ボタン押下
Name: LDAP server 2
Directory Type: OpenLDAP (Read-Only Posix Schema)
Hostname: localhost
Username: cn=Manager,dc=raffine,dc=moriguchi,dc=jp
Password: (ルートDNのパスワード)
Base DN: dc=raffine,dc=moriguchi,dc=jp
3. "Test basic connection: Succeeded"と表示されているのを確認し、再バインド用に、"For extended testing ..."の所で 
User name: user11
として"Test Settings"ボタン押下
4. システム管理メニューの"Users"→"User Directories"の画面でuser11とuser12が追加されていること、Groupがjira-usersであることを確認

※Configure画面のGroup Schema Settingsセクションを開くと
Group Object Class: groupOfUniqueNames
となっているが、これを特に"posixGroup"に修正しなくても、posixGroupクラスのオブジェクトからグループ情報が取得されるようである。

●"LDAP server 1"と"LDAP server 2"の共存のための設定
ここまでの状態で"LDAP server 1"を有効にすると、use11やuser12がinetOrgPersonクラスである為、"LDAP server 1"から取得されてしまい、"LDAP server 2"のuser11やuser12が無効になり、posixGroupオブジェクトによるグループ設定も無効になり、user11やuser12がグループ無しになってしまう。
これをJIRA側で解決する方法は、2つほど考えられる。
(a) "LDAP server 2"を"LDAP server 1"より優先する
 "User Directories"の画面でディレクトリーの参照順序を入れ替えるだけである。
(b) 該当するユーザーが"LDAP server 1"から取得されないようにする
 "LDAP server 1"の"Edit"からConfigure画面に入ると、User Schema SettingsのセクションのUser Object Filterが"(objectClass=inetOrgPerson)"になっているのがユーザーの検索条件で、これを、例えば"(&(objectClass=inetOrgPerson)(!(objectClass=posixAccount)))"とすれば良い。

●ユーザー情報の追加、JIRAでの確認(Posix Schemaのテスト用)
以下をuser13.ldifとして保存し、ldapaddで実行

dn: uid=user13,ou=people,dc=raffine,dc=moriguchi,dc=jp
objectClass: posixAccount
objectClass: inetOrgPerson
cn: user13
uid: user13
uidNumber: 10013
gidNumber: 10918
homeDirectory: /home/user13
userPassword: user13
mail: user13@localhost
sn: User No.13

dn: uid=user14,ou=people,dc=raffine,dc=moriguchi,dc=jp
objectClass: posixAccount
objectClass: inetOrgPerson
cn: user14
uid: user14
uidNumber: 10014
gidNumber: 10918
homeDirectory: /home/user14
userPassword: user14
mail: user14@localhost
sn: User No.14
以下をuser13m.ldifとして保存し、ldapmodifyで実行
dn: gidNumber=10918,ou=group,dc=raffine,dc=moriguchi,dc=jp
add: memberUid
memberUid: user13
memberUid: user14

→"User Directory"画面で"LDAP server 2"の"Synchronize"をクリックし、
 "User"画面でuser13やuser14が追加されていることを確認


●LDIFで属性値に日本語文字列を使用する方法
UTF-8の文字列をバイナリデータとして属性値に書く。
LDIFでは、バイナリデータは、属性名の後にコロンを2つ並べた後に、base64形式で書く。
例:
#sn: ユーザーNo.14
sn:: 44Om44O844K244O8Tm8uMTQ=
例えば、次のようにすると、上のbase64文字列が得られる。
echo -n ユーザーNo.14 | nkf -w | openssl base64

●slapdのログ出力の設定
syslog.confに

local4.* /var/log/slapd.log
を追加して、
touch /var/log/slapd.log
してsyslogdをkill -HUPすると、slapd.logに出力されるようになる。

なお、FreeBSDでは、特にこの設定をしなくても、/var/log/debug.logに出力される。


---
今回、CPUがCeleron 3.2GHzという10年前に買ったマシンにJIRAのインストールを試みたのだが、FreeBSD 9.2+OpenJDK6+Tomcat6という構成で、JIRA 6.2.6をWARインストールすると、タイムアウトを起こして起動しなかった。
試しに、それよりかなり速い、Intel Core i5 1.6GHzのMacBook上のVirtualBoxでは、同じFreeBSD 9.2+OpenJDK6+Tomcat6という構成で、同じようにインストールしてJIRA 6.2.6が起動したので、やり方は間違っていないと思う。

マシンスペックが低いとJIRAの起動時にシステムプラグインがタイムアウトするというのはよくあることらしく、必要なプラグインが一通り起動するまでの待ち時間を60秒から300秒に変えるよう、javaの引数に

-Datlassian.plugins.enable.wait=300
を加えるのが定跡となっている。実際、これを加えることによって、JIRA 5.2.11は起動するようになったのだが、JIRA 6.2.6はやはり起動しなかった。

(JIRA 6.2.6の起動失敗時のTomcatのログ)
2014-07-19 17:50:56,464 Timer-1 WARN [internal.dependencies.startup.DependencyWaiterApplicationContextExecutor] Timeout occurred before finding service dependencies for [NonValidatingOsgiBundleXmlApplicationContext(bundle=com.atlassian.activeobjects.activeobjects-plugin, config=osgibundle:/META-INF/spring/*.xml)]
2014-07-19 17:50:56,864 Timer-1 ERROR [internal.dependencies.startup.DependencyWaiterApplicationContextExecutor] Unable to create application context for [com.atlassian.activeobjects.activeobjects-plugin], unsatisfied dependencies: Dependency on [(objectClass=com.atlassian.sal.api.pluginsettings.PluginSettingsFactory)] (from bean [&pluginSettingsFactory])
org.springframework.context.ApplicationContextException: Application context initialization for 'com.atlassian.activeobjects.activeobjects-plugin' has timed out
at org.springframework.osgi.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor.timeout(DependencyWaiterApplicationContextExecutor.java:454)

これが発生すると、上記の300秒の待ち時間がほとんど残っているのに、JavaによるCPUの使用率が0に下がってしまい、何もせずにタイムアウト待ちになってしまう。

デフォルトではプラグインの全てが起動し終わるまでの待ち時間が60秒である他に、プラグインの1つ1つの起動の待ち時間が60秒に設定されているのが、1つの問題である。Tomcatのログに

2014-07-19 17:48:52,603 main WARN [factory.transform.stage.GenerateManifestStage] The Spring Manifest header in jar 'jira-gadgets-plugin-6.2.6.jar' isn't set for a 300 second timeout waiting for dependencies. Please add ';timeout:=300'
というのが20以上のプラグインについて出ていたので、これらのプラグインのJARファイルを1つ1つ、jar xfコマンドで展開して、META-INF/MANIFEST.MFやpom.xmlの";timeout=60"という文字列を";timeout=300"に変えて、jar Mcfコマンドで作り直してみた(注:そんなことをしなくても$JIRA_HOME/plugins/の.bundled-plugins/と.osgi-plugins/を削除してJIRAを再起動すれば良いらしい)が、"Please add ';timeout:=300'"というWARNINGは出なくなったが、上記のエラーは出続けた。
"activeobjects-plugin"とあるので、activeobjects-plugin-0.23.2.jarを展開し、META-INF/spring/atlassian-plugins-host-components.xmlの中のtimeout="200"等の値を全て10倍にしてみたが、次のログのように、症状は変わらなかった。
2014-07-20 11:07:08,571 main INFO [atlassian.plugin.manager.DefaultPluginManager] Initialising the plugin system
2014-07-20 11:09:06,928 Timer-1 WARN [internal.dependencies.startup.DependencyWaiterApplicationContextExecutor] Timeout occurred before finding service dependencies for [NonValidatingOsgiBundleXmlApplicationContext(bundle=com.atlassian.activeobjects.activeobjects-plugin, config=osgibundle:/META-INF/spring/*.xml)]
2014-07-20 11:09:08,002 Timer-1 ERROR [internal.dependencies.startup.DependencyWaiterApplicationContextExecutor] Unable to create application context for [com.atlassian.activeobjects.activeobjects-plugin], unsatisfied dependencies: Dependency on [(objectClass=com.atlassian.sal.api.pluginsettings.PluginSettingsFactory)] (from bean [&pluginSettingsFactory])
org.springframework.context.ApplicationContextException: Application context initialization for 'com.atlassian.activeobjects.activeobjects-plugin' has timed out
at org.springframework.osgi.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor.timeout(DependencyWaiterApplicationContextExecutor.java:454)
このログの先頭の2行の時刻を見る限り、pluginののロードが始まってから2分以内にtimeoutしており、timeoutを300秒等に設定した効果が出ていないようである。

このページにも、同様の問題を解決できないというコメントが残されている。
... but what this sets is the total time the start-up application waits for the plugins to be enabled not the internal timeout from each of the plugins with keeps being 60sec

タイムアウト時間を伸ばしさえすれば解決しそうなので、あと少し、と思い続けて結構な時間を費やしてしまったが、行き詰まったので、諦めてJIRA 5.2.11にして評価してみることにした。

【8/15 追記】
別のマシンでは起動したとはいえ、公式にはJIRA 6.2の動作環境としてはFreeBSDもOpenJDKもサポートされていない。そこで、上記のタイムアウトしてJIRA 6.2.6が起動しないマシンに、動作確認もされているCentOS 6.5+JDK1.7をインストールして試してみた所、JVMの引数に"-Datlassian.plugins.enable.wait=300"を加えただけで、あっさりJIRA 6.2.6が起動してしまった。
Standalone版(Linuxインストーラー版)とWAR版の両方を試したが、特にstandalone版の起動成功率が高い。WAR版は50%くらいの確率で上記と同じプラグインのタイムアウトを発生して起動に失敗する。WAR版のJVMの引数はstandalone版に合わせており、違いはTomcatのバージョンがstandalone版は7.0でWAR版は6.0である(yumでTomcat7がインストールできなかった為)ことくらいである。

マシンスペック的にはギリギリセーフだとわかったので、改めてFreeBSDでもJIRA 6.2.6の動作に取り組んでみた結果を以下に記す。なお、常にJVMの引数には"-Datlassian.plugins.enable.wait=300"を加えている。
・FreeBSD 9.2 + Tomcat6 + OpenJDK6で、VMの引数を-Xms128m -Xmx512mから-Xms384m -Xmx768mにすると、多少改善したが、データベース設定後、タイムアウトで起動せず
 -Xmsを384mより大きくするのは意味が無さそう
・OpenJDK6をlinux-sun-jdk17 に変えても改善は見られず
・Tomcatを7.0にしても、OpenJDK6でもlinux-sun-jdk17でも改善は見られず
・JVMの引数に-Djava.awt.headless=trueを加えるのも効果無し
・JVMの引数に-serverや-clientを加えるのも効果無し
・データベースをMySQLにしても内蔵DB(hsql)にしても同じ
・Tomcat6からhost-manager.xml, admin.xmlとJIRA以外の全てのwebappを削除しても変わらず
・.tar.gz形式のstandalone版JIRA 6.2.6(Tomcat7使用)を使用しても、OpenJDK6でもlinux-sun-jdk17でも同じ結果
 (mysql-connector-jへのリンクをlib/に置いて、bashへのリンクを/binに置いて、JIRA_HOMEとJAVA_HOMEをsetenvしてbin/start-jira.shを実行すると、別の速いマシンのFreeBSD 9.2では正常起動することを確認済)
・FreeBSD 9.3 + Tomcat6 + OpenJDK7で、起動成功率は30%と低いものの、WAR版JIRA 6.2.6のダッシュボード表示に成功
 pkgngで明示的にインストールしたpkg: tomcat6, tomcat-native, mysql51-server, mysql-connector-j
 成功時の/etc/rc.confの記述:

tomcat60_java_opts="-Djava.awt.headless=true -Dorg.apache.jasper.runtime.BodyContentImpl.LIMIT_BUFFER=true -Dmail.mime.decodeparameters=true -Datlassian.plugins.enable.wait=300 -Xms384m -Xmx768m -XX:MaxPermSize=256m"
・FreeBSD 9.2 + Tomcat6 + OpenJDK7でも、WAR版JIRA 6.2.6のダッシュボード表示に成功
 Tomcat6もOpenJDK7もpackagesからインストールした

FreeBSDでJIRA 6.2.6を動かすなら、OpenJDK7を使うのが良さそうである。

【9/27 追記】
現在のJIRAは、WAR版を使うメリットはほとんど無さそうである。
筆者のFreeBSDでは既にTomcatが動作していた為、Tomcatを含むStandalone版でなく、WAR版をインストールしたのだが、結局はTomcatの設定をStandalone版と細かい所まで一致させないと、まともに動かなかった。
Tomcatのインストールディレクトリに置く様々なライブラリ(JAR)も、JIRAが指定するバージョンのものでないと動作が不安定になるようであるし、そもそもJIRAのシステム要件ではTomcatのバージョンすら限定されている。
同じAtlassian製のJIRAとConfluenceすら、同じTomcatで動かしてはいけないとか同じTomcatでの動作はサポートしていないとかと書いてあり、JIRAは他のアプリと共存させることがあまり考慮されていないようである。
筆者は、今回JIRAをセットアップした経験から、JIRA 6.2のWAR版を使用するのは止めた方が良いと断言する。