レベル: 初級 池本 英貴, インダストリー・ソリューション・テクノロジー / ソフトウェア開発研究所, IBM
2006年 3月 03日
本稿では、OSやミドルウェアなどに含まれているアカウント情報をIBM Tivoli Identity Manager (TIM) で統合管理するために使用する、アダプターを開発する方法について説明します。
なお、本稿では以下の環境を前提としています。
- Red Hat Enterprise Linux AS 3.0
- DB2 UDB V8.2
- WAS V5.1.1
- Tivoli Identity Manager V4.6
はじめに
従来、アカウントは、OSやミドルウェアなどのサービスごとにシステム管理者が手作業で追加してきました。しかし、この方法では、次のような問題点があります。
- システム管理者の負担が大きい
- アカウントが使用可能になるまでに時間がかかる
- 使われなくなったアカウントの増大
これらの問題を解決するために、これまで使用されてきたアカウント管理の主なソリューションとしては、UnixにおけるNISや、WindowsにおけるActive Directoryなどがあります。しかし、これらは単一のOSでしか使えないなど、適用範囲が限られており、多数のOSやミドルウェアやアプリケーションが混在する今日におけるIT環境においては不十分です。
TIMは、IBMが提供するユーザー情報・アカウントの統合管理プラットフォームであり、数々のサービスのアカウントを統括して管理することができます。
アダプターとは
「アダプター」とは、TIMがサービスのアカウントを管理するために、TIMによるアカウントの操作要求を接続先のサービスのアカウント操作に変換するプログラムです。TIM 4.5までは「エージェント」と呼ばれていました。
TIMではいくつかの標準的なOS (AIX, Linux, Windows) やミドルウェア、アプリケーション (DB2 UDB, Oracle, SAP) については標準でアダプターを提供しています。しかし、アダプターが提供されていない環境を管理するためには、アダプターを開発する必要があります。
アダプターの開発には主に2種類の手法が使われます。1つは、TIM に同梱されている Tivoli Directory Integrator (TDI) を使用して開発する手法です。TDI は JDBC や LDAP といった標準的なプロトコルをサポートしているため、サービスがこれらのプロトコルを使用したアカウントの管理をサポートする場合に有効な手段です。もう1つは、TIM の Provisioning Connector API を使ってアダプターを開発する手法です。TIM の Provisioning Connector API は特定のプロトコルに依存しないため、独自プロトコルを使って通信する場合にも使用できます。
本稿では、2番目の、TIM の Provisioning Connector API を使ったアダプター開発について記述します。
アダプター開発の手順
TIMのアダプターを作成するためには、以下の作業を行う必要があります。
- TIM の Provisioning Connector API を使ったアダプターの実装
- サービスの定義を記述したプロファイルの作成
- アダプターのインストール
本稿では、JDBCを使用してRDBMSに格納されたアカウント情報をTIMで管理する、TIMsampleという名前のアダプターを作成します。
TIMsampleの概要
以下のような構造をした表に格納されたアカウント情報を、TIMで管理する例を使用します。
表1.users テーブル
| 列名 | 型 | 内容 |
|---|
| userid | varchar(20) | ユーザーID | | name | varchar(40) | ユーザーの名前 | | mailaddress | varchar(80) | ユーザーのメール・アドレス |
TIMはLDAPサーバーを使用してユーザー情報を管理しており、アカウントの情報をTIMで管理するためのスキーマが必要です。このスキーマを表2のように定めます。
表2.アカウントのスキーマ
| 属性名 | データ・タイプ | 内容 |
|---|
| eruid | 文字列 | ユーザーID | | cn | 文字列 | ユーザーの名前 | | mail | 文字列 | ユーザーのメール・アドレス |
また、管理対象のシステムをTIMのサービスとして登録するためのスキーマも必要です。このスキーマを表3のように定めます。
このTIMsampleアダプターでは、データベースに接続するためにJDBCを使っているため、接続先を識別するためのデータ・ソースを必要とします。そのため、サービスのスキーマにこのデータ・ソースを含める必要があります。
表3.サービスのスキーマ
| 属性名 | データ・タイプ | 内容 |
|---|
| erServiceName | 文字列 | サービス名 | | erSampleDataSource | 文字列 | データ・ソース |
LDAPスキーマとテーブルの列名との関係は以下のようになります。
表4.LDAPスキーマとテーブルとの関係
| usersテーブルの列名 | LDAP |
|---|
| userid | eruid | | name | cn | | mailaddress | mail |
TIM Provisioning Connector API
TIMのアダプターを作成するために必要なAPI は、以下の2つのインターフェースから構成されています。
表5.TIM Provisioning Connector API
| インターフェース名 | 内容 |
|---|
| ServiceProvider |
アダプターの本体であり、以下のようなメソッドが定義されています。(メソッドの詳細はJavadoc ドキュメントを参照)
- add: ユーザーの追加時に呼び出される
- delete: ユーザーの削除時に呼び出される
- modify: アカウント情報の変更時に呼び出される
- search: アカウントの調整時に呼び出される
- test: サービスの接続テスト時に呼び出される
| | ServiceProviderFactory | ServiceProviderを作成するためのファクトリー・クラス |
TIMでアカウント操作が行われると、その操作に対応したアダプターのAPIが呼び出されます。たとえば、アカウント追加の操作を行うと、APIのaddメソッドが呼び出されます。
表5のインターフェースを実装したクラスを作成します。図1、2はそれぞれ、ユーザーを追加するaddメソッド、ユーザーを削除するdeleteメソッドの実装の一部です。
図1.addメソッドの実装
public RequestStatus add(String objectClass,
AttributeValues attributeValues, String requestID) {
String userId = attributeValues.get("eruid").getValueString();
String name = attributeValues.get("cn").getValueString();
String mail = attributeValues.get("mail").getValueString();
try {
Connection conn = getConnection();
PreparedStatement stmt = conn
.prepareStatement("INSERT INTO USERS(userid, name, mailaddress) VALUES(?, ?, ?)");
stmt.setString(1, userId);
stmt.setString(2, name);
stmt.setString(3, mail);
stmt.execute();
return new RequestStatus(RequestStatus.SUCCESSFUL);
} catch (Exception e) {
SystemLog.getInstance().logError(this, e.getMessage());
RequestStatus status = new RequestStatus(RequestStatus.UNSUCCESSFUL);
status.setReasonMessage(e.getMessage());
return status;
}
} |
図2.deleteメソッドの実装
public RequestStatus delete(String entityDN, String requestID) {
try {
Account account = getAccount(entityDN);
String userId = account.getUserId();
Connection conn = getConnection();
PreparedStatement stmt = conn
.prepareStatement("DELETE FROM USERS WHERE USERID=?");
stmt.setString(1, userId);
stmt.execute();
return new RequestStatus(RequestStatus.SUCCESSFUL);
} catch (Exception e) {
SystemLog.getInstance().logError(this, e.getMessage());
RequestStatus status = new RequestStatus(RequestStatus.UNSUCCESSFUL);
status.setReasonMessage(e.getMessage());
return status;
}
}
|
プロファイル
TIMはアカウント管理システムを管理するために、サービスの定義を記述した「プロファイル」を必要とします。プロファイルは以下のファイルから構成されています。
表6.プロファイルに含まれるファイル
| ファイル名 | 内容 |
|---|
| schema.dsml | 管理対象のサービスとアカウントの情報をTIMのLDAPに登録するために必要なスキーマ(属性、オブジェクトクラス)の定義 | | resource.def | 管理対象のサービスの属性の定義 | | (アカウントのオブジェクトクラス名).xml | TIMのアカウント操作時に使用する入力フォームの定義 | | (サービスのオブジェクトクラス名).xml | TIMのサービス操作時に使用する入力フォームの定義 | | CustomLabels.properties | フォームに表示されるラベル文字列の定義 |
schema.dsml
アカウント情報をTIMで管理するためのLDAPスキーマを定義します。このファイルはDirectory Services Markup Language (DSML) v1で定義します。
図3. schema. dsml
<?xml version="1.0" encoding="UTF-8"?>
<dsml>
<directory-schema>
<!--
属性には以下の値を指定してください。
object-identifier: オブジェクトを一意に識別するための
LDAP OIDを指定します。既存のOIDと重複しない値を指定してください。
syntax: 属性のデータ・タイプを指定するためのLDAP OIDを指定します。
equality: 属性を比較するための規則を表すLDAP OIDを指定します。
LDAP OID の詳細はANS.1 Information Site
(http://asn1.elibel.tm.fr/) を参照してください。
-->
<!-- ******************************************************** -->
<!-- Service attributes -->
<!-- ******************************************************** -->
<attribute-type single-value="true">
<name>erSampleDataSource</name>
<object-identifier>
1.3.6.1.4.1.6054.3.200.2.1
</object-identifier>
<syntax>1.3.6.1.4.1.1466.115.121.1.15</syntax>
<equality>2.5.13.2</equality>
</attribute-type>
<!-- ******************************************************** -->
<!-- Class definitions -->
<!-- ******************************************************** -->
<class superior="top">
<name>erSampleService</name>
<description>
Class representing a TIM sample service
</description>
<object-identifier>
1.3.6.1.4.1.6054.3.200.1.1
</object-identifier>
<attribute ref="erServiceName" required="false" />
<attribute ref="erSampleDataSource" required="false" />
</class>
<class superior="top">
<name>erSampleAccount</name>
<description>
Class representing a TIM sample user account
</description>
<object-identifier>
1.3.6.1.4.1.6054.3.200.1.2
</object-identifier>
<attribute ref="erUid" required="true" />
<attribute ref="cn" required="false" />
<attribute ref="mail" required="false" />
</class>
</directory-schema>
</dsml> |
resource.def
管理対象のサービスの属性の定義を行うファイルです。以下の内容を指定します。
- プロトコルとそのオプション
- サービスデータのオブジェクト・クラスの指定
- アカウント・データのオブジェクト・クラスの指定
図4. resource.def
<?xml version="1.0" encoding="UTF-8"?>
<Resource>
<SystemProfile>
<Name>TIMSample</Name>
<Description>Sample service provider.</Description>
<BehaviorProperties>
<Property
Name="com.ibm.itim.remoteservices.ResourceProperties.SERVICE_PROVIDER_FACTORY"
Value="examples.serviceprovider.timsample.SampleServiceProviderFactory" />
<!-- Value には作成したアダプターのファクトリー・クラスの名前を指定してください。 -->
</BehaviorProperties>
</SystemProfile>
<AccountDefinition ClassName="erSampleAccount"
Description="TIM sample user account.">
</AccountDefinition>
<ServiceDefinition ServiceProfileName="tim_sample_service"
ServiceClass="erSampleService" AttributeName="erServiceName"
AccountClass="erSampleAccount" AccountProfileName="SampleAccount"
Description="TIM sample service.">
</ServiceDefinition>
</Resource>
|
(サービスのオブジェクト・クラス).xml
(アカウントのオブジェクト・クラス).xml
それぞれ、サービス、アカウントの操作時の入力フォームを定義したXMLファイルです。
入力フォームはTIMの「構成」→「フォームのカスタマイズ」から定義できますが、このファイルを事前に用意することで、入力フォームの定義作業を省略することができます。
図5. erSampleService.xml
<page>
<body>
<form action="formvalidator0">
<formElement name="data.erservicename" label="$erservicename">
<input name="data.erservicename" size="50" type="text"/>
</formElement>
<formElement name="data.ersampledatasource" label="$ersampledatasource">
<input name="data.ersampledatasource" size="50" type="text"/>
</formElement>
</form>
</body>
</page>
|
図6. erSampleAccount.xml
<page>
<body>
<form action="formvalidator0">
<formElement name="data.eruid" label="$eruid" required="true">
<input name="data.eruid" size="50" type="text"/>
<constraint><type>required</type><parameter>true</parameter></constraint></formElement>
<formElement name="data.cn" label="$cn">
<input name="data.cn" size="50" type="text"/>
</formElement>
<formElement name="data.mail" label="$mail">
<input name="data.mail" size="50" type="text"/>
</formElement>
</form>
</body>
</page>
|
CustomLabels.properties
入力フォームに表示されるラベル文字列を以下の形式で定義します。
属性名=ラベル文字列
TIMsampleのインストール
アダプターのインストール
rootユーザーで以下のコマンドを入力して、アダプターをコピーしてください。
# cp tim_sample_adapter.jar $(WAS_HOME)/AppServer/installedApps/{NODE_NAME}/enRole.ear
|
クラス・パスの設定
TIMにアダプターを認識させるためにクラス・パスを設定します。ここでは一例として、MANIFEST.MF ファイルのClass-Path に tim_sample_adaputer.jar を追加します。$(WAS_HOME)/AppServer/installedApps/{NODE_NAME}/enRole.ear/app_web.ear/META-INF/MANIFEST.MF を以下のように編集してください。
図7. MANIFEST.MF
Class-Path: batik.jar itim_api.jar itim_server.jar fesi.jar avalon.jar
…
diserverapi.jar tim_sample_adapter.jar
|
プロファイルのインストール
プロファイルのインストールには、TIMから提供されている以下のコマンドを使用してください。
# cd $(ITIM_HOME)/bin/unix # ./config_remote_services.sh -profile tim_sample_service
/var/ibm/tivoli/common/CTGIM/logs/trace.log を見て、
<LogText><![CDATA[Profile installation complete: tim_sample_service]]></LogText>
という文字列が見つかればインストール完了です。 プロファイルのインストールが終了したら、TIMを再起動し、サービス・プロファイルが正常に登録されたことを確認してください。
TIMsampleの概要
実装されている機能
アカウントの追加、削除(プロビジョン解除)、変更、調整機能が実装されています。
DBの定義
表1で定義された表を作成してください。それからWASのJDBCプロバイダーの設定を行い、JNDI名が'sampledb'であるデータ・ソースを作成してください。
TIMsampleの実行
サービスの追加
'Sample Service'というサービスがTIMに登録されています。
以下の画面例は、サービスの登録画面です。この登録画面で「Test」ボタンをクリックすると、DBサーバーへの接続テストが行われます。
DBサーバーへの接続が成功すると、次のような画面が表示されます。
以下は、プロビジョニング・ポリシーの追加画面です。
アカウントの調整を行うと、DBに格納されたアカウント情報とTIMのアカウント情報が同期されます。
新規アカウントの登録画面です。
アカウント作成時の情報入力画面です。
アカウントが正常に追加されました。DBにも同様の情報が反映されています。
まとめ
本稿ではTIM上で動作するアダプターを開発する方法について説明しました。
Provisioning Connector API の詳細な解説については、TIMに同梱されているJavadocドキュメントを参照してください。
また、$(ITIM_HOME)/extensions/examples/serviceprovider 以下に、サンプル・アダプターとその解説が含まれています。こちらの内容も参考になるでしょう。
ダウンロード | 内容 | ファイル名 | サイズ | ダウンロード形式 |
|---|
| tim_sample.zip | tim_sample.zip | 15.7KB | HTTP |
|---|
参考文献
著者について  | |  | 池本英貴は、ソフトウェア開発研究所の開発エンジニアです。主に金融関連のミドルウェアの開発を担当しています。 |
記事の評価
|