次の方法で共有


Active Directory: データを切断して便利に扱う

切断されたレコードセット (DRS) と DRS に関連するユーティリティを使用すると、クエリのパフォーマンスを維持するのに役立ちます。

James Turner

切断されたレコードセット (DRS) とは、メモリ内に存在する ADO レコードです。DRS は、元のデータ ソースから完全に切り離されており、比較的簡単に "オンデマンド" で作成できます。Active Directory などのソースからデータを収集し、単純な SQL 型のクエリを発行して有用な情報を収集できます。

この記事で説明するユーティリティは複雑なものではなく、リレーショナル データベースでもありません。通常 1 日または 1 週間単位で評価する必要のある、一般的なデータで構成されるデータベースです。データベースのフィールド数は最小に保たれています。通常、レコードの総数は 10,000 件未満で、ファイル サイズとメモリの使用量は最小になっています。このサイズ (およびこれより小さいサイズ) のレコードセットでは、クエリのパフォーマンスが高いことがわかるでしょう。

DRS ユーティリティを使用すると、時間を節約することが可能で、データ アクセスのパフォーマンスが高くなり、ディスク領域のフットプリントとメモリの使用量が少なくなります。通常、DRS ユーティリティにより、処理量が抑えられます。DRS はさまざまな方法で使用できます。対話型クエリが最適なときには、特定のクエリに一致するデータ セットを検出する .hta 形式の GUI を構築できます。

GUI が不要なときは、目的の作業を実行するのに必要な方法で DRS を作成してデータを評価します。その場合、ユーザー ID とコンピューター名を含むログ ファイルを整理して、これらの値を別の値で置き換えなければならないことがあります。

長年にわたり、DRS は、次のような作業を行うための迅速かつ効率的ですばらしい無料ユーティリティとして実証されています。

  • セキュリティ ログ スクラブ
  • セキュリティ識別子 (SID)/ユーザー保持データベース
  • SID/ユーザー相互参照ルックアップ
  • 印刷キュー ルックアップ
  • 管理者アカウントの週次比較

DRS を構築するには、まず ADO レコードセット (ADOR) オブジェクトを作成します。VBScript を使用した 2 つの例を示します。1 つ目は次のとおりです。

Set DRS = CreateObject("ADOR.Recordset")

もう 1 つは次のとおりです。

Set DRS = CreateObject("ADODB.Recordset")

ADOR は、レコードセット インターフェイスのみを公開する軽量の ADO クライアントです。ADO インスタンスを作成できる場合は、ADOR インスタンスも作成できます。ADOR は、ADO のサブセットである ADOdb のサブセットです。個人的には ADODB.Recordset をよく使用しますが、もう一方を使用してもかまいません。

DRS データベースは簡単に構築できます。まずデータベースの構築に関係のあるフィールドを設定し、Active Directory などのデータを使用してフィールドに値を設定します。

セキュリティ ログ収集ユーティリティ データベースの設定方法の例を次に示します。

Const adFldIsNullable = 32 Set DRS = CreateObject("ADODB.Recordset") DRS.Fields.Append "SecurityObject",201,256,adFldIsNullable DRS.Fields.Append "Type",201,256,adFldIsNullable DRS.Fields.Append "Substitute",201,256,adFldIsNullable DRS.Open

1 行目で定数を宣言しています。adFldIsNullable 定数は、フィールドに null 値を設定できることを示しています。この収集スクリプトでは、フィールドに常にデータが含まれています。そのため、必ずしもこの定数を含める必要はなく、この手順を省略してもかまいません。また、定数を含めても、スクリプトに影響が出ることはありません。ただし、データを含まない可能性があるフィールドを含むデータベースを作成する場合には、この定数を宣言して使用する必要があります。このスクリプトの他の特長をいくつか紹介します。

  • 2 行目で、DRS オブジェクトを作成しています。
  • 3 ~ 5 行目で、データベースのフィールドを定義しています。
  • 6 行目で、データベースを開いてデータを受け入れる準備ができていることを宣言しています。

Fields.Append ステートメントの構文を見てみましょう。

  • 作成されるフィールド名は SecurityObject です。
  • 201 という値は、フィールドのデータ型が長い文字列であることを示しています。
  • 256 という値は、フィールドの DefinedSize が可変長サイズであることを指定しています (定義によると、この型のフィールドで 255 文字を超えるフィールド幅は、可変長として扱われます。つまり、このフィールドには 256 文字以上の文字列でも 256 文字未満の文字列でも格納できます)。
  • adFldIsNullable フィールド属性は null 値を受け入れることを示しています。

フィールドのデータ型の詳細については、「DataTypeEnum (英語)」を参照してください。フィールド幅の詳細については、「Append メソッド (ADO) (英語)」を参照してください。

データベースにデータを追加するには、次の例のような手順に従います。

DRS.AddNew DRS("SecurityObject") = "172.172.\d\d?\d?\.\d\d?\d?" DRS("SecurityType") = "IP" DRS("Substitute") = "a1.b1.c1.d1" DRS.Update

レコードを設定するたびに DRS.Update メソッドを発行する必要はなく、全レコードセットを設定するまで、このコマンドの発行を遅らせてかまいません。Update メソッドでは単純にデータベースにレコードをコミットして、レコードをアクセス可能な状態にできます。

前述のコード スニペットでは、1 つのレコードをデータベースに追加しました。収集プロセスでは、この特定のレコードを使用して、172.172 で始まる IP アドレスを含むテキスト ベースのログ ファイルを検索して、172.172 で始まる値を a1.b1.c1.d1 で置換します。

Active Directory のコンピューター名とサーバー名のコレクションをデータベースに設定するには、図 1 のような LDAP クエリを作成して、データベースにデータを設定します。

図 1 LDAP クエリを作成して、データベースにデータを設定するスクリプト

Const ADS_SCOPE_SUBTREE = 2 DNC = GetObject("LDAP://RootDSE").Get("defaultNamingContext") Set objConnection = CreateObject("ADODB.Connection") Set objCommand = CreateObject("ADODB.Command") objConnection.Provider = "ADsDSOObject" objConnection.Open "Active Directory Provider" Set objCommand.ActiveConnection = objConnection objCommand.Properties("Page Size") = 1000 objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE objCommand.CommandText = _ "SELECT cn FROM 'LDAP://" & DNC & "' WHERE objectcategory = 'computer'" Set objRecordSet = objCommand.Execute objRecordSet.MoveFirst SubstCount = 1 Do Until objRecordset.EOF DRS.AddNew DRS("SecurityObject") = objrecordset.Fields("CN").Value DRS("SecurityType") = "Host" DRS("Substitute") = "Host" & SubstCount SubstCount = SubstCount + 1 objRecordset.MoveNext Loop

この一連の手順で作成した各レコードには、SecurityType 値が "Host" および Substitute 値が "Hostnnn" (nnn は Host123 などの通し番号) のコンピューター名が含まれています。このコードを詳しく確認すると、ユーザー ID をデータベースに設定するために似たような処理がコーディングされていることがわかります。

データベースの設定と .Update メソッドの発行が完了したら、レコードセットの並べ替え、読み込み、およびフィルター処理を行えます。データベースを処理するには、まずレコードセット ポインターを最初のレコードに配置してから、次のようにデータベースを順番に処理するループ プロセスを設定します。

DRS.MoveFirst Do while Not DRS.EOF myRegExp.Pattern = "\b" & Lcase(Trim(DRS.Fields.Item("SecurityObject"))) & "\b" If myRegExp.Test(strNewText) Then chng2 = Lcase(Trim(DRS.Fields.Item("Substitute"))) strNewText = myRegExp.Replace(strNewText,chng2) End If DRS.MoveNext Loop

ループ プロセスは、EOF (ファイルの終わり) マーカーに到達するまで継続します。MoveNext メソッドも重要で、このメソッドでレコードセット ポインターを次のレコードに移動します。このメソッドを使用しないと、プログラムが無限ループ状態になります。

データベースを処理するときは、前述のコード スニペットの 3 行目と 5 行目で示したように、Fields.Items プロパティを使用して、各レコードのデータ フィールドの値にアクセスできます。

  • DRS.Fields.Item("SecurityObject") には、Active Directory のユーザー ID またはコンピューター名の値が格納されます。
  • DRS.Fields.Item("Substitute") には、ユーザー ID またはコンピューター名が検出された場合に、それらの値を置換する値が格納されます。

前述のコード スニペットでは、整理する必要があるファイルを開いたり、ファイルを変数に読み込んだりする処理は含めていません。次に、テキスト内の文字列を特定して、指定の値と置換するための Regular Expression オブジェクトを作成しました。

検索対象の文字列は、すべてデータベースの SecurityObject という名前のフィールドに格納されており、置き換える値は Substitute という名前のフィールドに格納されています。この例では、データベースには、特定のドメインに存在するすべてのコンピューター名とユーザー ID が格納されています。ループ プロセスの処理中に、DRS によって、テキスト ファイル内に SecurityObject の値が検出されると、関連付けられた Substitute の値で置き換えられます。

DRS が EOF マーカーに到達すると、ファイルを確認し、データを収集したテキスト ファイルがファイル システムに書き込まれ、承認されるとベンダー サポートに渡されます。このコードは、そのまま使用することも、必要に応じて変更することもできます。Active Directory に存在する一般的な名前や語句をスキップするようにコードの微調整が必要な場合もあるでしょう。

この記事では DRS でできることの概要を示しただけですが、皆さんのお役に立てばさいわいです。DRS については、SQL 型クエリを使用したレコードの並べ替え、フィルター処理、表示など、DRS の機能を活用するための GUI の作成など、説明できることはまだたくさんあります。

James Turner

James Turner は、1980 年代中ごろから情報システム アナリストとして活躍しており、Windows のシステム管理者として働いています。また、長年にわたるスクリプト愛好家で、コーディングを楽しんでいます。

関連コンテンツ