Windows PowerShellシェルでアクセス許可を操作する

Don Jones

この記事で使用しているコードのダウンロード: PowerShell2008_02.exe (151KB)

Windows PowerShell の話をするときに、アクセス許可についての質問をよく受けますが、特に多いのは、アクセス許可の変更操作をシェルによって自動化できる状況とその方法についての質問です。ディレクトリやレジストリのアクセス許可についての質問もよく寄せられますが、おそらく最も多いのはファイルのアクセス許可についての質問だと思います。アクセス許可と

ほぼすべてのコマンド ラインやスクリプト インターフェイス (Windows PowerShellTM や VBScript など) との関係については、良い面と悪い面の両方があります。

悪い面は、Windows® のアクセス許可は本質的に複雑であり、これを解決するために Windows PowerShell ができることはあまりないということです。この問題の原因は、Windows オペレーティング システムにはアクセス許可に関するさまざまなオブジェクトが存在することです。これは、ファイル システム、Active Directory®、レジストリなど、ほぼすべての要素に当てはまります。

まず、ディレクトリ オブジェクト、ファイル、フォルダなど、リソースそのものが存在します。次に、リソースに関連付けられているアクセス制御リスト (ACL) オブジェクトが存在します。ACL は、1 つ以上のアクセス制御エントリ (ACE) オブジェクトで構成されています。ACE は、基本的にセキュリティ プリンシパル (ユーザーまたはグループ) をアクセス許可 (読み取りやフル コントロール) と許可または拒否の状態と結び付けています。このセキュリティ プリンシパルもオブジェクトです。これで、5 つものオブジェクトが存在することになります。つまり、リソース、ACL、ACE、プリンシパル、およびアクセス許可です。

すべての種類のリソースにさまざまな種類のアクセス許可があるということが、アクセス許可をさらに複雑にしています。たとえば、ディレクトリ オブジェクトには、個々のオブジェクト属性へのアクセスを管理する複雑なアクセス許可があります。それに比べると、ファイルのアクセス許可は比較的単純です。

また、厳密に言えば、監査について考慮すると、この複雑さは 2 倍になります。実際には、各リソースには ACL が 2 つあります。1 つ目は、リソースへのアクセスを管理する随意 ACL (DACL) です。そして 2 つ目は、リソースの監査を制御するセキュリティ ACL (SACL) です。これらのアクセス許可を操作するということは、かなり複雑そうな大量のプログラミング オブジェクトについて理解する必要があることを意味します。これを簡略化するために Windows PowerShell のようなシェルにできることは限られているのです。

.NET Framework による制限

まだ物足りませんか

検索可能なコマンドレット ライブラリなどの Windows PowerShell の関連リソースを利用したり、Don Jones やその他の Windows PowerShell の専門家と連絡を取るには、www.PowerShellCommunity.org を参照してください。

Windows PowerShell の性質によって、作業はもう少し複雑になります。Windows PowerShell は Microsoft® .NET Framework に基づいて構成されており、基になっている .NET Framework のクラスを使用してアクセス許可を表示および操作します。これらの .NET Framework クラスは、ソフトウェア開発者がアクセス許可をより細かく厳密に制御できるように設計されています。もちろん、"より細かく厳密に" ということは情報が多いということであり、"非常に複雑である" と言い換えられることもしばしばあります。

また、.NET Framework では、アクセス許可を表現するクラスがすべての種類の Windows リソース用に提供されているわけではありません。たとえば、ファイル セキュリティを操作できるクラスは提供されていますが、共有フォルダのセキュリティを操作できるクラスは提供されていません。このため、Windows PowerShell は、すべての種類の Windows リソースのアクセス許可を操作することはできません。簡単に言えば、Windows PowerShell の機能は、.NET Framework によって提供される機能に限定されます。

シェルでアクセス許可を操作する

Windows PowerShell では、2 つのコマンドレットを使用してアクセス許可を管理できます。これらは、Get-ACL と Set-ACL です。ご想像のとおり、Get-ACL はリソースから ACL を取得します。その後、必要に応じて ACL を変更し、Set-ACL を使用して変更後の ACL をリソースに書き込みます。これらのコマンドレットはどちらも汎用的であり、Windows PowerShell システムの PSDrive プロバイダに依存しています。したがって、これら 2 つの ACL コマンドレットは、特定の種類のリソースを理解できる PSDrive プロバイダと、そのリソースのアクセス許可を変更できる PSDrive プロバイダが存在すれば、理論的にはどんな種類のリソースでも操作できます。Windows PowerShell に含まれている FileSystem PSDrive プロバイダと Registry PSDrive プロバイダでは、これら 2 つの ACL コマンドレットを使用したアクセス許可の管理がサポートされています (その他の PSDrive プロバイダでは、この操作がサポートされていない場合があります)。

図 1 のサンプル スクリプトを使用すると、開始ディレクトリ、セキュリティ プリンシパル、およびアクセス許可を指定することができます。このスクリプトは、プリンシパルに指定したアクセス許可を、指定したディレクトリ内のすべてのファイルとフォルダに適用します。また、繰り返し処理によってサブディレクトリにもアクセス許可を適用します。

Figure 1 プリンシパルのアクセス許可をディレクトリ内のファイルとフォルダに適用するコード

#ChangeACL.ps1
$Right="FullControl"

#The possible values for Rights are 
# ListDirectory, ReadData, WriteData 
# CreateFiles, CreateDirectories, AppendData 
# ReadExtendedAttributes, WriteExtendedAttributes, Traverse
# ExecuteFile, DeleteSubdirectoriesAndFiles, ReadAttributes 
# WriteAttributes, Write, Delete 
# ReadPermissions, Read, ReadAndExecute 
# Modify, ChangePermissions, TakeOwnership
# Synchronize, FullControl

$StartingDir=Read-Host "What directory do you want to start at?"
$Principal=Read-Host "What security principal do you want to grant" `
"$Right to? `n Use format domain\username or domain\group"

#define a new access rule.
#note that the $rule line has been artificially broken for print purposes.
#it needs to be one line. the online version of the script is properly
#formatted.
$rule=new-object System.Security.AccessControl.FileSystemAccessRule
($Principal,$Right,"Allow")

foreach ($file in $(Get-ChildItem $StartingDir -recurse)) {
  $acl=get-acl $file.FullName
 
  #Add this access rule to the ACL
  $acl.SetAccessRule($rule)
  
  #Write the changes to the object
  set-acl $File.Fullname $acl
  }

このスクリプトで重要なのは、変数 $rule でアクセスに関する新しい規則を定義している部分です。この操作には、.NET Framework クラスを "そのまま" 使用しています。ここがおそらく Windows PowerShell を使用したアクセス許可の管理において最も複雑な部分です。次にスクリプトは Get-ACL を使用して ACL を各ファイルとフォルダから順番に取得し、ACL の SetAccessRule メソッドを使用して新しい規則を適用します。その後、Set-ACL を使用して、変更後の ACL をリソースに書き込みます。

ACL から ACE を削除する操作など、さらに複雑な操作になるともっとややこしくなってきますが、実は上記の操作はそれほど複雑ではありません。個人的な意見ですが、この操作が複雑そうに見えるのは多くの手順が実行されるためです。つまり、ACL の取得、規則の定義、ACL の変更、および ACL の書き込みという手順です。サンプル スクリプトのコマンドは、単独ですべての処理を一度に実行できるようなすっきりとしたコマンドではありません。また、複数のファイルの ACL を変更する必要があったため、foreach ループ内にすべてのコードを記述し、Get-ChildItem を使用して実際にすべてのファイルとフォルダにアクセスする必要がありました。

最も簡単な方法を選択する

今月のコマンドレット : Get-QADUser

Active Directory を管理している皆さんにとっては必携のコマンドレットです。Windows PowerShell には組み込まれていませんが、無償でダウンロードできる Quest Software の ActiveRoles Management Shell for Active Directory (www.quest.com/activeroles-server/arms.aspx) に含まれています。

スナップインをインストールしたら、Get-QADUser を使用してディレクトリからユーザー オブジェクトを取得できます。もちろん、単純にコマンドレットを実行するとすべてのユーザーが返されますが、それでは多くの管理作業にはあまり役立ちません。しかし、このコマンドレットを使用すると、フィルタ条件を指定してドメイン コントローラに適用できるため、目的のユーザーのみが実際に Windows PowerShell に返されるようにすることができます。これは、最初にすべてのユーザーを取得してから Where-Object コマンドレットを使用してフィルタをかけるよりもかなり手間のかからない手法です。たとえば、Get-QADUser -l Redmond では、単に "1" という属性に "Redmond" が含まれているユーザーが返されます (ちなみに、属性 "l" は地域を表しており、GUI に都市として一覧表示されます)。その後、それらのユーザーを他のコマンドレットに渡して、HTML レポートの生成、グループへのユーザーの配置、ユーザーの削除などを行うことができます。

私の例が複雑だとは思いませんが、多くの管理者はさらに簡単な方法でアクセス許可を操作したいと思っているでしょう。おそらく、図 1 のような複数の段階から成るスクリプトを記述しなくても、一連のフォルダから特定のユーザー グループを一度に削除できる方法を望んでいるのではないでしょうか。

幸運なことに、Windows PowerShell ではアクセス許可を操作するための簡単な方法が提供されています。さらに、皆さんはおそらくその方法を既に使い慣れていると思います。

Windows PowerShell では、信頼できる従来の方法も使用することができます。たとえば、Dsacls.exe、Cacls.exe、Xcacls.exe などのコマンド ライン ツールを使用できます。これらは、より簡単にさまざまな種類のアクセス許可を操作できるように設計されています。これらのツールの構文は、Windows PowerShell コマンドレットで使用されるような標準化された構文とはまったく異なりますが、従来の cmd.exe シェルで使用されていたように、コマンド ラインを場当たり的に使用する必要はなくなります。Windows PowerShell を使用すると、これらのユーティリティを自動化することができます。

Windows PowerShell 内で旧式のコマンド ライン ユーティリティを使用するのは何となく良くないと言う人たち (私は純粋主義者と呼んでいます) もいます。私はその理屈をまったく理解できません。大事なのは作業を完了することであり、10 年前から使用されているコマンド ライン ユーティリティを使用するのが最も簡単な方法であるなら、それを使用します。"純粋だから" という理由だけで、多くの時間を費やしてまで特定の方法を使用するつもりはありません。マイクロソフトの Windows PowerShell チームも同じ考え方です。既存のツールで作業を完了できるのであれば、Windows PowerShell のシェル内でそのツールを使用できます。無駄な労力を使う必要はないでしょう。

図 2 は、私の著書である『Windows PowerShell: TFM』(SAPIEN Press、2006 年) から引用した短いスクリプトです。このスクリプトでは Windows PowerShell を使用して Cacls.exe をオートメーション起動しています。**このスクリプトは単なるデモンストレーションであるため、本格的なオートメーション ツールにするには手を加える必要があります。しかし、Windows PowerShell スクリプトがどのように情報を収集し、その情報を使用して、"ネイティブの" Windows PowerShell コマンドであるかのように Cacls.exe を起動しているかはおわかりいただけると思います (このスクリプトは情報を収集する際に情報の入力をユーザーに要求していますが、パラメータをファイルやデータベースから読み込むこともできます)。

Figure 2 Cacls.exe をオートメーション起動するコード

#SetPermsWithCACLS.ps1
# CACLS rights are usually
# F = FullControl
# C = Change
# R = Readonly
# W = Write

$StartingDir=Read-Host "What directory do you want to start at?"
$Right=Read-Host "What CACLS right do you want to grant? Valid choices are F, C, R or W"
Switch ($Right) {
  "F" {$Null}
  "C" {$Null}
  "R" {$Null}
  "W" {$Null}
  default {
    Write-Host -foregroundcolor "Red" `
    `n $Right.ToUpper() " is an invalid choice. Please Try again."`n
    exit
  }
}

$Principal=Read-Host "What security principal do you want to grant?" `
"CACLS right"$Right.ToUpper()"to?" `n `
"Use format domain\username or domain\group"

$Verify=Read-Host `n "You are about to change permissions on all" `
"files starting at"$StartingDir.ToUpper() `n "for security"`
"principal"$Principal.ToUpper() `
"with new right of"$Right.ToUpper()"."`n `
"Do you want to continue? [Y,N]"

if ($Verify -eq "Y") {

 foreach ($file in $(Get-ChildItem $StartingDir -recurse)) {
  #display filename and old permissions
  write-Host -foregroundcolor Yellow $file.FullName
  #uncomment if you want to see old permissions
  #CACLS $file.FullName
  
  #ADD new permission with CACLS
  CACLS $file.FullName /E /P "${Principal}:${Right}" >$NULL
  
  #display new permissions
  Write-Host -foregroundcolor Green "New Permissions"
  CACLS $file.FullName
 }
}

アクセス許可を適切に操作できましたか

Windows PowerShell はアクセス許可の操作に向いていないという意見を聞いたことがあります。簡単で汎用的なアクセス許可の管理を提供するネイティブ コマンドレットが提供されないことがその理由だそうです。私はその意見に同意できません。まず、このような意見を持っているのは主に UNIX 環境に携わっている管理者がほとんどです。実は、Windows のアクセス許可のシステムは UNIX で使用されているものよりも非常に複雑です。この複雑なシステムを操作する場合、Windows PowerShell を使用した作業も複雑になります。しかし、これは Windows PowerShell の問題ではありません。

また、Windows PowerShell では、ここで紹介したような古き良きコマンド ライン ユーティリティと同じ形式で、簡素化されたツールを使用できます。確かに、Windows プラットフォーム全体にわたるすべてのアクセス許可を管理するには、.NET Framework を拡張する必要があります。しかし全体的に見れば、Windows PowerShell はどちらの利点も与えてくれます。つまり、アクセス許可を簡単に管理でき、きめ細かく精密な管理ツールも利用できるということです。

Don Jones は TechNet Magazine の編集に携わっており、『Windows PowerShell: TFM』(SAPIEN Press、2007 年) の共著者でもあります。**また、彼は Windows PowerShell に関するトレーニングの講師も務めています (www.ScriptingTraining.com を参照)。www.ScriptingAnswers.com で公開されている Web サイトから、彼と連絡を取ることができます。

© 2008 Microsoft Corporation and CMP Media, LLC. All rights reserved; 許可なしに一部または全体を複製することは禁止されています.