はじめに
LDAP認証を行うサーバー・サイドのJavaプログラムを開発することになったので、勉強のためにローカル環境(Windows 10環境)でサンプル・プログラムを動かしてみました。LDAPサーバーはOpenLDAPのDockerイメージを利用、データベースも付属のサンプルをそのまま利用して、まずはサーバー・サイドのサンプルJavaプログラムでLDAP認証してみることをゴールとしました。ladapsでの接続にちょっと手こずったので、注意点も含めてメモを残しておきます。
OpenLDAPのDockerイメージは以下のイメージを利用しました。
osixia/docker-openldap
サーバーはWebSphere Libertyを利用。以下からダウンロードしたWebSphere Liberty 21.0.0.10 + Java SE 8 for Windows (wlp-1.0.57.cl211020210920-1900)を使用しました。
WebSphere Liberty for developers
これから導入する方は、参考記事[5]をご一読することをお薦めします。
OpenLDAPをDocker上で起動
Windowsコマンド・プロンプトから以下を入力してOpenLDAPを起動します。
Window環境なのでコマンドの継続記号はバックスラッシュ('\')ではなくハット('^')になります。
docker run --hostname localhost -p 389:389 -p 636:636 ^
--name openldap ^
--volume C:\openldap\myvol:/myvol ^
--env LDAP_TLS_VERIFY_CLIENT=try ^
--detach osixia/openldap:1.5.0
後でOpenLDAPの証明書を取り出したりするのに使いたいので--volume C:\openldap\myvol:/myvol
を指定しておきます。
ldapsでアクセスしたいので--env LDAP_TLS_VERIFY_CLIENT=tryを指定しています。このTLSオプションはデフォルトがdemandに設定されており、デフォルトのままでldapsでアクセスするとエラーになります。
OpenLDAPのコンテナが起動したら、--volume
オプションで指定したディレクトリーにOpenLDAPの証明書ファイルをコピーします(以下参照)。コピーしたldap.crtは後で、WebSphere Libertyにインポートします。
dockerコンテナに入る。
docker exec -it openldap /bin/bash
OpenLDAPの証明書をコピーする。
cp /container/service/slapd/assets/certs/ldap.crt /myvol/
WebSphere Libertyの鍵ストアにパスワードを設定
以下、テスト用のWebSphere LibertyサーバーとしてMyServerというサーバーを新規作成した前提で説明します。
まず、server.xmlを編集して鍵ストア(defaultKeyStore)のパスワードを設定します。
<server description="new server">
<!-- Enable features -->
<featureManager>
<feature>webProfile-8.0</feature>
<feature>localConnector-1.0</feature>
</featureManager>
<!-- To access this server from a remote client add a host attribute to the following element, e.g. host="*" -->
<httpEndpoint httpPort="9080" httpsPort="9443" id="defaultHttpEndpoint"/>
<!-- Automatically expand WAR files and EAR files -->
<applicationManager autoExpand="true"/>
<applicationMonitor updateTrigger="mbean"/>
<webApplication id="LDAPTest" location="LDAPTest.war" name="LDAPTest"/>
<keyStore id="defaultKeyStore" password="password" />
</server>
テスト用に作成したサーバー(MyServer)のresources\security
ディレクトリー(下記参照)に既にkey.p12が存在する場合は削除します。サーバー起動時に前記ディレクトリーに鍵ストア・ファイル(key.p12
)が存在しないと自動的に作成されるのですが、その時設定されたパスワードが上記server.xmlで指定したパスワードと一致しないとエラーになってしまうため、既存の鍵ストア・ファイル(key.p12
)を削除します。こうすることで、次回サーバー起動時に上記server.xmlで指定したパスワードが設定された鍵ストア・ファイル(key.p12
)が新規作成されます。
wlp
|
+---usr
|
+---servers
|
+---MyServer
|
+---resources
|
+---security
key.p12
ltpa.keys
WebSphere Libertyを起動して、鍵ストアファイル(key.p12
)が作成されたことを確認します。
WebSphere Libertyの鍵ストア・ファイルにOpenLDAPの証明書をインポート
新しく作成されたWebSphere Libertyの鍵ストア(key.p12
)にOpenLDAPの証明書(ldap.crt
)をインポートします。
適当な作業ディレクトリーに以下の2つのファイルをコピーします。
- 新しく作成されたWebSphere Libertyの鍵ストア(
key.p12
) - OpenLDAPの証明書(
ldap.crt
)
以下のkeytoolコマンドでインポートします。
keytool -importcert -file ldap.crt -alias localhost -keystore key.p12 -storepass password -storetype PKCS12
以下のkeytoolコマンドでOpenLDAPの証明書(ldap.crt
)がインポートされたことを確認します。
keytool -list -v -keystore key.p12 -storetype PKCS12 -storepass password
OpenLDAPの証明書(ldap.crt
)をインポートした鍵ストア・ファイル(key.p12
)をサーバー(MyServer)のresources\security
ディレクトリーに上書きコピーします。
サーバー(MyServer)を再起動してエラーがなければ、WebSphere LibertyとOpenLDAPの接続作業は完了です。
サンプル・プログラムで疎通確認をしてみます。
OpenLDAPにテスト・ユーザーを登録
サンプル・プログラムでLDAP認証するために、前記Dockerイメージに付属のサンプル・データベースにテスト・ユーザーを登録します。まず、ldap.crtを搬出するのに使ったディレクトリー(C:\openldap\myvol
)にテスト・ユーザーを登録するためのLDIFファイル(u0001.ldif
)を作成します。
dn: uid=u0001,dc=example,dc=org
uid: u0001
cn: u0001
sn: 3
objectClass: top
objectClass: posixAccount
objectClass: inetOrgPerson
loginShell: /bin/bash
homeDirectory: /home/u0001
uidNumber: 10001
gidNumber: 10001
userPassword: u0001password
mail: u0001@example.org
gecos: TestUser 0001
以下のコマンドでテスト・ユーザーを登録します。
dockerコンテナに入る。
docker exec -it openldap /bin/bash
ldapaddコマンドでテスト・ユーザーを登録する。
ldapadd -x -D "cn=admin,dc=example,dc=org" -w admin -f /myvol/u0001.ldif -H ldap://localhost
サンプル・プログラムで疎通確認
以下のようなサーブレットを作成します。WebSphere LibertyとOpenLDAPの疎通確認を目的としたものなので、ユーザーIDとパスワードはハードコーディングしています。
package com.example;
import java.io.IOException;
import java.util.Hashtable;
import javax.naming.AuthenticationException;
import javax.naming.Context;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/LDAPAuthServlet")
public class LDAPAuthServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public LDAPAuthServlet() {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String msg = null;
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldaps://localhost:636");//ldapsで接続
env.put(Context.SECURITY_AUTHENTICATION, "simple");
//LDAP認証するユーザーIDとパスワード(OpenLDAPに登録したもの)を設定
String userid = "u0001";
String password = "u0001password";
env.put(Context.SECURITY_PRINCIPAL, "uid="+userid+",dc=example,dc=org");
env.put(Context.SECURITY_CREDENTIALS, password);
try {
//LDAP認証を実行
DirContext ctx = new InitialDirContext(env);
msg = "LDAP authentication successful.";
ctx.close();
} catch(AuthenticationException e) {
e.printStackTrace();
msg = e.getMessage();
} catch(Exception e) {
e.printStackTrace();
msg = e.getMessage();
}
response.getWriter().append(msg);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
上記サーブレットを含むwarをビルド、デプロイして、ブラウザーからアクセスしてみます。ブラウザーに"LDAP authentication successful."
のメッセージが表示されれば成功です。OpenLDAPのログには以下のようなメッセージが出力されます。
618a340d conn=1162 fd=12 ACCEPT from IP=172.17.0.1:58158 (IP=0.0.0.0:636)
618a340d conn=1162 fd=12 TLS established tls_ssf=256 ssf=256
618a340d conn=1162 op=0 BIND dn="uid=u0001,dc=example,dc=org" method=128
618a340d conn=1162 op=0 BIND dn="uid=u0001,dc=example,dc=org" mech=SIMPLE ssf=0
618a340d conn=1162 op=0 RESULT tag=97 err=0 text=
618a340d conn=1162 op=1 UNBIND
618a340d conn=1162 fd=12 closed
以上です。
WebSphere Application Server traditionalの場合
WebSphere Application Server traditional V9(以下tWASと表記)の場合は以下の手順でOpenLDAPの証明書をインポートします。
- 管理コンソールにログインします。
- 画面左側にあるメニューの「セキュリティー」を展開して、「SSL 証明書および鍵管理」をクリックします。
- 「構成設定」セクションの「エンドポイント・セキュリティー構成の管理」をクリックします。
- アウトバウンドのnodesフォルダーの下にあるノードのリンクをクリックします。
- 「関連項目」セクションの「鍵ストアおよび証明書」をクリックします。
- 一覧に表示されている「NodeDefaultTrustStore」をクリックします。
- 「追加プロパティー」セクションの「署名者証明書」をクリックします。
- 「追加」ボタンをクリックします。
- 「別名」フィールドに
localhost_cert
を入力します。 - 「ファイル名」フィールドにOpenLDAPの証明書のパス(
C:\openldap\myvol\ldap.crt
)を入力します。 - 「適用」ボタンをクリックします。
- 「保存」をクリックします。
補足)上記8~10の手順は、以下8'~12'の手順で代替することも可能です。
8'. 「ポートから取得」ボタンをクリックします。
9'. 「ホスト名」フィールドにlocalhost
を入力します。
10'. 「ポート」フィールドに636
を入力します。
11'. 「別名」フィールドにフィールドにlocalhost_cert
を入力します。
12'. 「署名者情報の取得」をクリックします。
参考記事
以下の記事を参考にさせていただきました。
[1] dockerでLDAP Serverを起動。ついでにphpLDAPadminも
[2] OpenLDAPでユーザー認証までやってみる
[3] Webアプリケーションの認証動作テスト用に Docker で openldap を立てみる
[4] LDAPクライアントプログラミングは怖くない(Java編)
[5] Libertyの始め方
[6] keytoolでWebSphere Liberty用の鍵ストアとトラストストアを作成する