2009年6月25日木曜日

ILM2007のクラスタリング

ILM2007の冗長化って少し癖がありますので今回はそのご紹介を。。

基本的な考え方はILMサポートチームのブログでひろとさんが書いているのでそちらを見てもらうとして、、
http://blogs.technet.com/jpilmblg/archive/2008/09/29/miis-ilm.aspx
http://blogs.technet.com/jpilmblg/archive/2008/10/22/miis-ilm-2.aspx


ここで紹介されている情報を含め基本はSQL ServerのクラスタリングとコールドスタンバイでのILMの冗長化という構成がメーカサポートの限界っぽいのですが、ここではあえてサポートを気にせずILM自体のクラスタリングをしてみます。
(ということでNonサポートです)

<参考URL>
http://blogs.msdn.com/alextch/archive/2005/12/17/clusteredmiis.aspx
http://social.technet.microsoft.com/Forums/en-US/identitylifecyclemanager/thread/bb508bbd-ca49-4cf8-8159-bde0570098bf



まず、セットアップ前の準備ですが通常のインストールと違い、以下のポイントに注意が必要です。
・サービスアカウントはドメインユーザを利用する
 ※ローカルAdministrator権限は不要
・MIISAdminsなどのグループアカウントはドメイン上のグローバルグループを利用する
 ※インストール前にあらかじめ作成が必要
 ※以下のメンバを所属させておく必要あり
  ILMサービスアカウント
  クラスタサービスアカウント:MSCS経由で実行する際に必要
  尚、クラスタサービスアカウントは通常ローカルAdministrator権限は不要ですが、
  ILMを使う場合はローカルAdministrator権限が必要・・・

次にILMのセットアップですが、以下の順番に実施します。
1.プライマリノードでセットアップ
  データベースはリモートサーバを指定
  グループはあらかじめ作成したドメイングループを使用する(DOM\GROUP形式で指定)
2.プライマリノードでILMを停止
3.セカンダリノードでセットアップ
  データベースはリモートサーバを指定
  データベースの認識をする際にすでにデータベースが存在している旨が表示されるのでOKする




















  グループはあらかじめ作成したドメイングループを使用する(DOM\GROUP形式で指定)
  キーファイル(*.bin)プライマリノードで作成したものをコピーする
4.セカンダリノードでILMを停止
5.プラまりノードでILMを起動
  通常通りの起動方法だと、こんなエラーが出てしまう。








イベントログはこんな感じ


















  というわけで、起動方法は
  miisactivate.exe キーファイル サービスアカウント パスワード
  となります。(クラスタエージェントもこのコマンドをサイレントモードで実行します)


ここまで来たら次はクラスタへの組み込みです。

注意点は下記の通りです。
・登録するクラスタグループに優先ノードの設定を入れておく
 ※スクリプトの作りの問題です(設定していないとスクリプトがエラーを出すので必ず設定が必要)
・sleep.exeを使うのでWindows Server 2003のリソースキットが必要
・クラスタエージェント(下記のスクリプト)およびILMのキーファイルはILMインストールフォルダ\bin以下に
 配置する(miisactivate.exeと同一フォルダである必要がある)
・CSV MAなどを使う場合、MADATAフォルダはローカルにあるので、CSVファイルは必ず両方のサーバに配置するような仕組みが別途必要です
 ※インストールオプションでMADATAだけ共有ディスクに移動できないか試したのですが、どうやら無理でした。。。


早速のセットアップですが、以下の流れです。
・リソースの種類は「汎用スクリプト」を使用















・登録してオンラインにした状態















クラスタエージェントスクリプトはこんな感じです。(参考URLに載っているものに一部バグがあったので修正しています)

各関数の解説
関数名種別機能/解説
Openクラスタのエントリポイントエージェントがロードされた時に呼ばれる。
Onlineクラスタのエントリポイントリソースをオンラインにする時に呼ばれる。
実行されたノードがGetPrefferedOwners関数で取得した優先ノードでなかった場合、CheckMIISServiceStatus関数で優先ノードでILMが実行されるか確認、もし実行中だった場合はStopRunningProfiles、StopMIISService関数を使って優先ノード上のILMを停止する。
その上でMiisactivateコマンドでILMの起動を試み、CheckMIISServiceStatus関数で起動状態を確認する。
LooksAliveクラスタのエントリポイントクラスタのエントリポイント。リソースのポーリングを行う。
CheckMIISServiceStatus関数を呼び出してILMのサービス死活を監視する。
IsAliveクラスタのエントリポイントクラスタのエントリポイント。リソースのポーリングを行う。
GetNumberOfMVRecords関数を呼び出してILMのサービス死活を監視する。
Offlineクラスタのエントリポイントクラスタのエントリポイント。リソースをオンラインにする時に呼ばれる。
StopRunningProfiles関数を呼び出して実行中のプロファイルを停止し、StopMIISService関数でILMのサービスを停止する
Terminateクラスタのエントリポイントクラスタのエントリポイント。特に何もしない。
Closeクラスタのエントリポイントクラスタのエントリポイント。特に何もしない。
GetPrefferedOwnersプライベート関数WMI経由でMSCS関連のレジストリより優先ノード情報を取得する
CheckMIISServiceStatusプライベート関数WMI経由でmiiserverサービスの実行状態を取得する
StopMIISServiceプライベート関数WMI経由でmiiserverサービスを停止する
StopRunningProfilesプライベート関数WMI経由でILMに接続し、実行中のプロファイルがあれば停止する
GetNumberOfMVRecordsプライベート関数WMI経由でILMに接続し、Metaverseのオブジェクト数を確認する(ポーリング目的)


実際のスクリプト


Option Explicit
'##################################################################################
'GLOBAL DECLARATIONS - MODIFY ACCORDING TO YOUR ENVIRONMENT
'CLUSTER GROUP WHICH CONTAINS MIIS SQL AND SCRIPT RESOURCES
Dim miisgroup
miisgroup = "MSSQL" ' ILM2007リソースを作成するクラスタグループ名
Dim miisServiceAccount
miisServiceAccount = "mscs\ilmservice"  ' ILMサービスアカウント
Dim miisServiceAccountPwd
miisServiceAccountPwd = "P@ssw0rd"  ' ILMサービスアカウントのパスワード
Dim miisEncryptKey
miisEncryptKey = "miiskey.bin"
Dim miisServiceStartupTime 'time in seconds for MIIS Service to come up
miisServiceStartupTime = 400

'###################################################################################
Dim activeNode
Dim prefferedOwners
Dim miisActivateCmd


Function Open()
  Dim WshNetwork

  Resource.LogInformation("Entering Open() for group" & Resource.Name)
  Set WshNetwork = CreateObject("WSCript.Network")
  activeNode = WshNetwork.ComputerName
  prefferedOwners = GetPrefferedOwners()
  miisActivateCmd = "miisactivate.exe " & miisEncryptKey & " " & miisServiceAccount & " " & miisServiceAccountPwd & " /q"
  Resource.LogInformation("MIISActivate Command - " & miisActivateCmd)
  Open = True

End Function

Function Online( )
  Dim Node
  Dim WshShell
  Dim oExec
  Dim oWait
  Dim i

  Resource.LogInformation("Entering Online()")

  'Ensurting that MIIS Service is not running on other preffered nodes of the cluster grp
  For Each Node In prefferedOwners
    If (Node <> activeNode) And (CheckMIISServiceStatus(Node) = True) Then
      StopRunningProfiles(Node)
      StopMIISService(Node)
    End If
  Next

  'Check if MIIS Service is already running on the active Node, if yes just exit
  If CheckMIISServiceStatus(activeNode) = True Then
    Online = True
    Exit Function
  End If

  'Run MIISActivate on the Active Cluster Noded
  Resource.LogInformation("About to execute:" & miisActivateCmd)
  Set WshShell = CreateObject("WScript.Shell")
  WshShell.CurrentDirectory = "C:\Program Files\Microsoft Identity Integration Server\Bin"
  Set oExec = WshShell.Exec(miisActivateCmd)
  ' ... Allow time for operation to complete...
  For i = 0 To miisServiceStartupTime
    Resource.LogInformation("Waiting for MIIS Service to come-up...")
    WshShell.Run "sleep 5" ,0,True
    If CheckMIISServiceStatus(activeNode) = True Then
      Resource.LogInformation("MIIS Service Started by MIISMonitor Script")
      Exit For
    End if
  Next

  If CheckMIISServiceStatus(activeNode) = False Then
    Resource.LogInformation("Failed to MIISActivate on Node:" & activeNode)
    Online = False
  Else
    Resource.LogInformation("MIISActivated on Node:" & activeNode)
    Online = True
  End If

End Function

Function LooksAlive()

  If CheckMIISServiceStatus(activeNode) = True Then
    Resource.LogInformation("MIIS Service LooksAlive")
    LooksAlive = True
  Else
    Resource.LogInformation("MIIS Service Failed")
    LooksAlive = False
  End If

End Function

Function IsAlive()

  'Perform various MIIS calls to ensure that it is alive
  If GetNumberOfMVRecords(activeNode) = True Then
    Resource.LogInformation("MIIS Service is Alive")
    IsAlive = True
  Else
    Resource.LogInformation("MIIS Service failed isAlive check")
    IsAlive = False
  End If

End Function

Function Offline()

  Resource.LogInformation("Entering Offline()")
  Resource.LogInformation("About to stop MIIS Service on node:" & activeNode)
  StopRunningProfiles(activeNode)
  StopMIISService(activeNode)

End Function

Function Terminate()

  Terminate = True

End Function

Function Close()

  Close = True

End Function

Function GetPrefferedOwners()
  Const HKEY_LOCAL_MACHINE = &H80000002
  Dim oReg
  Dim strKeyPath
  Dim arrSubKeys
  Dim strValueName
  Dim strValue
  Dim arrValues
  Dim subkey
  Dim strPrefferedNodes()
  Dim i
  i = 0

  Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
  activeNode & "\root\default:StdRegProv")

  strKeyPath = "Cluster\Groups\"
  oReg.EnumKey HKEY_LOCAL_MACHINE, strKeyPath, arrSubKeys

  For Each subkey In arrSubKeys
    strKeyPath = "Cluster\Groups\" & subkey
    strValueName = "Name"
    oReg.GetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strValue
    If strValue = miisgroup Then
      strValueName = "PreferredOwners"
      oReg.GetMultiStringValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,arrValues
      For Each strValue In arrValues
        strKeyPath = "Cluster\Nodes\" & strValue
        strValueName = "NodeName"
        oReg.GetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strValue
        ReDim Preserve strPrefferedNodes(i)
        strPrefferedNodes(i) = strValue
        i = i + 1
      Next
    End If
  Next

  GetPrefferedOwners = strPrefferedNodes

End Function

Function CheckMIISServiceStatus(Node)
On Error Resume Next

  Dim objWMIService
  Dim strWMIQuery
  Dim colServices

  Set objWMIService = GetObject("winmgmts:" _
  & "{impersonationLevel=impersonate}!\\" & Node & "\root\cimv2")
  strWMIQuery = "Select * from Win32_Service where Name = 'miiserver' and State = 'running'"
  Set colServices = objWMIService.ExecQuery(strWMIQuery)
  If Err.Number <> 0 Then
    Resource.LogInformation("Unable to complete WMI call in CheckMIISServiceStatus, error code " & Err.Number)
    CheckMIISService = False
    Exit Function
  End If

  If colServices.Count = 1 Then
    CheckMIISServiceStatus = True
  Else
    CheckMIISServiceStatus = False
  End If

End Function

Function StopMIISService(Node)
On Error Resume Next

  Dim objWMIService
  Dim colServiceList
  Dim objService

  Set objWMIService = GetObject("winmgmts:" _
  & "{impersonationLevel=impersonate}!\\" & Node & "\root\cimv2")
  Set colServiceList = objWMIService.ExecQuery _
  ("Select * from Win32_Service where Name='miiserver' and State = 'running'")

  For Each objService In colServiceList
    objService.StopService()
    If Err.Number <> 0 Then
      Resource.LogInformation("Unable to complete WMI call to stop MIIS during StopMIISService, error code " & Err.Number)
    End If
  Next

End Function

Function StopRunningProfiles(Node)
On Error Resume Next

  Dim objWMIService
  Dim Runs
  Dim Run
  Dim ManagementAgent

  'First stop all running jobs
  Set objWMIService = GetObject("winmgmts:" _
  & "{impersonationLevel=impersonate}!\\" & Node & "\root\MicrosoftIdentityIntegrationServer")
  Set Runs = objWMIService.ExecQuery("Select * From MIIS_RunHistory where RunStatus = 'in-progress'")

  For Each Run in Runs
    Resource.LogInformation("Stopping " & Run.MaName & " profile " & Run.RunProfile)
    Set ManagementAgent = objWMIService.Get("MIIS_ManagementAgent.Name='" & Run.MaName & "'")
    ManagementAgent.Stop()
    If Err.Number <> 0 Then
      Resource.LogInformation("Unable to complete WMI to get Run History call during StopRunningProfiles, error code " & Err.Number)
    End If
  Next

End Function

Function GetNumberOfMVRecords(Node)

  Dim Service
  Dim Server
  Dim numOfMvObjects

  Set Service = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & Node & "\root\MicrosoftIdentityIntegrationServer")
  Set Server = Service.Get("MIIS_Server.Name='MIIS_Server1'")
  numOfMvObjects = Server.NumMvObjects()

  If numOfMvObjects = "connection-failure" Or numOfMvObjects = "call-failure:0x80230621" Then
    Resource.LogInformation("Unable to complete WMI call in isAlive, error code " & Err.Number & ":" & numOfMvObjects )
    GetNumberOfMVRecords = False
  Else
    Resource.LogInformation("Count of Metaverse Objects = " & numOfMvObjects)
    GetNumberOfMVRecords = True
  End If


End Function

2009年6月24日水曜日

50ポスト目&Google検索結果

昨年秋から初めて早10ヶ月。
あまりペースは速くありませんがやっとのことで50ポスト目です。
トータルページビューもようやく9,000位まで来ました。


そして、ついに「IdM」でのGoogleの検索結果がトップになりました。
さすがにビッグキーワードだけあっていつまでトップを維持できるかわからないので、画面ショットを撮っておきました。

















見ていただいている皆様のおかげです。感謝感謝 <(_ _)>

2009年6月23日火曜日

ILM/FIMとRODC

ILM2007がWindowsServer2008環境に対応という話はILMチームのblogにあがっていましたが、RODCがいた場合ってどうなっちゃうのかな?というのが今回の実験です。

結論から言うと、RODCに対して更新クエリを投げた場合はreferral(紹介:「自分はダメなので他を紹介します!」)が返ってきてエラーになります。
一般的なLDAPクライアントはだいたいreferral対応の実装をするものなのですが、ILM(MIIS)は対応していないことが原因です。(ちなみにldp.exeはOK)

こんな感じで進めました。

■設定
ADMAのConfigure Directory Partitions画面でDomain controller connection settingsの中の
Only use preferred domain contorollersにチェックを入れます。














このPreferred Domain ControllersにはRODCが指定されています。

















■テスト
この状態でADへのExportを実行するとこのようにcd-errorが返ってきます。
















具体的なエラー内容を見ると、見事に「紹介」が返ってきています。















ちなみにPreferred Domain Contorollersの設定を変更して普通の2008DCにするとちゃんと更新が成功します。
















ということで、RODCが存在する環境下ではRODCを見に行かないようにPreferred Domain Controllers設定をきちんと行う必要があります。

2009年6月20日土曜日

ILM2007の無人インストール

MIIS UsersGroupのメーリングリストなどでトピックにあがっていたので紹介してみます。


■ILM2007
以下のTechnetフォーラムで紹介されています。
http://social.technet.microsoft.com/Forums/en-US/identitylifecyclemanager/thread/a5306af6-d051-401f-9f87-4becbd616b65
具体的には、下記の感じでmsiexec.exeの引数を付けて実行する形になります。
※ちなみにNONサポートだそうです。

start /wait msiexec /q /i "Microsoft Identity Integration Server.msi" SERVICEACCOUNT=ilmservice SERVICEPASSWORD=P@ssw0rd SERVICEDOMAIN=MSCS STORESERVER=MSSQLCLUS GROUPADMINS=ilmadmins GROUPOPERATORS=ilmoperators GROUPACCOUNTJOINERS=ilmjoiners GROUPBROWSE=ilmbrowse GROUPPASSWORDSET=ilmpasswordset PIDKEY=xxxxxxxxxxxxxxxx /log c:\temp\install.log

オプションはこんな感じです。

オプション意味
SERVCEACCOUNTサービス実行アカウントilmadmin
SERVICEPASSWORDサービス実行アカウントのパスワードP@ssw0rd
SERVICEDOMAINサービス実行アカウントの所属ドメインTESTDOM
STORESERVERSQLサーバ実行ホストMSSQL
MSSQLSERVERSERVICESQLインスタンス名MSSQLSERVER
GROUPADMINSMIIS管理者グループ名MIISAdmin
GROUPOPERATORSMIISオペレータグループ名MIISOperators
GROUPACCOUNTJOINERSMIISジョイナーグループ名MIISJoiners
GROUPBROWSEMIISブラウズグループ名MIISBrowse
GROUPPASSWORDSETMIISパスワードセットグループ名MIISPasswordSet
PIDKEYプロダクトキーxxxxxxxxxxxxxxxx(ハイフンなし)




インストーラのバイナリをエディタでのぞいてみると他にもこんなオプションがありそうです。(未検証)

カテゴリオプション
インストール先フォルダ関連TARGETDIR

INSTALLDIRC:\Program Files\Microsoft Identity Integration Server\

MADATAC:\Program Files\Microsoft Identity Integration Server\MaData\

UISHELLFOLDERC:\Program Files\Microsoft Identity Integration Server\UISell\

XMLSFOLDERC:\Program Files\Microsoft Identity Integration Server\UIShell\XMLs\

PackagedMAsFolderC:\Program Files\Microsoft Identity Integration Server\UIShell\XMLs\PackagedMAs\

IMAGESC:\Program Files\Microsoft Identity Integration Server\UIShell\Images\

HELPFILESC:\Program Files\Microsoft Identity Integration Server\UIShell\Helpfiles\

SOURCECODEC:\Program Files\Microsoft Identity Integration Server\SourceCode\

LOGGINGC:\Program Files\Microsoft Identity Integration Server\SourceCode\Logging\

GALSYNCC:\Program Files\Microsoft Identity Integration Server\SouceCode\GalSync\

EXTENSIONSCACHEC:\Program Files\Microsoft Identity Integration Server\ExtensionsCache\

EXTENSIONSC:\Program Files\Microsoft Identity Integration Server\Extensions\

DATAC:\Program Files\Microsoft Identity Integration Server\Data\

BINC:\Program Files\Microsoft Identity Integration Server\Bin\

ASSEMBLIESC:\Program Files\Microsoft Identity Integration Server\Bin\Assemblies\

MIISCommonC:\Program Files\Common Files\Microsoft Shared\Microsoft Identity Integration Server\
DB関連?(不明)DBFILNEMMSLOCATION

SETPERMISSIONDATA1

SETPERMISSIONDATA2

CLIENTUILEVEL

UILEVEL





FIMに関しては完全自動化は難しいみたいですが、半自動の手順(スクリプト)は存在するので、次回紹介したいと思います。

2009年6月16日火曜日

内部統制におけるアイデンティティ管理解説書(第2版)

一部手前味噌になりますが、、、
日本ネットワークセキュリティ協会(JNSA)より内部統制におけるアイデンティティ管理解説書(第2版)がリリースされました。私の名前(本名)もちょろっと載っています。

早いものでIdM関係のワーキンググループも4年目に突入です。
当初は内部統制というキーワードが大流行でしので、特に特権IDのライフサイクル管理(プロビジョニング)に重点をおいた話が多かったのですが、最近はもっぱらクラウド連携/対応がはやり言葉です。
どこのIdMベンダさんと話をしてもGoogleAppsとの連携とか、ClaimベースのID管理というお話ばっかりです。
確かにプロビジョニングに関しては殆どのユーザさんに入りきってしまった感があるので、今度は利便性や社内外を含めた形で拡大していくITインフラ全体をみたセキュリティという観点でより広い意味でのIdMの実用化が叫ばれているのかも知れません。

今期はJNSAのこのWGでもそのあたりの標準化の動向なんかも追いかけるようなので少しだけ楽しみです。

2009年6月11日木曜日

FIM Query Tool

FIM(ILM"2")のILM ServiceへはWebサービスでアクセスする、という話は以前書いたかと思いますが、具体的にはWS-TransferとWS-Enumerationを使っています。

ざっくり言うと以下のような使い方です。
・WS-Enumerationでオブジェクトの列挙をする(この際オブジェクトの絞り込みにXPath Filterを使用する)
・特定したオブジェクトに対してWS-Transferを使ってCreate/Read(Get)/Update(Put)/Deleteを行う

実際にデプロイ/障害対応をする際、FIMの中のオブジェクトの状態を確認するのにわざわざブラウザを立ち上げてILM Portalにアクセスして、それぞれのオブジェクトを確認、、という流れだと非常に手間がかかるのでこんなツールが公開されました。
(MIIS/ILM2007のMicrosoftIdentityIntegrationServerデータベースはまだ直接見て状態を把握できましたが、MSILMデータベースは見れたものではありません・・)

FIM Query Tool
http://fimquerytool.codeplex.com/
WS-Enumerationを使ってILM Serviceのオブジェクトの情報を取得/表示することができます。

Ensynchの方が作られたものです。

実際に使ってみました。

こんな感じで列挙/抽出対象のオブジェクトを選択します。













ユーザの抽出(AccountNameが'Administrator'というユーザを抽出)













ワークフロー定義の列挙















状態の把握がしにくかったExpected Rule Entryもこの通り。















なかなか便利です。