MOM スクリプト

第 2 部 - データをスクリプトに取得する

この記事は、Microsoft Operations Manager (MOM) でのスクリプト作成に関する 4 部構成のシリーズの第 2 部です。このシリーズの目的は、MOM と Windows Script Host のスクリプトを比較し、Windows Script Host のスクリプトにこれまで蓄積された膨大な知識や資料を有効利用できるようにすることです。

第 1 部 - 基本

MOM スクリプトの概念を Windows Script Host の概念と比較しながら説明し、2 つのスクリプトの共通オブジェクトおよび異なるオブジェクトを紹介します。ここでは、スクリプトからの出力データを MOM ワークフローに取得する方法を説明します。

第 2 部 - データをスクリプトに取得する

データを MOM スクリプトに取得する方法に重点を置いて説明します。パラメータの使い方や、スクリプトを起動する MOM オブジェクトから情報を取得する方法についても説明します。

第 3 部 - 作成およびデバッグ (Part 3 - Writing and Debugging)

MOM でのスクリプトの作成およびデバッグの方法について説明します。この記事では、各種のエディタやユーティリティを使用してこれらの機能を実行する方法を説明します。

第 4 部 - ベスト プラクティス (Part 4 - Best Practices)

ベスト プラクティスを紹介し、次のような一般的な質問に答えます。MOM スクリプトのイベントに対してどのタイミングでアラートを生成すればよいか。MOM スクリプトがどの程度複雑になったら分割するべきか。セキュリティをどうしたらよいか。

トピック
データを MOM スクリプトに取得するデータを MOM スクリプトに取得する
パラメータ (引数に相当する機能)パラメータ (引数に相当する機能)
スクリプト パラメータの値をルールから指定するスクリプト パラメータの値をルールから指定する
スクリプト パラメータの値をタスクから指定するスクリプト パラメータの値をタスクから指定する
呼び出し側の MOM オブジェクトにアクセスする呼び出し側の MOM オブジェクトにアクセスする
イベント パラメータイベント パラメータ
ユーザー アカウントを無効にする例ユーザー アカウントを無効にする例
まとめまとめ

データを MOM スクリプトに取得する

Windows Script Host (WSH) では、通常、WScript.Arguments でスクリプトに情報を渡します。MOM でこの機能に相当するのは ScriptContext.Parameters です。このメソッドにより、スクリプトを呼び出すルールに定義済みのパラメータに値を指定することができます。MOM スクリプトにデータを取得するその他のメソッドには、WSH に直接相当するものはありません (これらのメソッドについては後述します) が、スクリプトを起動するイベント オブジェクト、アラート オブジェクト、またはパフォーマンス データ オブジェクトから情報を取得する機能があります。メソッドごとにシナリオが異なり、多くのスクリプトではこれらのメソッドを組み合わせて使用するため、この 4 部シリーズの第 2 部では、これらのメソッドを個別に説明します。

パラメータ (引数に相当する機能)

WSH スクリプトでは、引数の指定に WScript.Arguments を使用しますが、MOM スクリプトでは、ScriptContext.Parameters を使用します。2 つのメソッドの機能はほぼ同様ですが、若干の相違があります。WScript.Arguments では引数が配列で返されますが、ScriptContext.Parameters では Get メソッドにパラメータ名を指定して個々のパラメータを取得する必要があります。MOM スクリプトでは、パラメータを使う前に [パラメータ] タブで定義しておく必要がありますが、WScript.Arguments はコマンド ラインで自由に使用できます。

ScriptContext.Parameters の簡単な例を次に示します。このコードでは 2 つのパラメータ (Parameter1 と Parameter2) を指定し、スクリプトで使用可能な単純な変数に割り当てます。

strParameter1 = ScriptContext.Parameters.Get("Parameter1")
strParameter2 = ScriptContext.Parameters.Get("Parameter2")

この例を、Parameters オブジェクトを生成するステップと、オブジェクトを指定して Get メソッドを呼び出すステップに分割することも可能です。次のスニペットは、前の例と同じ機能を果たします。

Set objParams = ScriptContext.Parameters
strParameter1 = objParams.Get("Parameter1")
strParameter2 = objParams.Get("Parameter2")

どちらのサンプル コードも、スクリプトの [パラメータ] タブでパラメータが定義済みであることを前提にしています (図 1 を参照)。スクリプトで使用できるパラメータは、このダイアログ ボックスで定義したパラメータのみです。

スクリプトのパラメータを定義するときに値を割り当てることができます。この値はスクリプトをルールに割り当てる際の既定値になります。スクリプトを起動するルールまたはタスクに値を設定することもできます。

少々ややこしいと思われるかもしれませんが、次の例でわかりやすくなります。次の WSH スクリプト「プロセスの終了」では、終了するプロセスの名前 notepad.exe がハードコーディングされています。

strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")

Set colProcessList = objWMIService.ExecQuery _
    ("Select * from Win32_Process Where Name = 'Notepad.exe'")

For Each objProcess in colProcessList
    objProcess.Terminate()
Next

このスクリプトでは、終了するプロセスごとにスクリプトを作成する必要があり、柔軟性に欠けます。プロセス名を引数として指定すれば、スクリプトははるかに再利用しやすくなります。MOM では、パラメータでプロセスを定義することにより、同じスクリプトを使って異なるプロセスを終了する複数のルールを定義できます。スクリプトを呼び出すタスクを作成し、スクリプトの実行時にユーザーがプロセス名を指定するようにすることも可能です。

この場合、スクリプトを次のように変更します。

strProcess = ScriptContext.Parameters.Get("ProcessName")

strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")

Set colProcessList = objWMIService.ExecQuery _
    ("Select * from Win32_Process Where Name = '" & strProcess & "'")

For Each objProcess in colProcessList
    objProcess.Terminate()
Next

ここでは、パラメータ ProcessName をスクリプトで定義し、終了するプロセス名を指定するこのパラメータの値を、スクリプト実行のルールまたはタスクに定義する必要があります。終了する既定のプロセスを定義してもあまり意味がないので、このパラメータに既定値を設定する必要はありません。

例を少し発展させて、イベントを生成するかどうかを指定するパラメータをこのスクリプトに追加してみましょう。プロセスを終了する場合、そのプロセスの存在の有無や終了したインスタンス数を示すイベントを生成することができます。イベントを生成するかどうかの選択は管理者の判断にお任せします。一般的には、このような場合にはイベントが必要なので、例では既定値を True に設定します。

図 1 に、[スクリプトのプロパティ] ダイアログ ボックスに定義した 2 つのパラメータを示します。

プロセスの終了

図 1: スクリプト "Terminate a Process" のパラメータ
拡大表示する

これらの 2 つのパラメータを使用したスクリプトを次に示します。ここでは CBool 関数を使って GenerateEvent パラメータをブール値 (True または False) に変換しています。VBScript の変数と同様、MOM イベント パラメータのデータ型はバリアント型であり、この場合の値 True は文字列として認識されます。必要なのは ブール値の True または False なので、このような変換を行う必要があります。

MOM イベントを作成するため、第 1 部で説明した CreateEvent サブルーチンと、このサブルーチンに関連する定数を使用します。CreateEvent サブルーチンを呼び出すのは、GenerateEvent スクリプト パラメータが True の場合のみです。

Const EVENT_TYPE_SUCCESS = 0
Const EVENT_TYPE_ERROR   = 1
Const EVENT_TYPE_WARNING = 2
Const EVENT_TYPE_INFORMATION = 4
Const EVENT_TYPE_AUDITSUCCESS = 8
Const EVENT_TYPE_AUDITFAILURE = 16

strProcessName = ScriptContext.Parameters.Get("ProcessName")
bolGenerateEvent = CBool(ScriptContext.Parameters.Get("GenerateEvent"))

strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")

Set colProcessList = objWMIService.ExecQuery _
    ("Select * from Win32_Process Where Name = '" & strProcessName & "'")

For Each objProcess in colProcessList
        objProcess.Terminate()
Next

If bolGenerateEvent = True Then
        CreateEvent 100,EVENT_TYPE_INFORMATION, "Process Monitoring", _
"Terminated " & colProcessList.Count & " instances of process " _
 & strProcessName & "."
End If

Sub CreateEvent(intEventNumber,intEventType,strEventSource,strEventMessage)
        Set objEvent = ScriptContext.CreateEvent()
        objEvent.EventNumber = intEventNumber
        objEvent.EventType = intEventType 
        objEvent.EventSource = strEventSource
        objEvent.Message = strEventMessage
        ScriptContext.Submit objEvent
End Sub

これでスクリプトは完了しました。次にこのスクリプトを起動します。このスクリプトはルールまたはタスクから呼び出すときに便利です。では、内容を詳しく説明します。

スクリプト パラメータの値をルールから指定する

スクリプト "Terminate a Process" をイベント ルールから呼び出す場合、スクリプト パラメータの最終的な値をルール定義に指定できます。これを例示するため、起動後すぐに終了するプロセスがあるとします。例では、このたちの悪いプロセスを root.exe と名付けることにします。

スクリプトをルールから起動するには、root.exe プロセスが起動したかどうかを検出する別のルールが必要です。話が少しそれますが、MOM でプロセスの起動の有無を確認する最も簡単な方法は、WMI イベント プロバイダを使うことです。この概念をご存知の方は、話の内容が既におわかりでしょう。この概念になじみがなくても、とにかく図 2 のプロバイダに示されている情報をコピーして、そのプロバイダをスクリプト "Terminate a Process" を起動するイベント ルールに使うことができます。このプロバイダは、この記事に関連するサンプル AKM (英語) にも含まれています。

プロセスの起動

図 2: プロセスの起動を検出する WMI イベント プロバイダ

このプロバイダを使用し、スクリプト "Terminate a Process" を起動するイベントの詳細を表 1 に示します (この表は AKM (英語) にもあります)。このイベントには条件は不要です。WMI イベント プロバイダでは検索対象のプロセスを既に指定しているため、root.exe が起動したことを検知するたびにスクリプトを起動します。

表 1. 指定したプロセスを検出して終了するサンプル イベント ルールの詳細

タブプロパティ

全般

名前

Process root.exe was detected and will be terminated.

データ プロバイダ

プロバイダ名

Process root.exe started (WMI Event Provider)

アラート

アラートを生成する

オン

アラート

アラートの重要度

警告

応答

スクリプトの起動

Terminate a process

ルール定義の [応答] タブで、起動するスクリプトを選択すると、スクリプトに定義された各パラメータの既定値 (既定値が定義されている場合) が [スクリプトの起動] ダイアログ ボックスの各パラメータに使用されます。既定値を変更する (または、既定値がない場合に値を指定する) には、対象のパラメータをクリックし、[パラメータの編集] ボタンをクリックします。このテスト イベントのスクリプト パラメータを図 3 に示します。GenerateEvent には既定値をそのまま使用し、ProcessName には root.exe を指定しました。

ルールのパラメータ値

図 3: ルールにパラメータ値を指定する
拡大表示する

これをテストするには、MOM エージェントが動作するコンピュータにルールを配置します。このコンピュータ上で root.exe という名前のプロセス (notepad.exe などの小さいアプリケーションを root.exe としてコピーし、実行するだけです) を起動すると、このプロセスは数秒後に自動的に閉じ、MOM アラートが生成されます。

スクリプト パラメータの値をタスクから指定する

タスクでは、スクリプト パラメータの値を指定するタイミングが 2 回あります。最初のタイミングは、タスクの作成時です。スクリプト内のパラメータ定義と同様に、タスクの既定値もこのタイミングで定義します。値を変更できるもう 1 つのタイミングは、タスクの実行時です。

第 1 部のスクリプト "プロセス所有権の判別" の例を発展させて、スクリプト "Terminate a Process" をタスクで使用します。エージェント コンピュータを分析するとき、"プロセス所有権の判別" をタスクから実行し、不正なプロセスの実行を検出することができます。この情報に応答して、問題のあるプロセスを終了する別のタスクを起動することもできます。これは、イベント ルールからスクリプトを呼び出す前述の例と同様の機能ですが、こちらの方が用途は特殊です。

この方法でスクリプト "Terminate a Process" をテストするには、このスクリプトを起動するタスクを作成します (サンプル AKM (英語) にもあります)。エージェント コンピュータに対してタスクを起動すると、タスクの起動ウィザードが開き、[次へ] を数回クリックすると、スクリプトのパラメータ一覧が表示されます。ここで、終了するプロセスの名前を指定できます (図 4 を参照)。

タスクからの実行

図 4: タスクからのスクリプト実行のパラメータ値を定義する

このスクリプトの実行は、ルールからのスクリプト実行よりさらに簡単です。エージェント コンピュータ上でプロセス root.exe (Notepad.exe をコピーして、root.exe という名前で保存するだけでかまいません) を起動し、そのコンピュータに対してタスクを起動します。プロセスは数秒後に終了し、MOM アラートが生成されます。

呼び出し側の MOM オブジェクトにアクセスする

ルールまたはタスクの作成時にスクリプトに情報を指定することもできますが、これはスクリプト パラメータが使用できる状態にあるときに限られます。不測の事態が起こることもあり得るため、場合によってはスクリプトを起動したオブジェクトから情報を取得する必要があります。幸運なことに、ScriptContext には、これらのオブジェクトを操作するための Alert、Event、PerfData という 3 つのプロパティがあります。注意すべきことは、いずれの時点においてもこれらのオブジェクトのうちの 1 つのみが有効であり、実際には、すべてのオブジェクトが無効であることもあります。

無効なオブジェクトに対してスクリプトを実行するとどうなるのでしょうか。たとえば、イベントから起動するスクリプトを作成し、適切に Event オブジェクトを使ったとします。その後、アラート ルールに応答してスクリプトを起動した方が適切な状況が発生したとします。このスクリプトをアラート ルールから呼び出しても、対象の Event オブジェクトが存在しないため、スクリプトは失敗します。

スクリプトを起動した MOM オブジェクトの種類を識別する機能として、ScriptContext オブジェクトには IsAlert、IsEvent、IsPerfData の各メソッドがあります。名前からわかるように、これらのメソッドは、スクリプトを起動したオブジェクトの種類に応じて True または False を返します。図 5 に、この概念を示します。

呼び出し側オブジェクトのプロパティ

図 5: 呼び出し側オブジェクトのプロパティ

そこで、私たちの例のように、特定のオブジェクト型のみに応答してスクリプトが実行されるようにすれば、適切なメソッドを使用して、コードを実行するか、スクリプトの起動が不正であることを通知するエラー イベントを生成するかを選択することができます。もう 1 つの方法として、イベントまたはアラートに応答してスクリプトを正常に実行することができます。この場合、次の擬似コードに示すように、IsEvent メソッドと IsAlert メソッドを使って、どちらのコード ブロックを実行するかを判断します。

If ScriptContext.IsEvent = True Then
    Set objEvent = ScriptContext.Event
    <Code using objEvent>
Else If ScriptContext.IsAlert = True Then
    Set objAlert = ScriptContext.Alert
    <Code using objAlert>
Else
    <Create an error event saying that the script isn’t allowed to be
     executed by a performance rule or a task.> 
End If

いつものように、例によって、これらの概念を示します。ここでは、第 1 部で使ったパフォーマンス データの例を利用します。このスクリプトでは、指定したファイルのサイズを使用してパフォーマンス データを作成します。ここでは、パフォーマンス カウンタにしきい値を設定し、一定のサイズを超えたらファイルをアーカイブに移動するとします。

この機能は、第 1 部の表 5 に定義されたしきい値ルールを使用して実装します。このルールでは、ファイル サイズが 1 MB に達すると、アラートが生成されます。このルールを変更して、アラートを発行するのではなく、スクリプトを起動するようにします。また、少し内容を発展させて、静的な名前をハードコーディングするのではなく、このルールをすべてのログ ファイルに適用するようにします。新しいルールの詳細を表 2 に示します。太字は変更箇所です。

表 2. スクリプト "File Move" を起動するパフォーマンス ルールの詳細

タブプロパティ

全般

名前

The size of an application log has exceeded its threshold value. File will be moved to archive.

データ プロバイダ

プロバイダ名

Script-generated Data

条件

インスタンス

次のワイルドカードと一致する 'c:\logs\*'

条件

オブジェクト

次の値と等しい ‘File’

条件

カウンタ

次の値と等しい ‘File Size’

しきい値

サンプリングされた値

オン

しきい値

次の値より大きい

1000000

アラート

アラートを生成する

オフ

応答

応答

TechNet: Scripting MOM: Move File
(任意のスクリプト名を使ってかまいません。)

応答

種類

スクリプト

このルールは、パスが "c:\logs" で始まる (一般的な言い方をすれば、c:\logs ディレクトリに保存されている) すべてのファイルに適用されます。この記事の目的は、ルールの処理ではなく、スクリプトの学習です。スクリプト センターの「単一ファイルの移動」スクリプトから始めます。

Set objFSO = CreateObject("Scripting.FileSystemObject")
objFSO.MoveFile "C:\FSO\ScriptLog.log" , "D:\Archive"

移動するファイルのパスとファイル名および移動先がわかっていれば、スクリプトの内容は簡単です。この例では、スクリプトが実際に起動するまでファイル名がわかりません。先ほど作成したルールを利用して新しい移動スクリプト (後述) を作成すれば、パフォーマンス カウンタに応答してスクリプトを起動することができます。パフォーマンス カウンタの取得には ScriptContext.PerfData プロパティを使います。この場合、ファイル パスは PerfData オブジェクトの InstanceName プロパティに存在するので、その値を MoveFile メソッドに渡します。また、スクリプト パラメータの使い方がわかっているので、スクリプト パラメータを使ってアーカイブ パスを指定します。新しいスクリプトは次のようになります。

Set objPerfData = ScriptContext.PerfData
strFilePath = objPerfData.InstanceName
strArchivePath = ScriptContext.Parameters.Get("ArchivePath")

Set objFSO = CreateObject("Scripting.FileSystemObject")
objFSO.MoveFile strFilePath , strArchivePath

スクリプトを完成させるため、簡単なエラー チェックを組み込みましょう。このスクリプトをイベント ルール、アラート ルール、またはタスクから呼び出すと、図 6 のようなエラーが発生します。

エラー イベント

図 6 不正なオブジェクトを使用した場合のエラー イベント
拡大表示する

このエラーは、スクリプトが ScriptContext.PerfData を参照しようとして使用不可能であったときに発生します。ただし、これではエラーの内容がよくわかりません。スクリプトがパフォーマンス データに応答して起動したかどうかをチェックし、呼び出しが不正な場合は適切なエラー メッセージが返されるようにした方がよいでしょう。そのためには IsPerfData メソッドを使用して、エラーを通知するイベントを生成します。イベントを生成するには、第 1 部の CreateEvent サブルーチンと定数をコピーして貼り付けます。

Const EVENT_TYPE_SUCCESS = 0
Const EVENT_TYPE_ERROR   = 1
Const EVENT_TYPE_WARNING = 2
Const EVENT_TYPE_INFORMATION = 4
Const EVENT_TYPE_AUDITSUCCESS = 8
Const EVENT_TYPE_AUDITFAILURE = 16

If ScriptContext.IsPerfData = False Then
        CreateEvent 200, EVENT_TYPE_ERROR, "Scripting MOM", 
"The script " & _ ScriptContext.Name & 
" may only be executed in response to a performance rule. "
Else
        Set objPerfData = ScriptContext.PerfData
        strFilePath = objPerfData.InstanceName
        strArchivePath = ScriptContext.Parameters.Get("ArchivePath")

        Set objFSO = CreateObject("Scripting.FileSystemObject")
        objFSO.MoveFile strFilePath , strArchivePath
End If

Sub CreateEvent(intEventNumber,intEventType,strEventSource,strEventMessage)
        Set objEvent = ScriptContext.CreateEvent()
        objEvent.EventNumber = intEventNumber
        objEvent.EventType = intEventType 
        objEvent.EventSource = strEventSource
        objEvent.Message = strEventMessage
        ScriptContext.Submit objEvent
End Sub

スクリプトをタスクから実行するか、イベント ルールまたはアラート ルールに応答して実行すると、図 7 のような詳細なエラー メッセージを取得できます。

カスタム エラー イベント

図 7: 不正なオブジェクトを使用した場合のカスタム エラー イベント
拡大表示する

パフォーマンス ルールに応答してスクリプトを実行すると (サンプル AKM (英語) に例があります)、指定のしきい値を超えたファイルがアーカイブに移動します。

イベント パラメータ

MOM でスクリプトを実行する最も一般的な方法は、おそらくイベント ルールに応答して起動する方法でしょう。ScriptContext.Event でスクリプトからイベント情報を参照できることは既に説明しましたが、多くの場合、より詳細な情報がイベント メッセージに存在します。Mid、Left、Right、InStr などの各種関数を使ってデータの一部を取り出すことができますが、必ずしもこのような操作を行う必要はありません。

多くの場合、イベントにはイベント パラメータがあります。イベント パラメータを、この記事の最初のセクションで説明したスクリプト パラメータと混同しないでください。スクリプト パラメータとその値はスクリプトの起動ルールを作成する管理者が定義しますが、イベント パラメータは MOM で生成された一部のイベントに付随する別のデータです。

Windows の一般的なイベントは、静的テキストと、発生する各イベントに固有の情報を示す複数のパラメータで構成されます。たとえば、セキュリティ イベント ログのイベントには、通常、イベントの作成を開始したユーザー アカウントのユーザー名やドメイン名などのパラメータがあります。MOM スクリプトで使用できるのは、これらのイベント パラメータです。通常、イベント メッセージにはパラメータ値が含まれますが、多くの場合、説明テキストと連結されています。それなら、個々のパラメータを参照した方がはるかに簡単です。

ユーザー アカウントを無効にする例

かつて、ドメイン コントローラのセキュリティ イベント ログを削除しようとするユーザーを監視するため、MOM モニタが欲しいという依頼を受けたことがあります。このような行為が行われたら、悪質なユーザーのユーザー アカウントを無効にする必要があります。それは、管理者アカウントが危殆化した可能性があり、犯人が痕跡を消すためにセキュリティ ログを削除するかもしれないからです。このケースはイベント パラメータの例を示すのに絶好なので、この機会に Active Directory Services Interface (ADSI) を使った操作を少しご紹介します。

ここでは、Active Directory を操作するスクリプトに関連するいくつかの概念をまとめて説明します。これらの概念になじみがない場合は、ADSI の詳細を説明している「Microsoft Windows 2000 Scripting Guide」(英語) を参照してください。ユーザー アカウント データの取得にはイベント パラメータを使うのが一般的ですが、ここでのイベント パラメータの例には、ADSI を使うと便利です。これから説明するのと同様の課題に直面する頻度はきわめて高いでしょう。ADSI に関心がなくても、次の例はイベント パラメータの使い方を示す例として参考になります。

この例では、ドメイン コントローラのアクション アカウントに Active Directory のユーザー アカウントを無効にする権限を与える必要があります。アクション アカウントの概念については、「MOM Security Guide」(英語) を参照してください。

では、ソリューションを続けましょう。セキュリティ イベント 517 を監視することにより、セキュリティ イベント ログを削除しているユーザーを検出できます。このイベントの内容を確認するため、コレクション ルールを作成し (サンプル AKM (英語) に例があります)、続けてログを削除します。その結果、イベントは図 8 のようになります。

サンプル セキュリティ イベント

図 8: サンプル セキュリティ イベント
拡大表示する

ログを削除したユーザーの名前がイベントの説明の "クライアント ユーザー名:" というテキストの横に示され、そのすぐ下にドメイン名が示されているのがわかります。InStr 関数と Mid 関数を使って Event オブジェクトの Message プロパティから値を取り出すコマンドを作成することもできますが、より簡単な方法があります。同じイベントの [イベント] タブをクリックすると、図 9 のような画面が表示されます。

サンプル イベント パラメータ

図 9: サンプル イベント パラメータ
拡大表示する

これらはイベント パラメータです。パラメータ 4 とパラメータ 5 に目的のユーザー名とドメインが取得されているのがわかります。メッセージから値を切り出すより、ここから値を取得する方がはるかに簡単です。

では、イベントにはどのようなパラメータがあり、どの値がどの位置にあるかを知るにはどうしたらよいでしょうか。イベントを生成したアプリケーションのドキュメントを参照することもできますし、前述の例のように目的のイベントのイベント コレクション ルールを作成することもできます。それにより、収集したイベントから必要な情報を検査できます。すべてのパラメータを収集するオプションがルールで選択されているか、またはイベントだけが収集され、パラメータが全く収集されないようになっているかを確認してください。

このようなパラメータはセキュリティ監査イベントで一般的です。ADSI で Active Directory オブジェクトを取得する場合の課題は、OU 全体とドメイン パスを含むオブジェクトの識別名が必要だということです。通常、監査イベントで取得できるのはアカウント名とドメイン名のみです。そのため、次のスクリプトでは 2 つの手順に分け、まず、無効にする必要があるユーザー オブジェクトを検出し、次に、そのユーザーを無効にします。

最初のタスクは、スクリプト「Active Directory 内のユーザー アカウントの検索」で提供されている機能で実現します。このスクリプトでは、ユーザー アカウント名を指定すると、そのユーザーがディレクトリに存在するかどうかがレポートされます。

strUserName = "kenmyer"
dtStart = TimeValue(Now())
Set objConnection = CreateObject("ADODB.Connection")
objConnection.Open "Provider=ADsDSOObject;"
 
Set objCommand = CreateObject("ADODB.Command")
objCommand.ActiveConnection = objConnection
 
objCommand.CommandText = _
    "<LDAP://dc=fabrikam,dc=com>;(&(objectCategory=User)" & _
         "(samAccountName=" & strUserName & "));samAccountName;subtree"
  
Set objRecordSet = objCommand.Execute
 
If objRecordset.RecordCount = 0 Then
    WScript.Echo "sAMAccountName: " & strUserName & " does not exist."
Else
    WScript.Echo strUserName & " exists."
End If
 
objConnection.Close

このスクリプトを変更し、イベント パラメータを使用して目的のユーザー アカウントとドメイン名を取得するようにする必要があります。この場合は、図 9 からわかるように、イベントのパラメータ 4 とパラメータ 5 です。また、ユーザーの存在の有無をレポートするのではなく (この処理には WScript.Echo が必要ですが、MOM でスクリプトを実行する場合はこのコマンドを削除しなければなりません)、2 つ目の手順で使用する変数にユーザーの識別名を取得する必要があります。

ユーザー アカウントを指定したら、検索条件を指定する行を変更します。ドメイン名を変更すると共に、クエリが samAccountName ではなく distinguishedName を返すように指定する必要があります。最後に、クエリの結果セットから distinguishedName を取得し、変数に割り当てるコードを 1 行追加する必要があります。

変更後のスクリプトは次のようになります。

Set objEvent = ScriptContext.Event
strUserName = objEvent.EventParameter(4)
dtStart = TimeValue(Now())
Set objConnection = CreateObject("ADODB.Connection")
objConnection.Open "Provider=ADsDSOObject;"
 
Set objCommand = CreateObject("ADODB.Command")
objCommand.ActiveConnection = objConnection
 
objCommand.CommandText = _
    "<LDAP://" & objEvent.EventParameter(5) & ">;(&(objectCategory=User)" & _
         "(samAccountName=" & strUserName & "));distinguishedName;subtree"
  
Set objRecordSet = objCommand.Execute
 
strDistinguishedName = objRecordset("distinguishedName")
 
objConnection.Close

ユーザーの識別名を取得したので、次に示すスクリプト「ユーザー アカウントの無効化」で該当アカウントを無効にすることができます。

Const ADS_UF_ACCOUNTDISABLE = 2
 
Set objUser = GetObject _
    ("LDAP://cn=myerken,ou=management,dc=fabrikam,dc=com")
intUAC = objUser.Get("userAccountControl")
 
objUser.Put "userAccountControl", intUAC OR ADS_UF_ACCOUNTDISABLE
objUser.SetInfo

この変更は、ユーザーの検索よりもはるかに簡単です。変更後のスクリプトは、ハードコーディングされた識別名を前述のスクリプトで取得した変数に置き換えるだけです。変更後のスクリプトは次のようになります。

Const ADS_UF_ACCOUNTDISABLE = 2
 
Set objUser = GetObject _
    ("LDAP:// " & strDistinguishedName)
intUAC = objUser.Get("userAccountControl")
 
objUser.Put "userAccountControl", intUAC OR ADS_UF_ACCOUNTDISABLE
objUser.SetInfo

最後のスクリプトは、変更後の "Search for a User Account in Active Directory" スクリプトの直後に、変更後の "Disable a User Account" スクリプトを追加したものです。

Set objEvent = ScriptContext.Event
strUserName = objEvent.EventParameter(4)
dtStart = TimeValue(Now())
Set objConnection = CreateObject("ADODB.Connection")
objConnection.Open "Provider=ADsDSOObject;"
 
Set objCommand = CreateObject("ADODB.Command")
objCommand.ActiveConnection = objConnection
 
objCommand.CommandText = _
    "<LDAP://" & objEvent.EventParameter(5) & ">;(&(objectCategory=User)" & _
         "(samAccountName=" & strUserName & "));distinguishedName;subtree"
  
Set objRecordSet = objCommand.Execute
 
strDistinguishedName = objRecordset.Fields ("distinguishedName")
 
objConnection.Close

Const ADS_UF_ACCOUNTDISABLE = 2
 
Set objUser = GetObject _
    ("LDAP:// " & strDistinguishedName)
intUAC = objUser.Get("userAccountControl")
 
objUser.Put "userAccountControl", intUAC OR ADS_UF_ACCOUNTDISABLE
objUser.SetInfo

重要 : このスクリプトのテスト方法を説明する前に、ネットワークからロックアウトされている可能性があるので、その点に注意してください。無効にするテスト ユーザー アカウントを作成するか、Active Directory ユーザーとコンピュータ MMC を開いたままにして、すぐに再有効化できるようにしておいてください。

このスクリプトをテストするには、表 3 と同様のルールを作成し、1 つまたは複数のドメイン コントローラに配置します。セキュリティ イベント ログを削除し、ユーザー アカウントが無効になったことを確認してください。

表 3. セキュリティ イベント ログの削除に応答してユーザー アカウントを検出し、無効にするイベント ルールの詳細

タブプロパティ

全般

名前

Security Event Log was cleared. User account will be disabled.

データ プロバイダ

プロバイダ名

セキュリティ

条件

ソース

セキュリティ

条件

イベント ID

517

アラート

アラートを生成する

オン

アラート

アラートの重要度

セキュリティの問題

応答

応答

TechNet: Scripting MOM: Disable a User Account

応答

種類

スクリプト

このソリューションの仕上げとして、アカウントが無効になった後にユーザーをログオフすると有効です。不正ユーザーがログオン済みの場合はユーザー アカウントを無効にしてもあまり意味がなく、自らログオフしないかぎり、不正ユーザーは自由に悪事を続けられることになります。しかし、主な概念は既に十分に説明してきたので、ログオフについてはここでは取り上げません。ログオフを含めると、スクリプトのテストに伴うリスクも増します。興味があれば、「Microsoft Windows 2000 Scripting Guide」(英語) で、コンピュータをシャットダウンするスクリプトや、現在のユーザーをログオフするだけのスクリプトを参照してください。そのスクリプトを先ほど作成したスクリプトの最後に追加するだけです。

最後にもう 1 つ、お断りしておきます。抜け目ない不正ユーザーなら、MOM サービスを無効にしてからセキュリティ イベント ログの削除などの操作を行うでしょう。この場合には、前述のスクリプトは起動しません。このスクリプトは、堅牢なセキュリティ設定の例を示すことを目的としたものではなく、全体的なセキュリティ計画に組み込む多数のセキュリティ強化および監査方法の一例を示すためのものです。しかし、MOM サービスが無効になっていれば、MOM でハートビート エラーに対するアラートが生成され、調査が開始される場合があります。

まとめ

動的にデータを取得することで、MOM スクリプトの用途を広げ、応答性を高める方法を説明しました。呼び出し元のルールやタスクに定義した値によってデータを指定したり、スクリプトから呼び出し元オブジェクトの要素を取得したりすることができます。このシリーズの第 1 部の情報がさらに発展し、優れた MOM スクリプトを記述できるようになったはずです。

第 3 部では、スクリプトの話を一歩戻して、MOM スクリプトの作成およびデバッグの手順を説明します。内容としては、コードの記述方法や、各種のテストおよびトラブルシューティング方法などを取り上げます。


**
**