前回までは、複数のLDAPオブジェクトデータをエクスポート/インポートする(バルクインポート)ツールとして、csvdeやldifdeを紹介しました。これらのツールは大量のアカウントを同時に作成/変更することに最適化されており、個々のオブジェクト情報の検索や変更を行なうのは得意ではありません。今回は個々のオブジェクトデータを直接操作するコマンドを紹介します。      
DS*コマンドとは 
DS*コマンドは、個々のLDAPオブジェクトを検索/表示/変更/移動/削除するコマンド群の総称となります。目的に応じて異なるコマンドを利用します。目的別コマンドのリストを表1に示します。 
表1  DS*コマンドの一覧
  
    dsquery LDAPオブジェクトを検索する 
   
  
    dsadd LDAPオブジェクトを新規に追加する 
   
  
    dsget LDAPオブジェクトの内容を表示する 
   
  
    dsmod LDAPオブジェクトの内容を変更する 
   
  
    dsmove LDAPオブジェクトを移動する 
   
  
    dsrm LDAPオブジェクトを削除する 
   
各コマンドには、操作するオブジェクトの種類ごとのサブメニューがあり(dsmoveとdsrmにはありません) 、実際はサブメニューを指定した形でコマンドを実行します。たとえば、"ユーザアカウントを検索したい"ならdsquery userコマンドを、"コンピュータアカウントを検索したい"ならdsquery computerコマンドを使います。一例としてdsqueryコマンドのサブメニューを記載しますが、dsquery /?コマンドヘルプから、情報の詳細を確認できます(他のコマンドも同じ要領です) 。なお、コマンドによってサブメニューの内容が異なる点には、注意します。          
表2  dsqueryコマンドのサブメニュー
  
    dsquery computer "コンピュータ"オブジェクトを検索する 
   
  
    dsquery contact "連絡先"オブジェクトを検索する 
   
  
    dsquery subnet "サブネット"オブジェクトを検索する([Active Directoryサイトとサービス]で利用する)  
   
  
    dsquery group "グループ"オブジェクトを検索する 
   
  
    dsquery ou "OU"オブジェクトを検索する 
   
  
    dsquery site "サイト"オブジェクトを検索する([Active Directoryサイトとサービス]で利用する)  
   
  
    dsquery server "サーバ(DSA)"オブジェクトを検索する([Active Directoryサイトとサービス]で利用する)    
   
  
    dsquery user "ユーザ"オブジェクトを検索する 
   
  
    dsquery quota "ディレクトリパーティションでのクォータ設定"オブジェクトを検索する 
   
  
    dsquery partition "ディレクトリパーティション"を検索する 
   
  
    dsquery * フィルタを使って汎用的にオブジェクトを検索する 
   
また、DS*コマンドをサブメニューには、サブメニューの内容に添ったオプションが用意されています。たとえばdsquery userコマンドの-inactiveオブションを使うと、一定期間ログオンしていないユーザを検索する、ということができます。一例としてdsquery userコマンドのサブメニューを記載しますが、dsquery user /?コマンドヘルプから、情報の詳細を確認できます(他のコマンドも同様です) 。       
表3  dsquery userコマンドのサブメニュー
  
    {<開始ノード>|forestroot|domainroot} 検索を開始するノードを指定する。 
   
  
    -o {dn|rdn|upn|samid} 出力形式を指定する。 
   
  
    -scope {subtree|onelevel|base} 検索のスコープを指定する。 
   
  
    -name <名前> name属性(名前)で一致するオブジェクトを検索する。   
   
  
    -namep <ふりがな> msDS-PhoneticDisplayName属性(表示名のふりがな)で一致するオブジェクトを検索する。   
   
  
    -desc <説明> description属性(説明)で一致するオブジェクトを検索する。   
   
  
    -upn <UPN> userPrincipalName属性(UPN)で一致するオブジェクトを検索する。   
   
  
    -samid <SAMアカウント名> saMAccountName属性(SAMアカウント名)で一致するオブジェクトを検索する。   
   
  
    -inactive <週> <週>週間の間ログオンしていないオブジェクトを検索する。 
   
  
    -stalepwd <日> <日>日間パスワードを変更していないオブジェクトを検索する。 
   
  
    -disabled 無効なアカウントとなるオブジェクトを検索する。 
   
  
    {-s <サーバ名>"|-d " 接続先のドメインコントローラやドメインを指定する。 
   
  
    -u <ユーザ名> 指定したユーザ名で接続する。 
   
  
    -p {<パスワード>|*} 接続するユーザのパスワードを指定する。 
   
  
    -q 標準出力への出力を抑制する。 
   
  
    -r 紹介(他のLDAPサーバへの再検索)を再帰的に行うか指定する。   
   
  
    -gc グローバルカタログを検索する。 
   
  
    -limit <オブジェクト数> 検索により返されるオブジェクト数を指定する。 
   
  
    {-uc|-uco|-uci} パイプラインやファイルへの入力や出力をUnicode形式にするかどうか指定する。 
   
ds*コマンドのサブメニューがあることで、LDAPフィルタを使ったオブジェクトの種類を指定する方法を知らなくても、必要な種類のオブジェクトを簡単に操作することができます。(サブメニューにない)特殊なオブジェクトや属性をキーワードとして操作したい場合、dsquery *コマンドを使って汎用的にオブジェクトを検索することができます。   
DS*コマンドのもうひとつの強みは、"パイプライン"が使えることです。パイプラインとは、あるコマンドの実行結果を透過的に引き継いで、次に実行するコマンドのパラメータ(引数)の一部とする、ということです。この機能を使うことで、たとえばdsqueryコマンドで検索抽出したすべてのオブジェクトの詳細データを、dsgetコマンドで確認することができます。      
簡単なDS*コマンドを使う 
簡単にDS*コマンドを使う方法として、いくつかの例をあげてみます。 
dsquery user "OU=営業部,DC=marubatsucorp,DC=local" -stalepwd 30  
実行結果 
"OU=営業部,DC=marubatsucorp,DC=local"ディレクトリ配下のユーザオブジェクトで、30日間以上パスワードを変更していないコンピュータを検索します。Active Directoryパスワードポリシーの"パスワードの有効期限"で決められた期間とは関係なく、ユーザのパスワード変更状況をチェックするときに便利です。  
dsquery computer "CN=Computers,DC=marubatsucorp,DC=local" -inactive 4  
marubatsucorp.localドメインのドメインコントローラ以外のコンピュータオブジェクトで、4週間ログオンしていないコンピュータを検索します。一定期間利用されていないコンピュータを確認するときに便利です。  
dsadd user "CN=川本 尚子,OU=第二課,OU=営業部,DC=marubatsucorp,DC=local" -samid nkawamoto -upn nkawamoto@marubatsucorp.local -pwd P@ssw0rd -mustchpwd yes -memberof "CN=営業部第二課,OU=第二課,OU=営業部,DC=marubatsucorp,DC=local" -fn 尚子 -ln 川本 -display "川本 尚子" -desc 営業部第二課ユーザー -tel 03-1234-6789 -email nkawamoto@marubatsucorp.local -dept 営業部第二課 -company ○×株式会社  
実行結果 
"OU=第二課,OU=営業部,DC=marubatsucorp,DC=local"ディレクトリ内に新規ユーザ"川本 尚子"を登録します。
個々のオプションについて簡単に紹介しますが、これ以外のオプションも存在します。詳しくはdsadd user /?コマンドヘルプをご覧ください。 
表4  dsadd userのオプション(一部) 
  
    -samid SAMアカウント名を指定する。 
   
  
    -upn UPNを指定する。 
   
  
    -pwd パスワードを指定する。 
   
  
    -mustchpwd "ユーザーは次回ログオン時にパスワードの変更が必要"を指定する。 
   
  
    -memberof 所属するグループを指定する。 
   
  
    -fn "名"を指定する。 
   
  
    -ln "姓"を指定する。 
   
  
    -display "表示名"を指定する。 
   
  
    -desc "説明"を指定する。 
   
  
    -tel "電話番号"を指定する。 
   
  
    -email "電子メール"を指定する。 
   
  
    -dept "部署"を指定する。 
   
  
    -company "会社名"を指定する。 
   
dsget group "CN=営業部第二課,OU=第二課,OU=営業部,DC=marubatsucorp,DC=local" -members  
"CN=営業部第二課,OU=第二課,OU=営業部,DC=marubatsucorp,DC=local"グローバルグループのメンバ(所属するユーザ)の一覧を表示します。セキュリティグループのメンバ一覧を確認するときに便利です。  
dsget user "CN=山川 しずか,OU=第二課,OU=営業部,DC=marubatsucorp,DC=local" -memberof  
"CN=山川 しずか,OU=第二課,OU=営業部,DC=marubatsucorp,DC=local"ユーザアカウントが所属するグループの一覧を表示します。ユーザが所属するグループの一覧を確認するときに便利です。
dsquery server -forest -hasfsmo pdc  
フォレスト内のすべてのドメインのPDCエミュレータを検索します。-hasfsmoオプションにはschema(スキーマ) 、name(名前付け) 、infr(インフラストラクチャ) 、rid(RID)の各マスタを検索できます。        
dsmove "OU=第二課,OU=営業部,DC=marubatsucorp,DC=local" -newname 輸入販売課  
実行結果 
"OU=第二課,OU=営業部,DC=marubatsucorp,DC=local"OUの名前を"輸入販売課"に変更します。オブジェクトの名前を変える場合、たとえばdsmod userコマンドに直接名前を変更するオプションはないので、dsmoveコマンドを使って"新しい名前でオブジェクトを配置し直す"というかたちをとります。  
dsmove "CN=SERVER00,CN=Servers,CN=Tokyo,CN=Sites,CN=Configuration,DC=marubatsucorp,DC=local" -newparent "CN=Servers,CN=Kanagawa,CN=Sites,CN=Configuration,DC=marubatsucorp,DC=local"  
ドメインコントローラServer00オブジェクト(DSAオブジェクト)を、TokyoサイトからKanagawaサイトに移動します。[Active Directoryサイトとサービス]スナップインで行なう作業に相当します。たとえばWindows Server 2008 R2 Server Coreでドメインコントローラを構成する場合、これらのコマンドを利用すると便利です。    
パイプラインによる複雑なDSコマンドを使う 
先に記載したとおり、パイプラインを使って複数のコマンドを連続して利用することで、複雑な動作が可能になります。いくつかの例を示します。  
dsquery user "OU=営業部,DC=marubatsucorp,DC=local" -stalepwd 21|dsmod user -mustchpwd yes  
実行結果 
"OU=営業部,DC=marubatsucorp,DC=local"ディレクトリ内で、21日間パスワードの変更がなかったユーザアカウントについて、次回ログオン時にパスワードを変更することを強制します。dsquery userコマンドでパスワードの変更状況をチェックし、該当するアカウントにdsmod userコマンドでパスワードの変更を強制する設定を行ないます。パスワードポリシーとは関係なく強制的にパスワードを変更させたい場合に、便利です。    
dsquery computer "CN=Computers,DC=marubatsucorp,DC=local" -inactive 12|dsrm -noprompt  
"CN=Computers,DC=marubatsucorp,DC=local"ディレクトリ内で、12週間ログオンがなかったコンピュータオブジェクトを検索し、そのオブジェクトを削除します。利用されないアカウントオブジェクトをそのままにしておくのはセキュリティ上問題があるので、無効化したり削除したい場合に便利です。   
dsquery server|dsget server -dnsname -site -isgc  
実行結果 
フォレスト内のすべてのドメインコントローラについて、所属するサイトとグローバルカタログかどうかを表示します。このコマンドを使うことで[Active Directoryサイトとサービス]スナップインの情報を簡単にテキスト化することができます。 
dsadd group "CN=課長グループ,OU=営業部,DC=marubatsucorp,DC=local" -desc 営業部課長グループ && dsquery * -filter "&(objectCategory=Person)(objectClass=User)(department=営業部*)(title=課長*)"|dsmod group "CN=課長グループ,OU=営業部,DC=marubatsucorp,DC=local" -addmbr  
実行結果 
少し長いですが、まずdsadd groupコマンドで新しいセキュリティグループ(課長グループ)を"OU=営業部,DC=marubatsucorp,DC=local"に作成し、dsquery *コマンドで、部署名(department)に"営業部"が、役職名(title)に"課長"が含まれるユーザオブジェクトを検索して、dsmod groupコマンドで"CN=課長グループ,OU=営業部,DC=marubatsucorp,DC=local"グループのメンバとして、これらのユーザを追加します。ユーザオブジェクトはobjectCategory属性に"Person"文字列とobjectClass属性に"User"文字列を含んでいますので、このような検索条件で抽出することができます。             
dsquery * -filterコマンドを使うと、任意の属性を使って検索条件を指定できるため、非常に便利です。検索条件を指定する演算子には、つぎのようなものがあります。なお、特殊文字をリテラル文字(表記上の文字)として扱う場合、エスケープシーケンスによる符号化が必要です。あわせて記載します(表5、表6) 。         
表5  LDAP検索時の演算子
  
    = Equal 等しい 
   
  
    & And かつ 
   
  
    | Or または 
   
  
    ! Not ~でない 
   
  
    > Less than より小さい 
   
  
    < Greater than より大きい 
   
  
    >= And Above 以上 
   
  
    <= Or Below 以下 
   
表6  特殊文字のエスケープシーケンス
  
    * アスタリスク \2a 
   
  
    ( 開き括弧 \28 
   
  
    ) 閉じ括弧 \29 
   
  
    \ バックスラッシュ \5c 
   
  
    NUL Null文字 \00 
   
  
    / スラッシュ \2f 
   
dsadd ou "OU=利用していないアカウント,DC=marubatsucorp,DC=local" && For /F "usebackq delims=" %i in (`dsquery * -filter "&(|(&(objectCategory=Person)(objectClass=User)(company=○×株式会社))(objectClass=computer))(lastLogon<=129249216000000000)"`) Do @dsmove %i -newparent "OU=利用していないアカウント,DC=marubatsucorp,DC=local"  
実行結果 
このコマンドは、まずdsadd ouコマンドで新しいOU(利用していないアカウント)を"DC=marubatsucorp,DC=local"に作成し、dsquery *コマンドで、会社名(company)に"○×株式会社"が含まれるユーザオブジェクトとすべてのコンピュータオブジェクトについて、最終ログオン時間(lastLogon)が"2010年7月30日9:00:00"以前のオブジェクトを検索して、dsmoveコマンドで該当するオブジェクトを移動します。           
通常DS*コマンドはパイプラインによる引数の引き渡しができますが、コマンドによってうまくいかないことがあります。このようなときには、For /Fコマンドを利用することで、引数を適切に引き渡すことができます。ここでは、dsquery *コマンドの結果(複数行のDN)をひとつずつ%iに代入し、Do [dsmoveコマンド]の適切な位置で変数を利用することで、コマンドを実現させています(くわしくはFor /?コマンドヘルプをご覧ください) 。         
明示的なログオン時間をしきい値としたい場合、lastLogonまたはlastLogonTimestamp属性を検索条件に加える必要があります。lastLogon属性の時刻は、1601年1月1日を起点に100ナノ秒単位の累積時間で表現されますので、しきい値の設定には計算が必要です(簡単なチェックにはw32tm /ntteコマンドが便利です) 。またlastLogon属性はドメインコントローラ間で複製を行なわない(ドメインコントローラごとに異なる)ので、どのドメインコントローラでも同じ値が必要な場合lastLogonTimestamp属性を使います。ただしlastLogonTimestamp属性にはいくつかの制限がある(Windows Server 2003ドメイン機能レベルで動作する、必ずしも最新のログオン時間を表していない等)ので、注意してください。           
dsquery * "OU=利用していないアカウント,DC=marubatsucorp,DC=local" -filter "&(!objectClass=organizationalUnit)(whenChanged<=20100730000000.0Z)"|dsrm -noprompt  
dsquery *コマンドで"OU=利用していないアカウント,DC=marubatsucorp,DC=local"ディレクトリ内の、オブジェクトクラスがOU以外でwhenChanged属性が"2010年7月30日00:00:00(GMT時間)"以前のものを検索し、dsrmコマンドで削除します。  
whenChanged属性は、オブジェクトに直接紐付いた任意の属性が変更されたときにその時刻が記録されます。ログオンやパスワードの変更も含め、オブジェクトに何か変更が加えられた時刻を確認するときに利用します。なお、whenChanged属性は国際標準時で時刻が設定されますので、OSのタイムゾーン設定に添った調整が必要です。うえのコマンドの場合、日本のタイムゾーン(GMT+9:00)であれば"2010年7月30日09:00:00"がしきい値になります。       
Column:PowerShell 2.0を使ったオブジェクトの管理  
Windows Server 2008 R2では、DS*コマンドのほかPowerShell 2.0を使ったActive Directoryの管理を行なうことができます。PowerShellではコマンドレットと呼ばれる専用コマンドを使って、Actice Directoryの各種オブジェクトの新規作成/変更/削除やActive Directoryの自身の設定を行なうことができます。   
多くの種類のコマンドレットがあるのでくわしい紹介はできませんが、PowerShellでしか設定できないコマンドレット(細かい設定が可能なパスワードポリシーを設定するSet-ADFineGrainedPasswordPolicyや、Active Directoryごみ箱機能(Recycle Bin)を設定するEnable-ADOptionalFeature等)があること、マイクロソフトの戦略として今後はPowerShellスクリプト技術を中心に展開していくことを考えれば、PowerShellを使ったスクリプト技術を習得しておくことは、非常に重要です。       
Active Directoryのコマンドレットにどのようなものがあるのか、から知りたいのであれば、Windows Server 2008 R2ドメインコントローラで[PowerShell]のシェルを起動して、次のコマンドレットを実行すれば、最初の疑問は解決するでしょう。    
Import-Module ActiveDirectory
Get-Command -Module ActiveDirectory|Foreach-Object {Get-Help $_.Name|Select-Object Name,Synopsis}  
実行結果