2009年2月10日火曜日

退職そして復職(ILM2007で実装してみました)



実際にあった要件で、
①人事システムからはアクティブ(在籍中の)ユーザ一覧のみしか渡せない
②非アクティブユーザのActiveDirectory上のエントリを無効化したい
③一度退職した人も復帰するケースがあるので、その際はActiveDirectory上のエントリを再度有効化してほしい(結構偉い人の場合が多いので新規IDで、というわけにはいかないらしい・・・)
という話がありました。

話を聞くだけだと「ふ~ん、なるほど」という話なんですが、実装をしてみるとそれなりに面倒です。

よくWeb上などで出回っている情報だと、人事システム側にEmployeeStatusのような状態を示す属性があり、その属性を基にActiveDirectoryのuserAccountControlを変更して、、、というようになっています。

ただ、冒頭に挙げた例も含め実際の要件ってそんなにIdMに都合のよいインプット情報が渡ってくるわけではないので、今回の様に工夫が必要になります。

まず①ですが、要するに入社するとエントリが増え、異動するとエントリの属性が変更され、退職するとエントリが消えるということになります。(下表)


入力情報の例
元情報id,sn-j,givenName-j,sn-e,givenName-e,Department
0001,田中,一郎,Tanaka,Ichiro,営業部
入社時id,sn-j,givenName-j,sn-e,givenName-e,Department
0001,田中,一郎,Tanaka,Ichiro,営業部
0002,佐藤,次郎,Sato,Jiro,開発部
異動時id,sn-j,givenName-j,sn-e,givenName-e,Department
0001,田中,一郎,Tanaka,Ichiro,営業部
0002,佐藤,次郎,Sato,Jiro,営業部
退職時id,sn-j,givenName-j,sn-e,givenName-e,Department
0001,田中,一郎,Tanaka,Ichiro,営業部


次に②ですが、これは普通に考えるとActiveDirectory用のMA(以下MA_AD)のDeprovisioning Optionにrules extensionを書いて、その中でcsentryのuserAccountControlに無効値(ADS_UF_ACCOUNTDISABLE)をセットしてあげれば問題ないんですが、今回は最後③の復帰を考えてあげないといけません。

通常のProvisioningの動きだと、MetaVerse(以下MV)と対象のConnectorSpace(以下CS)のオブジェクト間にリンクがあるかどうかによってオブジェクト(csentry)の新規作成をするか、既存エントリの更新を行うかが決定されます。
ただし今回普通にdeprovisionを使ってしまうと、MVとMA_ADのCS内オブジェクト間のリンクが切断されてしまいますし(※)、そもそもdeprovisionはMVのオブジェクトが削除されないと走らない、という制限があります。

※deprovision関数の返却値はDeprovisionActionという型で、選択肢として、
 ・DeprovisionAction.Delete → CSからの削除(AD上にオブジェクトは残したいので今回使えない)
 ・DeprovisionAction.Disconnect → 再接続可能な状態でdisconnectする
 ・DeprovisionAction.ExplicitDisconnect → 再接続不可能な状態でdisconnectする
 しか存在しません。





















この状態で再度provisioningを実行すると、MVとCSのリンクがないので新規作成という動作が選択されるのですが同じDNのcsentryは消えずにCS上に残っているので「Already Exist」という形でエラーが出てしまいます。

















これを回避するために、
・人事システム用MA(MA_HR_PERSON)のCSとMVの間のリンク状況を見てAD_MAのCS内オブジェクトの属性(userAccountControl)をコントロールする
ということをしてみます。(当然他にも方法はあると思います)

具体的には、AD_MAのAttribute Flowのrules extensionを使います。
この中で、対象のmventryがMA_HR_PERSONのCSとリンクがあるかどうかを、
 mventry.ConnectedMAs("MA_HR_PERSON").Connectors.Count
に入っている値を見ることで判断します。
値が0ならリンクはありませんし、1ならリンクされているオブジェクトがある、と判断できます。

実際のコードはこんな感じです。

Public Sub MapAttributesForExport(ByVal FlowRuleName As String, ByVal mventry As MVEntry, ByVal csentry As CSEntry) Implements IMASynchronization.MapAttributesForExport

 Const ADS_UF_ACCOUNTDISABLE As Long = &H2 ' Disable user account
 Const ADS_UF_NORMAL_ACCOUNT As Long = &H200 ' Typical user account
 Dim currentValue As Long

 Select Case FlowRuleName
  Case "cd.user:userAccountControl<-mv.person:"
   If csentry("userAccountControl").IsPresent Then
    currentValue = csentry("userAccountControl").IntegerValue
   Else
    currentValue = ADS_UF_NORMAL_ACCOUNT
   End If
   If mventry.ConnectedMAs("MA_HR_PERSON").Connectors.Count = 0 Then
    'HR_MAに存在しない→無効化
    csentry("userAccountControl").IntegerValue = currentValue Or ADS_UF_ACCOUNTDISABLE
   Else
    'HRに存在する→有効化
     csentry("userAccountControl").IntegerValue = (currentValue Or ADS_UF_NORMAL_ACCOUNT) And (Not ADS_UF_ACCOUNTDISABLE)
   End If
  Case Else
   Throw New EntryPointNotImplementedException()
 End Select
End Sub

以下、実際に実行した結果です。

■通常同期







CSVファイルの中身





















MA_HR_PERSONのfull import & full syncの結果















MA_ADのexportの結果















ADのオブジェクト状態


■退職







CSVファイルの中身





















MA_HR_PERSONのfull import & full syncの結果














MA_ADのexportの結果















ADのオブジェクト状態


■復職







CSVファイルの中身





















MA_HR_PERSONのfull import & full syncの結果














MA_ADのexportの結果














ADのオブジェクト状態


0 件のコメント: