前回はiDempiereの画面から実装したプロセスを起動する方法を紹介しました。
今回は、iDempiereの検証を進める中で気になっていた認証関連の調査結果をお伝えします。
認証サーバーとしてOpenLDAPを利用しましたので、その内容を共有させていただきます。
Ⅰ.OpenLDAPを認証サーバとして動作させた結果
一部のソースコードを修正し、iDempiereの設定を行った結果、OpenLDAPとの認証ができました。
もちろん、OpenLDAP認証を実現するためには他にも適切な方法があるかもしれませんが、この記事は参考情報としてご覧いただければと思います。
課題については、当記事「LDAP認証と運用時の課題」に記載しました。
LDAP認証を実際に導入する過程でさまざまな課題が浮かび上がりましたが、それらの詳細な解決策やベストプラクティスについては今後の課題となります。その一環として、LDAP認証の導入手順について以下で詳細に紹介いたします。
Ⅱ.事前知識と準備
Javaソースコードの修正とiDempiereの画面を用いて設定を行います。
iDempiereの開発環境を構築し、JPiereのプラグインが動作できるようにしておきます。
iDempiereの環境構築と開発環境の準備はこちらをそれぞれ参照ください。
その他、必要となるスキル面は以下です。
- Eclipse
- iDempiere(JPiere)
- OpenLDAP (Ver3ベースです)
- php LDAP admin (OpenLDAPのアカウント登録時に使用します)
※ OpenLDAP 公式サイトはこちらから
Ⅲ.iDempiereとLDAP連携の参考記事
接続情報に関する点は、こちらを参考にさせていただきました。
Ⅳ.LDAP認証機能の検証のながれ
今回は以下のながれで動作検証を行いました。
以下の内容を次章以降から紹介します。
Ⅴ.OpenLDAPの環境構築
Dockerを使用した環境構築には、こちらを参考にさせていただきました。ありがとうございました。
以下の内容から、phpLDAPadminを用いた環境構築およびLDAPのユーザ登録方法を把握することができます。
1) LDAP環境の起動
当検証において以下の内容でOpenLDAPサーバを利用します。
- LDAPサーバのDocker定義情報
以下の内容をdocker-compose.yml
ファイルに記述します。
version: '3'
services:
ldap-server:
image: osixia/openldap:latest
restart: always
container_name: ldap-host
environment:
LDAP_ORGANISATION: "erp"
LDAP_DOMAIN: "erp.work"
LDAP_ADMIN_PASSWORD: "password"
networks:
- webnet
ldap-admin:
image: osixia/phpldapadmin:latest
restart: always
container_name: ldap-admin
environment:
PHPLDAPADMIN_LDAP_HOSTS: "ldap"
PHPLDAPADMIN_HTTPS: "false"
ports:
- "8081:80"
links:
- "ldap-server:ldap"
networks:
- webnet
networks:
webnet:
- LDAPサーバの起動
DOSプロンプトからdocker-compose up -d
コマンドを実装しLDAPサーバーを起動します。
補足)登録結果
次章以降の手順に沿って登録した結果、以下の状態になります。
※ phpLDAPadminにより確認
ユーザを登録する所属DNをdc=erp,dc=work
とし、ou=users
に属するcn=ldapuser1
アカウントを登録した結果です。
またユーザ情報(ObjectClass)として、inetOrgPersonが適用されています。
今回検証したiDempiereの認証機能では、以下のRDN識別子を使用します。
dc:ユーザの所属するtopのDomain Component名(erp.workの2階層で表現)
ou: ユーザの所属するOrganization Unit名(usersとして定義)
cn: ユーザーのcommonName名(iDempiereではこの名称がログインIDとなります)
userPassword: ユーザーのログインパスワード(iDempiereではこのパスワードがログインパスワードになります)
2) ログイン
iDempiereからログインするユーザをOpenLDAPに登録します。
ブラウザを起動しlocalhost:8081
を入力しphp LDAP adminページにアクセスします。
LDAPサーバへログインします。
Login DN: cn=admin,dc=erp,dc=work
Password: password
※ docker-compose.ymlのLDAP_ADMIN_PASSWORD: "password"
で指定したパスワードを入力します。
3) 各RDN識別子の登録
1. 最初にouを追加します。
左メニューのdc=erp,dc=work
をクリックし、つづいて、Create a child entry
をクリックします。
2. objectClassを指定する画面が表示されます。
Generic: Organisational Unit
をクリックします。
3. Organisational Unit入力画面が表示されます。
users
を入力しCreate Object
ボタンをクリックします。
4. LDAP Entryの登録確認画面が表示されます。
Commit
ボタンをクリックします。
以上でouのRDN識別子登録は完了です。
ou=users
にて当階層にアクセスすることができます。
続いて、ou=usersの下にユーザを追加します。
5. ユーザを登録します。
左メニューのツリーを展開し、ou=users
欄をクリックし、つづいて、Create a child entry
をクリックします。
6. objectClassを指定する画面が表示されます。
Kolab: User Entry
をクリックします。
LDAPにユーザを登録する場合、数多くのobjectClassを使用することができます。
ツールおよびご利用のユーザ管理方法に沿って適切なobjectClassを指定します。
今回の検証では、登録ユーザのcnおよびpasswordが必要になるため、Kolabを指定しました。
7. ユーザ情報の登録画面が表示されます。
各項目を入力します。
Common Name
、Email
は後続の手順でiDempiereに登録します。
Common Name
は、姓名の間にスペースが付加されるためldapuser1
として入力しなおします。
また、Password
を登録する際にはclear
を指定します。
なお、ここでのPasswordは、user1password
とします。
Passwordを登録する際にclearを指定することによりパスワードがLDAP内に平文で保存されます。
iDempiereと連携してログインする場合、clear以外を指定すると正常にログインすることができませんでした。
また、iDempiereにおけるパスワード管理方法はデフォルトでは平文で保持(PostgreSQLのAD_Userテーブルに平文で保存されている)する設定になっています。
iDempiere側の設定に依存していると思われますが、まだ検証はできていません。
今回の検証では、iDempiereおよびLDAPに平文でパスワードを保持する設定を前提に進めます。
入力後、画面をスクロールしCreate Object
ボタンをクリックします。
8. LDAP Entryの登録確認画面が表示されます。
Commit
ボタンをクリックします。
以上でユーザ登録は完了です。
続いて、iDempiereの設定を行います。
Ⅵ.iDempiere設定
iDempiere側で以下の点の設定、登録をします。
ログインユーザ、ロールを切り替えながら設定を進めます。
iDempiereサービスを起動していない場合は、こちらを参考にサービスを起動します。
PostgreSQLサーバも起動しておきます。
- LDAPのDN定義の追加
- LDAP認証にOpenLDAP形式を使用する設定の追加
- LDAP認証するユーザの登録
- メールアドレスによる認証の無効化
1) LDAPのDN定義の追加
1. iDempiereにログインします。
ブラウザのURLにhttps://127.0.0.1:8443/webui
を入力しログインします。
ユーザ情報は以下を入力します。
- EMail: superuser@oss-erp.co.jp
- Password: System
ロール情報は以下を入力します。
- Tenant: System
- Role: System Administrator
2. System画面を開きます。
検索欄にSys
を入力するとSystem
が表示されます。
System
をクリックします。
3. System画面が表示されます。
LDAPのサーバー情報およびDN情報を入力します。
LDAPのDN定義の登録は以上です。
続いて、OpenLDAP形式を使用する定義を追加します。
2) LDAP認証にOpenLDAP形式を使用する設定の追加
1. System Configurator画面(新規登録)を開きます。
検索欄にSys
を入力するとSystem Configurator
が表示されます。
System Configurator
行の新規
ボタンをクリックします。
2. LDAP_TYPEを追加します。
以下の欄を入力および選択します。
- Name: LDAP_TYPE
- Configured Value: openldap
- Entity Type: iDempiere
-
Configuration Level: System
入力したら保存ボタンをクリックします。
以上で、OpenLDAP形式を使用する設定は完了です。
つづいて、LDAP認証するユーザを登録します。
3) LDAP認証するユーザの登録
LDAP認証するユーザ情報を、iDempiereにも登録します。
株式会社OSS ERP Solutionsに属するユーザとして追加します。
1. 現在ログインしているSystem:System Administrator
を株式会社OSS ERP Solutions:Admin Role
に切り替えます。
画面上部のChange Role
をクリックします。
2. テナントおよりロールの指定画面が表示されます。
以下のロールを指定します。
3. User画面(新規登録)を開きます。
検索欄にuser
を入力するとUser
が表示されます。
User
行の新規
ボタンをクリックします。
4. ユーザ情報の新規登録画面が表示されます。
それぞれの項目を入力します。
最初にUser Contact
情報を入力します。
- Name: LDAP User1
- EMail Address: ldapuser1@yourdomain.com.com
- Password: dummy
-
LDAP User Name: ldapuser1
※ LDAP User Nameには、上記のLDAP登録したCN
名と一致させます。
LDAP認証を使用する際も、EMail Address
およびPassword
を入力する必要があります。
5. つづいてに権限情報を入力します。
画面下のDetail Record
エリアを開きます。
新規
ボタンをクリックし、虫眼鏡
ボタンをクリック後、所属するロールを選択します。
虫眼鏡
ボタンをクリック後、ログインユーザのロールが表示されます。
Name
欄のテキストを削除し、再表示ボタンをクリックすると登録されているロールが全て表示されます。
ロールの設定と同様に、つづいて、Org Access
タブをクリックしOrgを登録します。
同エリアにLDAP Access
というタブがありますが、登録は特に行いません。
以上でユーザ登録の作業は完了です。
つづいて、最後の設定です。
メールアドレスによる認証を無効にし、ユーザIDでログインできるようにします。
4) メールアドレスによるログインの無効化
ログイン方法を変更するにあたり、再度ロールを切り替えて設定します。
1. ロールを切り替えます。
上記の手順同様に、画面上部Chainge Role
をクリックし、以下のロールに切り替えます。
ロール情報は以下を入力します。
- Tenant: System
- Role: System Administrator
2. メールアドレスログインを無効化します。
検索欄にsys
を入力するとSystem Configurator
が表示されます。
System Configurator
行をクリックします。
3. 検索画面が表示されます。
Name
欄にUSE_EMAIL_FOR_LOGIN
を入力し、検索します。
4. USE_EMAIL_FOR_LOGINの設定内容が表示されます。
Configured Value
をN
にします。
変更したら保存
ボタンをクリックします。
以上でメールアドレスによるログインの無効化の設定は完了です。
iDempiere画面からの設定は全て完了しました。
つづいて、Eclipseを開きソースコードを一部修正します。
Ⅶ.iDempiereのソースコード改修点
修正点は、RDN識別子名称の変更です。
デフォルトのuidがログイン関数による検証でどうしてもエラーになります。
RDN識別子でcnを使用するようにします。
1) RDN識別子の変更
- 対象のパッケージ: org.compiere.db
- 修正クラス: LDAP
- 修正ソースファイル: org.adempiere.base/src/org/compiere/db/LDAP.java
validateメソッド内の以下の点を修正します。
public static boolean validate (String ldapURL, String domain, String userName, String password)
{
Hashtable<String,String> env = new Hashtable<String,String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
// ldap://dc.compiere.org
env.put(Context.PROVIDER_URL, ldapURL);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
StringBuilder principal;
if ("openldap".equals(MSysConfig.getValue(MSysConfig.LDAP_TYPE))) {
- principal = new StringBuilder("uid=").append(userName).append(",").append(domain);
+ principal = new StringBuilder("CN=").append(userName).append(",").append(domain);
} else {
principal = new StringBuilder(userName).append("@").append(domain);
}
env.put(Context.SECURITY_PRINCIPAL, principal.toString());
env.put(Context.SECURITY_CREDENTIALS, password);
//
try
{
// Create the initial context
InitialLdapContext ctx = new InitialLdapContext(env, null);
// DirContext ctx = new InitialDirContext(env);
// Test - Get the attributes
ctx.getAttributes("");
// Print the answer
//if (false)
// dump (answer);
}
catch (AuthenticationException e)
{
if (log.isLoggable(Level.INFO)) log.info("Error: " + principal + " - " + e.getLocalizedMessage());
return false;
}
catch (Exception e)
{
log.log (Level.SEVERE, ldapURL + " - " + principal, e);
return false;
}
if (log.isLoggable(Level.INFO)) log.info("OK: " + principal);
return true;
} // validate
Javaコードの修正は以上です。
以上で、LDAP認証の準備は全て整いました。
実際に動作をします。
ソースコードを修正しているので、iDempiereサービスを再起動します。
Ⅷ.動作確認
LDAP認証によるログインの確認です。
電子メールによる認証からユーザIDによる認証に変更しましたので、先ほどまで入力していた欄がEMail
からUser
に変わっています。
画面のログイン画面にLDAPに登録したユーザldapuser1
を入力し、パスワードにuser1password
を入力します。
テナント・Role画面が表示されれば、LDAP認証処理は成功です。
ldapuser1ユーザに定義したロール情報が表示されますので、選択してOK
ボタンによりログインします。
Ⅸ.LDAP認証と運用時の課題
LDAP認証とその運用における課題についてです。今回はOpenLDAPを用いた認証機能を検証しましたが、いくつかの課題が浮かび上がりました。もしかすると設定等で回避することができるかもしれませんが、以下にそれらの課題をいくつか紹介いたします。
1. LDAPサーバのDN名が固定(ouの指定を含む)
iDempiereのLDAPサーバ参照時のDN(LDAP Domain)の定義が1つしかなく、ユーザ認証のために使用するou=users,dc=erp,dc=workの定義を固定で設定する必要がありました。
2. ログインユーザのロールに応じたLDAP内のouの定義がiDempiereの仕様上難しい(階層状の定義など)
ログインするユーザのロール階層に基づいてLDAPの階層を一致させることができませんでした。実際の運用では、LDAP上の定義として課部署など階層状に登録することが想定されますが、ログイン時の認証認可の制御については、認証(課部署情報を含まない)にはLDAPを使用し、認可についてはiDempiereの設定に依存する形になりました。
3. ソースコードの改修が必要
OpenLDAPで認証する際、標準の実装ではRDN識別子としてuidが記述されており、InitialLdapContextメソッドによる認証の検証処理が正常に行えませんでした。OpenLDAPにユーザを登録する際に適用するObjectClassによっては、uidが存在しているものの、認証処理でエラーが発生しました。posixAccountの適用や個別にuidを追加したユーザを登録しても、認証エラーによりログインができませんでした。
Ⅹ.次回は
今回は、認証機能の第1弾としてOpenLDAP認証について動作確認を行いました。
次回も他の認証機能を用いたユーザ認証処理について調査を進めたいと思います。