[MIISSP2以降] Utils.FindMVEntries() の引数に与える Attribute のデータ型が Non-Indexable かつ SQL2005 使用の場合 0x80040e14が発生する

みなさんこんにちは。いかがお過ごしでしょうか。ういこです。

我が家は子供がインフルエンザと溶連菌感染症が同時上映になってしまったため絶賛お休み中です。今週中は登園ストップがかかってしまいました。ピンチです。

私たちは親を頼れないため、家族で交互にお休みを頂きながらやり過ごしていかざるを得ません。こりゃもう家から仕事しようかなと思っております。漢らしく家族全員予防接種を受けていなかった我が家の今後に乞うご期待ください。(先生いわく、「もうしかたないね。熱でたら早めに来て」とのこと)

さて本日の記事は、MIIS SP2 以降 (ILM2007 含む) の変更点についてのご案内となります。

【今日のお題】

Utils.FindMVEntries() の引数に与える Attribute のデータ型が Non-Indexable の場合、 MIIS + SQL Server の組み合わせの違いによって実行結果に差異が生じる。

・MIIS RTM (Non-Service Pack) or SP1 環境 + SQL Server 2000

 ・・・ 正常動作

・MIIS SP2 あるいは ILM 2007 + SQL Server 2005

 ・・・ “データ型 ntext と nvarchar は equal to 演算子では互換性がありません。” というエラー  0x80040e14が発生する。(※)

(※) Indexable データ型では発生しません。

【問題について】

この動作差異は MIIS SP2 以降に実装された SQL Server 2005 対応の処理追加、分岐に伴う現象です。設計変更により発生する現象であり、障害ではありません。

ただし、現時点では大変心苦しい限りですが、この点について明確に記載したドキュメント等はございません。

ドキュメント作成については引き続き米国本社に働きかけを行ってまいりますが、取り急ぎ情報周知のために本ブログに記載させていただいております。

【再現方法】

AD MA を作成し、以下のコードを実装する。

    void IMASynchronization.MapAttributesForImport( string FlowRuleName, CSEntry csentry, MVEntry mventry)

  {

      MVEntry[] MV_List = null;

      string str = null;

      switch (FlowRuleName)

      {

        case "test":

          str  = "dummy-" + csentry["cn"].Value;

          // MVの属性"userPrincipalName"が"String(non-indexeable)"の場合、エラーが発生

          MV_List = Utils.FindMVEntries("userPrincipalName", str , 1);

          break;

        default:

          // TODO: remove the following statement and add your default script here

          throw new EntryPointNotImplementedException();

      }

    }

-- Metaverse 上に属性を作成する手順

まず、[Metaverse Designer] で以下の属性を作成します。

1. [Metaverse Designer] を押す

2. "Object types" で、person を選択し、右ペインの "Actions" から "Add Attibute" を選択

3. [New attribute] ボタンを押す

4. [New Attribute] ダイアログが表示されるので、以下のように設定。チェックボックスはチェックしなくても確認可能

Attribute name : userPrincipalName

Attribute type : String (non-indexable)

-- MA の作成手順

1. [Management Agent] を選択し、右ペインの [Create] を押す

2. "Create Management Agent" フェーズでは [Management Agent for:] は "Active Directory" を選択する

3. "Connect to Active Directory Forest" は同期対象の Active Directory を設定

4. "Select Object Types" は以下の "Object Types:" を選択

container

domainDNS

organizationalUnit

user

5. "Select Attributes" は以下の "Attributes:" を選択

cn

sAMAccountName

6. "Configure Connector Filter" と "Configure Join and Projection Rules" は既定

7. "Configure Attribute Flow" を以下のように設定

 a. [New] ボタンを押し、"Rules extension" ラジオ ボタンを選択し、"Flow rule name:" を上記ソース例の場合は、以下のように設定します。(※)

  test

 b. "Data Source Attribute" と "Metaverse Attribute"、"Type" の設定は下記。

   Data Source Attribute | Metaverse Attribute

  + ObjectType:user   | ObjectType:person

    cn          ※ userPrincipalName (Type は "Rules Extension")

 c. "Build Attribute Flow" グループは下記のような設定になります。

  Data source object type: user

  Data source attribute:

   <dn>

   cn (※選択状態)

   sAMAccountName

  Mapping Type : Advanced

  Flow Direction : Import

  Metaverse object type: user

  Metaverse attribute: userPrincipalName (※選択状態、Metaverse Designer で作成したもの)

  (※) void IMASynchronization.MapAttributesForImport() の switch (FlowRuleName) の case 文の名前を指定。上記例の場合は test になる。

8. "Configure Deprovisioning" は既定、"Deprovisioning Options" を "Make them disconnectors" に

9. "Configure Extensions" は "Rules Extension Name" をルール拡張した、上記の IMASynchronization.MapAttributesForImport() を実装した DLL を指定。

10.[OK] を押す。

-- 確認手順

1. エクステンションのプロジェクト (拡張子 *.csproj もしくは *.vbproj) を開く

2. void IMASynchronization.MapAttributesForImport() の switch (FlowRuleName) の case 文あたりにブレークを設定。このときブレーク ポイントは完全には有効化されないが問題ない

3. [デバッグ(D)] - [プロセスにアタッチ(P)...] を選択

4. "選択可能なプロセス(V)" で、miiserver.exe をクリックして選択し、[アタッチ(A)] ボタンを押す。これで準備完了

5. Identity Manager を起動し、該当の MA を選択し、右ペイン [Actions] で "Configure Run Profiles" を選択

 a. "Configure Run Profiles for "<MA の名前>" ダイアログが開くので [New Profile] ボタンを押す

 b. "Profile Name" は適当につけ [Next>] を押す

 c. "Configure Step" は Type を [Full Import and Full Sync] とかでよい

 d. "Management Agent Configration" はそのまま既定でよい。[Finish] を押す

6. 作成した Run Profile を実行する。[Actions] から、[Run] - 上記手順 5. で作成した Run Profile を指定、[OK] を押す

7. 実行すると、Visual Studio の設定したブレークポイントに停止するので、F10 で処理を実行すると、以下の部分で例外発生

 MV_List = Utils.FindMVEntries("userPrincipalName", dummy_val, 1);

 ⇒ 0x80040e14

【問題の詳細】

本現象の発生条件は下記 3 つを満たす場合となります。

 

-- 発生条件

  MIIS のデータストアに SQL Server (SQL) 2005 が使用されている

  MIIS SP2 が適用されている、あるいは ILM 環境である

  Attribute のタイプが non-indexable である

 

MIIS SP2 は、バックエンドのデータストアとして使用される SQL の

バージョン 2005 に正式に対応するロジック変更がなされております。

現象はこのロジック変更に伴う動作となりますため、結果として MIIS 2003 Service Pack 無し (RTM) および Service Pack 1 との動作が異なる現象として現れます。

 

製品の動作上サポート対象となる対処方法は以下の二つとなります。

 

-- 対処方法

  SQL Server 2000 を使用する。

  Attribute タイプを indexable で作成する。

 

※ ILM2007 は MIIS 2003 機能および SP2 相当ですので、実質的にはILM2007 は MIIS 2003 SP2 以降相当とお考えください。

-- 例外発生理由

バックエンド SQL Server のバージョンによって、MIIS SP2 以降およびILM ではデータ クエリの構築方法をそれぞれ適切な方法に振り分けます。SQL 2005 対応ロジックは、パフォーマンスを考慮したコード変更です。

 

そして、Attribute を Identity Manager の GUI 上から作成すると、以下のようにデータが作成されます。

non indexable の場合 … ntext

indexable の場合    … nvarchar

SQL Server 2000 がバックエンドの場合、FindMVEntries() に対する Select 文は、“Like” 演算子を指定した状態で発行され、SQL Server 2005 がバックエンドの場合は、"=" 演算子を指定した状態で発行されます。

 

 SQL Server 2000:

select distinct [mms_metaverse].object_id from [mms_metaverse] with (nolock) where (([GNPTest2] like N'Jordan'))

 SQL Server 2005:

select distinct [mms_metaverse].object_id from [mms_metaverse] with (nolock) where (([userPrincipalName] =N'T T'))

 

ntext 型のフィールドの場合、"=" 演算子に対応していないため、

結果として SQL の構文エラーが発生し、MIIS にはこの構文エラーが通知されます。

nvarchar 型のフィールドの場合は対応しているために問題は発生しません。

 

-- 実装変更理由

MIIS および MIIS SP1 ではクエリに LIKE 演算子を使用しておりました。

SQL 2005 対応設計を検討する段階で、SQL 製品チームの見解を参考としたところパフォーマンスを考慮した場合、LIKE 演算子の使用はあまり望ましくないため、"=" 演算子を使用する方向での実装を決断する経緯がございました。

さらに、データストアとして使用するデータ型を検討した際、nText データ型の場合、格納サイズから、正確な検索ができることの重要性は低いという判断となりました。

ユーザーが String(non-indexable) を作成する際、そのユーザーはこの属性内に大量のデータを格納したい場合ユーザーの使用するテキストが固定、たとえば、255 バイト以下となるような場合は、String(indexable) 属性を作成したうえで、[Indexed] チェック ボックスをチェックすることで、indexed であるかnot Indexed であるかを設定する対処を推奨いたします。

~ ういこう ~