この章では、編成に関する概念と、Oracle Identity Managerの機能を拡張するためのカスタム・イベント・ハンドラの作成方法について説明します。内容は次のとおりです。
Identity Managementシステムでは、ユーザーまたはシステムによって実行されるアクションは、操作と呼ばれます。操作には、ユーザーの作成、ロールの変更、パスワード・ポリシーの作成などがあります。事前に定義された一連のステージを進み、各ステージでなんらかのビジネス・ロジックを実行するOracle Identity Manager操作を編成と呼びます。編成によって変更されるオブジェクトのタイプを編成ターゲットと呼びます。編成操作の実行に必要なデータを編成パラメータと呼びます。
バルク編成は、複数のエンティティで同じ操作を編成するプロセスです。たとえば、複数ユーザーの組織を更新する場合にバルク編成を送信できます。その結果、すべてのエンティティに対する操作が1回のコールで実行されます。
注意: ロック/ロック解除操作に対してカスタムのイベント・ハンドラの導入が必要な場合は、バルク編成を実装する必要があります。シングル・ユーザーのロック/ロック解除操作のバルク編成は、UIから起動されます。 |
編成は、ステージと呼ばれる事前に定義されたステップに分割されます。すべての操作は、終了処理に到達するまで、これらのステージを移動します。編成には次のステージがあります。
検証: 編成パラメータの整合性など、編成に対する検証を実行するステージ。編成パラメータは、編成操作を実行するために必要なデータです。
前処理: 編成パラメータ操作の実行、承認の取得または職務の分離チェックを実行するステージ。
アクション: アクションを実行するステージ。
監視: 操作の監視が実行されるステージ。
後処理: 現行の操作に関連する結果としての操作が実行されるステージ。結果としての操作には、自動ロール・メンバーシップや、ユーザー作成に対するポリシー評価があります。
終了処理: クリーン・アップを実行する、プロセスの最後のステージ。
実行される各操作には、ユーザーやその他のエンティティに影響を及ぼすものもあります。たとえば、ユーザーを作成するとそのユーザーに対するリソースのプロビジョニングが発生し、新規パスワード・ポリシーを作成すると特定のユーザー・パスワードが無効になって次のログイン時に変更を要求される場合があります。結果としての各操作は編成として表されます。遅延された結果としての処理は、現行の編成の終了処理の前に実行されます。即時結果は、現行のイベント・ハンドラが戻された直後、現行の編成の次のイベント・ハンドラに進む前に実行されます。ユーザーの作成、変更、削除、有効化、無効化、ロック、ロック解除などのいくつかの操作の結果は、後続の項に示すとおり、イベント・ハンドラを作成することによってカスタマイズできます。
後処理ステージが開始点となる編成もあります。信頼できるソースからユーザーを調整する場合や、ユーザーをバルク・ロードしてこのデータをそのままOracle Identity Managerに追加する場合です。データがOracle Identity Managerにある場合は、ユーザーに対する後処理操作を実行し、自動グループ・メンバーシップの計算やポリシーの評価ができます。その結果、リコンシリエーション・エンジンやバルク・ロード・ユーティリティによって後処理専用の編成が送信されます。
イベント・ハンドラ は、様々なステージで編成に登録されるコードです。これらのイベント・ハンドラは、関連する編成ステージが実行されたときに起動されます。イベント・ハンドラは、同期がとられる場合と非同期の場合があります。同期イベント・ハンドラはすぐにレスポンスを返しますが、非同期イベント・ハンドラは後のステージで完了します。イベント・ハンドラは条件付きにすることができ、これは、特定の条件が満たされた場合に実行されることを意味します。
編成の各ステージにおける処理は、そのステージに配置されているブランチおよびイベント・ハンドラ(存在する場合)によって決定されます。ステージにブランチがある場合は、イベント・ハンドラからのレスポンスによって、使用するブランチが決まります。ステージにイベント・ハンドラがない場合、またはイベント・ハンドラからのレスポンスに推奨パスがない場合、操作はデフォルトのパスに従って次のステージに移ります。ただし、イベント・ハンドラが無効な場合や取り消された場合、プロセスは帯域外ステージに移ることができます。次のステージがあります。
無効: 編成の検証に失敗した場合、プロセスはこのステージに移ります。
拒否: 前処理イベント・ハンドラが拒否された場合、プロセスはこのステージに移ります。たとえば、承認者によって承認が却下された場合、編成は拒否されます。
取消し: 取消しメソッドをコールすることによって操作が停止された場合、プロセスはこのステージに移ります。
補正: 補正メソッドをコールすることによって操作がロールバックされた場合、プロセスはこのステージに移ります。
図28-1に、様々な編成ステージを示します。
Oracle Identity Managerを使用すると、編成操作の機能をカスタマイズするためにService Provider Interfaces (SPI)を実装できます。エンティティ編成の操作でサポートされるのは、前処理、後処理、検証および終了処理ステージのカスタマイズのみです。
イベント・ハンドラの実装の例を次に示します。
ユーザーの作成時、アカウントのステータス(有効または無効)が同じルールに基づいて設定されます。これを実行するために前処理イベント・ハンドラを実装できます。
契約者というタイプのユーザーを作成するときは、このユーザーに電子メール・アドレスが必要です。その他のユーザーは、電子メール・アドレスがなくても作成できます。ユーザーが契約者かどうかを検証する場合に検証イベント・ハンドラを使用でき、検証結果に基づいてユーザー作成を許可または禁止します。
エージェントというタイプのユーザーを作成した後に、このユーザーの代替電子メール・アドレスで通知を受け取るようにします。これは、後処理イベント・ハンドラを実装することによって実行できます。
後処理イベント・ハンドラは、ビジネス要件を満たすために最も一般的に実装されます。後処理イベント・ハンドラの実装によって特定の要件を満たすことができる例を次に示します。
要件
エンタープライズ・ユーザーが契約者の場合、Oracle Identity Managerでユーザーを作成した後、ユーザーは、外部アプリケーションである契約者登録システムに登録される必要があります。これはデータベース・アプリケーションです。データベースには、ユーザーのユーザーID、契約者ID、名、姓の各属性を格納する構造があります。正常に登録された後は、Oracle Identity Managerのユーザー・プロファイルでユーザーの契約者IDが取得され、更新される必要があります。
解決策
このユースケースはプラグインとして開発でき、Oracle Identity Managerにデプロイできます。プラグインは、契約者IDや指定したデータベース表からの構成済の列名の取得、およびOracle Identity Managerでのユーザー・プロファイルの更新に使用できます。後処理イベント・ハンドラは、ユーザー・エンティティの作成操作用に実装および登録できます。これは、条件付きのイベント・ハンドラで、タイプが契約者であるユーザーに対してのみ実行されます。ユーザー・タイプが契約者の場合、イベント・ハンドラは外部アプリケーションに接続し、Oracle Identity ManagerのユーザーIDに基づいて契約者IDを取得し、契約者IDを使用してOracle Identity Managerでユーザー・プロファイルを更新します。
次に、イベント・ハンドラの後処理実装の例をもう1つ示します。
Oracle Identity Managerでリコンサイルされるデータが、すべてのユースケースを実装するには不十分で、リコンサイルしたデータに基づいて追加の属性を生成する必要がある場合のカスタム属性の生成です。これは、特にカスタム属性がロール・メンバーシップ・ルールまたはアクセス・ポリシーで使用される場合に一般的なユースケースです。
イベント・ハンドラは、次のもので構成されます。
Javaコード: 操作の実装
XML定義: 適切なステージでの関連する編成との関連付け
プラグイン定義: Oracle Identity Managerプラグイン・フレームワークへのイベント・ハンドラおよび拡張コードの登録
カスタム・イベント・ハンドラの開発では、Javaコードを使用した操作の実装、XML定義の記述、プラグインの作成と登録が行われます。これについて次の項で説明します。
この項では、SPIの実装によるJavaコードの作成と、JARファイルの作成方法について説明します。
カスタム・イベント・ハンドラを作成する際、次の事項を考慮する必要があります。
カスタム・イベント・ハンドラを登録できる編成ステージは、検証、前処理および後処理です。
検証、前処理および後処理イベント・ハンドラは条件付きにできます。これは、特定の条件が満たされた場合にのみイベント・ハンドラが実行されるという意味です。
イベント・ハンドラを条件付きにするには、oracle.iam.platform.kernel.spi.ConditionalEventHandlerインタフェースとそのisApplicableメソッドを実装します。このメソッドでは、コンテキスト・データと編成パラメータが使用可能です。条件付きイベント・ハンドラの場合、操作の開始時にイベント・ハンドラの適用性が計算されます。したがって、編成フローの中でコンテキストまたは編成パラメータが変更されると、実行してはいけないイベント・ハンドラが実行される場合があります。
イベント・ハンドラは、単一のエンティティもバルク・エンティティも処理できます。
イベント・ハンドラは、親ハンドラでの特定の操作をコールバックする、関連付けられた失敗ハンドラを持つことができます。
イベント・ハンドラの再試行がサポートされているため、イベント・ハンドラはリエントラントです。
リコンシリエーションによって後処理編成が送信される場合、バルク編成が送信されます。イベント・ハンドラに対するbulkExecuteメソッドは、これらの編成に対してコールされます。したがって、必ずこのメソッドを実装してください。
カスタム・イベント・ハンドラ間でデータが渡される場合は、イベント間データを使用して渡すことができます。編成に対してgetInterEventData()メソッドをコールすると、ハッシュマップが返されます。このマップでは、カスタムで始まるキーを持つオブジェクトを配置でき、後続のカスタム・ハンドラでこのデータにアクセスできます。同じハッシュマップに含まれる事前定義されたイベント間データは変更または削除しないでください。
書込みまたは削除操作のためにイベント・ハンドラ内部でAPIコールを行うには、Platform.getServiceForEventHandlersメソッドを使用してAPIサービスを取得します。このメソッドを使用して取得したサービスを使用して行われたAPIコールは、後処理を含め、同期をとって実行されます。
検証ハンドラを除くイベント・ハンドラの戻りタイプを次の表に示します。
イベント・ハンドラのタイプ | 成功時 | 失敗時 |
---|---|---|
同期 | executeメソッドの新規EventResult()と、バルク・バージョンのexecuteメソッドの新規BulkEventResult() | EventFailedException |
非同期 | nullを返します | EventFailedException |
イベント・ハンドラでオブジェクト・レベル変数を定義しないでください。
表28-1に、様々な編成ステージで実装できるメソッドを示します。
表28-1 イベント・ハンドラを実装するためのメソッド
メソッド | 適用可能な編成ステージ | 説明 |
---|---|---|
initialize |
前処理、後処理 |
このメソッドは、接続を開き、状態またはリソースをプールするために使用します。 |
execute for single entity |
前処理、後処理 |
このメソッドは、基礎となる操作の入力属性を読み取り、(必要に応じて)別の値に更新する場合に使用します。 |
execute for bulk orchestration |
前処理、後処理 |
このメソッドは、基礎となる複数の操作の入力属性を読み取り、(必要に応じて)別の値に更新する場合に使用します。 |
isApplicable |
条件付き |
このメソッドは、条件付きハンドラで、イベント・ハンドラ実行の前提条件が満たされるかどうかを判別するために使用します。 |
validate |
validation |
このメソッドは、検証ハンドラで入力データを検証する場合に使用します。 |
cancel |
前処理、後処理 |
このメソッドは、編成操作が取り消される場合にコールされます。 |
compensate |
前処理、後処理 |
このメソッドは、編成操作が補正される場合にコールされます。 |
executeなどのメソッドでは、次の引数値が使用可能です。
トラブルシューティングのためにコードに含めることができるID:
プロセスID: 編成インスタンスのID
イベントID: イベント・ハンドラ・インスタンスのID
基礎となるエンティティ・インスタンスの詳細情報で構成される編成オブジェクト。次のもので構成されます。
基礎となるエンティティの入力属性の読取り元となるENTITY_ATTRIBUTE、VALUEを含むマップ(キー値ペア)。
エンティティID: 同じエンティティまたは異なるエンティティの値を元に戻すには、エンティティ・マネージャAPIを使用して、エンティティIDおよびデータを渡します。バルク編成の場合、複数のエンティティIDとマップを取得します。
注意: Platform.getServiceForEventHandlersを使用して、イベント・ハンドラで作成、更新および削除操作をコールするサービスを取得します。 |
この項では、様々な種類のイベント・ハンドラを作成する方法を説明するコード例を示します。
例1: カスタム電子メール検証
例28-1に、ユーザーの電子メールIDにアンパサンド(@)が使用されていることを確認する、カスタム検証ハンドラのコード例の一部を示します。
例28-1 カスタム電子メール検証
public void validate(long processId, long eventId, Orchestration orchestration) throws ValidationException, ValidationFailedException { HashMap<String, Serializable> parameters = orchestration.getParameters(); String email = (parameters.get("Email") instanceof ContextAware) ? (String) ((ContextAware) parameters .get("Email")).getObjectValue() : (String) parameters .get("Email"); if (!(email.contains("@"))) { throw new ValidationFailedException("Email doesn't contain @"); } }
例2: ミドル・ネームを設定するカスタム前処理イベント・ハンドラ
例28-2に、ミドル・ネームに値が指定されていない場合に、ミドル・ネームを名の最初の文字に設定するカスタム前処理イベント・ハンドラのコード例の一部を示します。
例28-2 ミドル・ネームを設定するカスタム前処理イベント・ハンドラ
// the middle initial when the user doesn't have a middle name public EventResult execute(long processId, long eventId, Orchestration orchestration) { HashMap<String, Serializable> parameters = orchestration .getParameters(); // If the middle name is empty set the first letter of the first name // as the middle initial String middleName = getParamaterValue(parameters, "Middle Name"); if ((middleName == null) || middleName.equals("")) { String firstName = getParamaterValue(parameters, "First Name"); middleName = firstName.substring(0, 1); orchestration.addParameter("Middle Name", middleName); } return new EventResult(); } private String getParamaterValue(HashMap<String, Serializable> parameters, String key) { if(parameters.containsKey(key)){ String value = (parameters.get(key) instanceof ContextAware) ? (String) ((ContextAware) parameters .get(key)).getObjectValue() : (String) parameters.get(key); return value; } else{ return null; } }
例3: リソース・オブジェクトをプロビジョニングするカスタム後処理イベント・ハンドラ
例28-3に、ロールがROLE 005であるユーザーにリソース・オブジェクトOBJ005をプロビジョニングするカスタム後処理イベント・ハンドラのコード例の一部を示します。
例28-3 カスタム後処理イベント・ハンドラの例
// This custom post process event handler provisions resource object 'OBJ005' // to a user who has role 'ROLE 005' public EventResult execute(long processId, long eventId, Orchestration orchestration) { tcUserOperationsIntf userOperationsService = Platform.getService(tcUserOperationsIntf.class); try { String userKey = getUserKey(processId, orchestration); if (hasRole(userKey, "ROLE 005")) { long objKey = findObject("OBJ001"); userOperationsService.provisionResource(Long.getLong(userKey), objKey); } } catch (Exception e) { throw new EventFailedException(null, "Error occurred", null, null, e); } return new EventResult(); } // This method retrieves the key of the user entity on which an operation // is performed // This method shows how to retrieve the operation being performed, entity type // and the associated value objects private String getUserKey (long processID, Orchestration orchestration) { String userKey; String entityType = orchestration.getTarget().getType(); EventResult result = new EventResult(); if (!orchestration.getOperation().equals("CREATE")) { userKey = orchestration.getTarget().getEntityId(); } else { OrchestrationEngine orchEngine = Platform.getService(OrchestrationEngine.class); userKey = (String) orchEngine.getActionResult(processID); } return userKey; } // This method checks if a given user has a given role. // It demonstrates how to invoke a OIM 11g API from a custom event handler private boolean hasRole(String userKey, String roleName) throws Exception { RoleManager roleManager = Platform.getService(RoleManager.class); List<Role> roles = roleManager.getUserMemberships(userKey, true); for (Iterator iterator = roles.iterator(); iterator.hasNext();) { Role role = (Role) iterator.next(); if (roleName.equals((String)role.getAttribute("Role Name"))) { return true; } } return false; } // This method finds details about a resource object with the given name. // It demonstrates how to invoke a 9.1.x API from a custom event handler private long findObject(String objName) throws Exception { long objKey = 0; tcObjectOperationsIntf objectOperationsService = Platform.getService(tcObjectOperationsIntf.class); HashMap params = new HashMap(); params.put("Objects.Name", objName); tcResultSet objects = objectOperationsService.findObjects(params); for (int i = 0; i < objects.getRowCount(); i++) { objects.goToRow(i); if (objects.getStringValue("Objects.Name").equals(objName)) { objKey = objects.getLongValue("Objects.Key"); } } return objKey; }
例4: bulkExecuteメソッドを使用するカスタム・ユーザー後処理イベント・ハンドラ
例28-4に、バルク・ユーザー作成編成に含まれるユーザーをループする方法を示します。
例28-4: bulkExecuteメソッドを使用するカスタム・ユーザー後処理イベント・ハンドラ
public BulkEventResult execute(long processId, long eventId, BulkOrchestration orchestration){ HashMap<String, Serializable>[] orchParamArray = orchestration.getBulkParameters(); // Array of user keys String [] entityIds = orchestration.getTarget().getAllEntityId(); for(int i=0; i< entityIds.length; i++){ } }
例5: isApplicableメソッドでのコンテキストの使用
Oracle Identity Managerでの操作は、複数のコンテキストで実行できます。たとえば、ユーザーの作成は、管理者がユーザーをダイレクト操作として作成する場合、管理者がリクエストを送信することによってユーザーを作成する場合、自己登録によってユーザーを作成する場合、および信頼できるソース・リコンシリエーションによってユーザーを作成する場合という4つのコンテキストで発生する可能性があります。これらのすべてのシナリオで、Oracle Identity Managerは、同じデータ型で、同じパラメータ名と値を持つ、同じユーザー作成編成を送信します。
例28-5には、イベント・ハンドラの適応性を示すためにこの操作を実行するコンテキストの検出方法を示します。
例28-5 isApplicableメソッドでのコンテキストの使用
public boolean isApplicable(AbstractGenericOrchestration orchestration) { // Request Context if (ContextManager.getContextType() == ContextTypes.REQUEST) { } // Recon context if (ContextManager.getContextType() == ContextTypes.RECON) { } }
カスタム・イベント・ハンドラ・コードを使用してJARを作成するには:
表28-2に示すSPIのいずれかを実装して、カスタム前処理、後処理または検証ハンドラを作成します。
表28-2 カスタム・イベント・ハンドラを作成するためのSPI
ステージ | 実装するSPI |
---|---|
前処理 |
oracle.iam.platform.kernel.spi.PreProcessHandler |
後処理 |
oracle.iam.platform.kernel.spi.PostProcessHandler |
検証 |
oracle.iam.platform.kernel.spi.ValidationHandler |
終了処理 |
oracle.iam.platform.kernel.spi.FinalizationHandler |
カスタム・クラスをコンパイルするクラス・パスに次のJARファイルを含めます。
OIM_ORACLE_HOME/server/platform/ディレクトリから:
iam-platform-kernel.jar
iam-platform-utils.jar
iam-platform-context.jar
iam-plaftorm-authz-service.jar
OIM_ORACLE_HOME/designconsole/lib/ディレクトリから:
oimclient.jar
xlAPI.jar
コンパイルに他のOracle Identity Manager JARファイルが必要な場合は、この手順に示すディレクトリにあります。
カスタム・クラスのJARファイルを作成します。
イベント・ハンドラの例外処理では、条件付きのJAVA例外処理メソッドを使用する必要があります。失敗時の処理には次のガイドラインを参照してください。
イベント・ハンドラ・コードで、失敗を示す適切な引数を指定してEventFailedExceptionをスローします。
失敗は、失敗ハンドラを登録することによって処理できます。失敗ハンドラの一部として、失敗を修正するために必要なロジックを実装できます。失敗ハンドラは、レスポンスとして次のオプションを持つFailedEventResultを返す必要があります。
CANCEL: 操作を取り消す必要があることを示します。これまでに実行され完了したすべてのイベント・ハンドラに対するCancelメソッドは、カーネルによって実行とは逆の順にコールされます。
COMPENSATE: 操作をロールバックする必要があることを示します。これまでに実行され完了したすべてのイベント・ハンドラに対するCompensateメソッドは、カーネルによって実行とは逆の順にコールされます。
MANUAL_COMPLETE: 失敗したハンドラは手動で完了され、残りのイベント・ハンドラが処理されることを示します。
RETRY: 失敗したイベント・ハンドラを再試行する必要があることをカーネルに示します。
NULL: 失敗したハンドラによるレスポンスや推奨がないことを示します。
この項では、イベント・ハンドラXMLファイル内の、一部の要素および要素の属性について説明します。また、イベント・ハンドラXML定義の必須の名前空間についても説明します。
要素
イベント・ハンドラXMLファイルのトップレベル(親)要素は、eventhandlers
です。表28-3に、eventhandlers
親要素内に一般的に定義されるサブ要素を示します。
表28-3 eventhandlers要素内の一般的なサブ要素
サブ要素 | 説明 |
---|---|
|
編成に対して実行される検証を識別します。 |
|
前処理、後処理およびアクション・ステージで実行される操作を識別します。 |
|
デフォルトのフローでイベント・ハンドラが失敗した場合に実行されるイベント・ハンドラを識別します。 |
|
編成の最後に実行されるイベント・ハンドラを識別します。終了処理は、編成の最後のステージです。 |
|
影響の編成が失敗した場合に親編成で実行されるイベント・ハンドラを識別します。 |
|
拒否や取消しなどの帯域外編成フローのイベント・ハンドラを定義します。 |
|
編成の補正フローで実行されるイベント・ハンドラを識別します。 |
要素の属性
イベント・ハンドラXMLファイル内の要素には、属性が含まれています。表28-4に、要素内に一般的に定義される属性を示します。
表28-4 eventhandlers要素内のサブ要素の一般的な属性
要素の属性 | 説明 |
---|---|
名前 |
イベント・ハンドラの名前。 |
class |
イベント・ハンドラを実装するJavaクラスのフル・パッケージ名。 |
entity-type |
イベント・ハンドラの実行対象のエンティティのタイプを識別します。値 |
operation |
イベント・ハンドラの実行対象の操作のタイプを識別します。値 |
order |
イベント・ハンドラが実行される順序を識別します。順序の値は、エンティティ、操作およびステージの範囲内にあります。この範囲にある各イベント・ハンドラの順序の値は一意である必要があります。競合があると、この競合のあるイベント・ハンドラは無作為な順に実行されます。 サポートされる値は、 |
orch-target |
編成のタイプ(エンティティ編成、Toplink編成など)を識別します。次の値がサポートされています。
デフォルト値は |
sync |
この属性は、action-handlerおよびchange-failed要素のみで機能します。sync属性は、イベント・ハンドラが同期か非同期かを示します。サポートされている値は、 注意: validation-handler要素の場合、sync属性は |
stage |
この属性は、out-of-band-handler、action-handlerおよびfailed-handler要素のみで機能します。stage属性は、イベント・ハンドラが実行されるステージを示します。次の値がサポートされています。
|
tx |
この属性は、out-of-band-handler、action-handler、compensate-handlerおよびfinalization-handler要素のみで機能します。tx属性は、イベント・ハンドラが独自のトランザクションで実行されるかどうかを示します。サポートされている値は、TRUEまたはFALSEです。デフォルト値はFALSEです。 |
<eventhandlers>要素の名前空間要件
すべてのイベント・ハンドラ定義には、次の必須名前空間定義が必要です。
<eventhandlers xmlns="http://www.oracle.com/schema/oim/platform/kernel" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.oracle.com/schema/oim/platform/kernel orchestration-handlers.xsd">
表28-4に示す、すべてのカスタム・イベントの定義を含むメタデータXMLファイルを作成します。
例28-6 カスタム・イベント定義のサンプル・メタデータXMLファイル
<?xml version='1.0' encoding='utf-8'?> <eventhandlers xmlns="http://www.oracle.com/schema/oim/platform/kernel" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.oracle.com/schema/oim/platform/kernel orchestration-handlers.xsd"> <!-- Custom preprocess event handlers --> <action-handler class="oracle.oim.extensions.preprocess.SamplePreprocessExtension" entity-type="User" operation="CREATE" name="SetUserMiddleName" stage="preprocess" order="1000" sync="TRUE"/> <!-- Custom postprocess event handlers --> <action-handler class="oracle.oim.extensions.postprocess.SamplePostprocessExtension" entity-type="User" operation="CREATE" name="SamplePostprocessExtension" stage="postprocess" order="1000" sync="TRUE"/> <action-handler class="oracle.oim.extensions.postprocess.SamplePostprocessExtension" entity-type="User" operation="MODIFY" name="CustomResourceProv" stage="postprocess" order="1000" sync="TRUE"/> <!-- Custom validation event handlers --> <validation-handler class="oracle.oim.extensions.validation.SampleValidationExtension" entity-type="User" operation="CREATE" name="ValidateUserEmail" order="1000"/> </eventhandlers>
カスタム・イベント・ハンドラを含むプラグインを作成するには、適切なイベント・ハンドラ・クラスを開発する必要があります。プラグインおよびプラグイン・ポイントの詳細は、「プラグインの開発」を参照してください。
プラグインZIPを作成して登録するには:
イベント・ハンドラ・プラグイン・ポイントを含むプラグインXMLを定義します。
注意: プラグイン定義で使用されるプラグイン・ポイントがoracle.iam.platform.kernel.spi.EventHandlerに設定されていることを確認してください。 |
プラグインXMLファイルの例を次に示します。
<?xml version="1.0" encoding="UTF-8"?> <oimplugins> <plugins pluginpoint="oracle.iam.platform.kernel.spi.EventHandler"> <plugin pluginclass= "oracle.oim.extensions.preprocess.SamplePreprocessExtension" version="1.0" name="SamplePreprocessExtension"> </plugin> <plugin pluginclass= "oracle.oim.extensions.postprocess.SamplePostprocessExtension" version="1.0" name="SamplePostprocessExtension"> </plugin> <plugin pluginclass= "oracle.oim.extensions.validation.SampleValidationExtension" version="1.0" name="SampleValidationExtension"> </plugin> </plugins> </oimplugins>
カスタム・クラスを含むプラグインXMLおよびJARファイルをプラグインZIPファイルにパッケージ化します。
「カスタム・イベント定義XMLの定義」に示す情報を使用して定義されたイベント・ハンドラXMLを同じzipのMETA-INFというディレクトリにパッケージ化します。
プラグイン登録ユーティリティを使用してプラグインを登録します。追加情報については、「プラグインの登録」を参照してください。
デプロイおよび登録したカスタム・イベント・ハンドラのリストは、Oracle Enterprise Managerを使用して表示できます。イベント・ハンドラは、起動順に表示されます。このイベント・ハンドラのリストを使用すると、イベント・ハンドラの実行順序を指定できます。
カスタム・イベント・ハンドラの順序を指定するには、既存のイベント・ハンドラのリストと特定の操作におけるその順序を把握している必要があります。そのためには、次の手順を実行して、Enterprise ManagerからMBeanを起動する必要があります。
Enterprise Managerにログインします。
左側にあるナビゲーション・ペインで、「WebLogicドメイン」を展開して「OIM DOMAIN」を選択します。
ドメイン名を右クリックして、「システムMBeanブラウザ」を選択します。
「アプリケーション定義のMBean」でoracle.iamを展開します。
「OIM_SERVER_NAME」、「oim」、「IAMAppDesignMBean」、「ConfigQueryMBeanName」の順にナビゲートします。
「操作」タブをクリックします。
getEventHandlersメソッドをクリックします。
p1パラメータのエンティティ名およびp2パラメータの操作名を指定して、「起動」をクリックします。パラメータ値は大/小文字を区別しません。指定可能なパラメータ値は次のとおりです。
エンティティ名: 値は、User、RoleまたはRoleUserのいずれかです。
操作: 値は、CREATE、MODIFYまたはDELETEのいずれかです。
承認者は、リクエストを承認する前に属性値を更新できます。承認者が入力したデータの清浄化を保証するために、承認者がリクエストを更新したときに、Oracle Identity Managerは再度検証ハンドラを起動します。これは、リクエストが送信され、承認者が承認ワークフローでそのリクエストを変更した場合に、特定のエンティティおよび操作用に構成された検証ハンドラが1つのリクエスト・フローの中で複数回起動されることを意味します。
たとえば、自己登録リクエストが送信されると、USER CREATE用に構成された一連の検証ハンドラが実行されます。次に、承認者が組織またはその他のユーザー属性を移入するようにリクエストを変更すると、これらの検証ハンドラが再実行されます。
したがって、カスタム検証ハンドラは1つのリクエスト・フローで複数回起動されることから、このカスタム検証ハンドラはリエントラントな検証ロジックで開発される必要があります。
注意: Oracle Identity Managerに利用可能なパスワード・ポリシーがない場合は、カスタム・パスワード検証を追加できます。たとえば、パスワードが辞書に記載されている単語でないことを確認するパスワード検証を追加できます。カスタム・パスワード検証を追加するには、カスタム検証イベント・ハンドラを追加して、イベント・ハンドラの操作をCHANGEACCOUNTPASSWORDに設定します。次に、Oracle Identity Managerによってカスタム・イベント・ハンドラがトリガーされる順序を調整します。 |
次のサンプル・ユースケースについて考えてみます。
部門番号フィールドの値にランダムな番号を付与して、HR Employee Number UDFを生成する必要があります。ユーザー作成リクエストまたは自己登録リクエストが送信されると、カスタム・ロジックに基づいてHR Employee Number UDFが自動的に生成されます。承認者が承認時にリクエストを編集し、部門番号の値を変更すると、部門番号に割り当てられた新しい値を使用して、HR Employee Number UDFが再計算される必要があります。ただし、承認者が部門番号を変更しなかった場合は、リクエストの送信時に生成された以前の値が使用されます。
このため、部門番号とランダムな番号を付与することによってHR Employee Number UDFを生成するための新しい検証ハンドラを開発する必要があります。前処理ハンドラがリクエストのライフサイクルで起動されるのは1回だけであるため、このロジックを前処理ハンドラで作成することはできません。この検証ハンドラのロジックを次に示します。
package custom.handlers; import java.io.Serializable; import java.util.HashMap; import java.util.Random; import oracle.iam.identity.usermgmt.api.UserManagerConstants; import oracle.iam.identity.utils.Utils; import oracle.iam.platform.kernel.ValidationException; import oracle.iam.platform.kernel.ValidationFailedException; import oracle.iam.platform.kernel.spi.ValidationHandler; import oracle.iam.platform.kernel.vo.BulkOrchestration; import oracle.iam.platform.kernel.vo.Orchestration; public class EmployeeNumberGenerationHandler implements ValidationHandler { @Override public void initialize(HashMap<String, String> parameters) { } @Override public void validate(long processId, long eventId, Orchestration orchestration) throws ValidationException, ValidationFailedException { HashMap<String, Serializable> contextParams = orchestration.getParameters(); //1. Generate UDF Employee number during request submission as Department Number and a random number //2. If request is in approval stage, then control has come here since approver has modified the request //2a: Check if approver has modified Department Number. If yes, then re-generate if( !Utils.isRequestInApprovalStage()) //Utility method to find if request is in approval stage or not? If it returns true, it means that approver is attempting to update the request during approval { //Step 1: String dept = contextParams.get(UserManagerConstants.AttributeName.DEPARTMENT_NUMBER.getId()).toString(); String en = dept+"_"+random(); contextParams.put("SSN", en); } else { String dept = contextParams.get(UserManagerConstants.AttributeName.DEPARTMENT_NUMBER.getId()).toString(); //compare with department number with which request was submitted, if modified by approver; the regenerate SSN if( Utils.isAttributeModifiedByApprover(orchestration , UserManagerConstants.AttributeName.DEPARTMENT_NUMBER.getId()) ) // //Utility method to find if approver has edited the particular attribute or not , during approval? { String en = dept+"_"+random(); contextParams.put("SSN", en); } } } private String random() { Random random = new Random(); String randomStr = "" + random.nextLong(); randomStr = randomStr.replaceAll("-", ""); return randomStr; } @Override public void validate(long processId, long eventId, BulkOrchestration orchestration) throws ValidationException, ValidationFailedException { } }
イベント・ハンドラを開発して実装する前に、操作を分析することをお薦めします。操作用のプラグインがサポートされている場合は、イベント・ハンドラを開発するのではなく、プラグインを使用してカスタマイズします。たとえば、ユーザー名の生成は、使用可能なプラグインを使用して実装する必要があり、ユーザーの作成編成でイベント・ハンドラとして作成しようとしないでください。
イベント・ハンドラの開発における考慮事項については、「開発に関する考慮事項」を参照してください。
デプロイメント・マネージャでは、Oracle Identity Managerのデプロイメント間でのプラグインおよびプラグインに登録されたイベント・ハンドラの移行をサポートしています。たとえば、イベント・ハンドラをテスト環境で実装した後、デプロイメント・マネージャを使用して本番環境に移行することができます。図28-2に、デプロイメント・マネージャを使用したプラグインのエクスポートを示します。
表28-5に、一般的な問題、および操作の実行時にイベント・ハンドラがトリガーされなかった場合のトラブルシューティングに役立つ原因と解決策を示します。
表28-5 イベント・ハンドラのトラブルシューティング
問題 | 原因/解決策 |
---|---|
リコンシリエーションによってユーザーを作成すると、カスタム前処理イベント・ハンドラはトリガーされません。 |
開始ステージが後処理の場合、リコンシリエーションは後処理のみの編成を送信します。 |
リコンシリエーションによってユーザーを作成すると、カスタム後処理イベント・ハンドラはトリガーされますが、実行メソッドのロジックはトリガーされません。 |
リコンシリエーションはバルク編成を送信します。したがって、必ずbulkExecuteメソッドを実装してください。 |
編成操作の完了に非常に長い時間がかかります。 |
イベント・ハンドラごとにかかる時間を確認します。
|