【Script】AD/File/Reg のアクセス権リストは Get-ACL にお任せ~その1

ヒトはパンのみに生きるに非ず…とか言うようですが、わたしは PowerShell のみに生きてもよいとさえ思っています。もうたまりません。いま、可愛いヤツ ランキングをつけたら、間違いなく Windows PowerShell が1位です。2番目が 赤ちょうちん の頃の秋吉久美子。3番目に偕楽園の梅娘と写真を撮ってくれと泣いてせがんだ5歳の頃の自分です。

アクセス権の一覧を作りたいけど、うまい方法が無くて困っている方はいらっしゃいませんか?これまで、CACLSコマンドとかを使ってきて、うーんどうも…じゃVBSで作るか!と思い立ったものの、以外に難しくて断念したり…(VBSを使う方法は知っておく価値アリなので、時間のあるときに解説しようかとも思っています)。

いい方法があるんです。Windows PowerShell の Get-ACL コマンドレットです。

このコマンドレット1つで、ファイルシステムも、レジストリも、はてはActive Directory のオブジェクトに関してもアクセス権を参照することができるのです!現場のSEさんにとって、これほど便利なコマンドがいままであったでしょうか?いや無いです。

■ファイルシステム編

まずはPowerShell のコンソールを開いてください。

以下は、C:\ に設定されているアクセス権を取得しています。

PS C:\> Get-ACL c:\ | Out-GridView

出力結果は以下の通りです。パイプ(|)を通して、Out-GridView に結果を渡しています。

image

うーん。見やすい…。ちなみに、おなじみCACLSコマンドを使用した結果は以下の通りです。

PS C:\> cacls C:\ | Out-GridView

image

うむむ、いまいちですよね。やっぱり、Get-ACL の結果のほうが美しいです。

では、Get-ACLの結果を CSVファイルに保存するにはどうするかといえば、以下のようにします。ちょっと長いですが、1行で書けてしまいます。

PS C:\> Get-Acl C:\ |Select-object @{Label="Path";Expression={Convert-Path $_.Path}}, Owner, AccessToString |Export-Csv C:\tmp\accesslist.csv

CSVファイルに保存するには、Export-CSV コマンドレットを使うのが簡単です。ここでは、C:\tmp\accesslist.txt というファイルに保存しています。

さて、難しいのは、「Get-ACL」と「Export-CSV」の間にあるSelect-Object ですよね。ためしに、Get-ACL の結果をそのまま Export-CSVを使って保存してみてください。Path、Owner、AccessToString以外のプロパティも保存されてしまうことがわかります。今欲しいのは、ひとまず3つの属性だけなので、Select-Object を使用して、Get-ACLの出力結果から必要な3つの属性だけを抜き出しています。

もう1点、以下のコマンドで、Path の値を見てください。

PS C:\> Get-Acl C:\ |Select-Object path

Path ---- Microsoft.PowerShell.Core\FileSystem::C:\

Path の値として「Microsoft.PowerShell.Core\FileSystem::C:\」という文字列が格納されていることに気づくと思います。これはPowerShell内での絶対パスの表現方法です。例えば、レジストリの場合には、Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\ 、Active Directory ならば、ActiveDirectory:://RootDSE/CN=Schema,CN=Configuration,DC=contoso,DC=com といった具合です。

Microsoft.PowerShell.Core\FileSystem:: が入っているからと言って意味不明なものでもありませんが、管理上、ちょっと気持ち悪いですね。

そこで、このPowerShell上の絶対パスを、ファイルシステムやレジストリ、Active Directory 内の相対的なパスに変換したいと考えるわけですが、この時に使用するのが Convert-Path コマンドレットです。ためしに、以下のように入力してみてください。結果として、ファイルシステムプロバイダー内の相対パスである C:\ が結果として得られます。

PS C:\> Convert-Path( (Get-ACL C:\).Path ) C:\

で、残った問題は @{Label="Path";Expression={Convert-Path $_.Path}} が何を意味しているかですよね?

なぜ単純に、Select-Object {Convert-Path $_.Path}, Owner, AccessToString と書かないのか?ためしに書いてみると、以下のような結果になります。

PS C:\> Get-Acl C:\ |Select-Object {Convert-Path $_.Path}, Owner, AccessToString

Convert-Path $_.Path Owner AccessToString -------------------- ----- -------------- C:\ NT SERVICE\TrustedInstaller NT AUTHORITY\Authenticated...

何がダメなのかわかりますか?そうです。ラベル名として Path が欲しいのに、Convert-Path $_.Pathとなってしまうのです。せっかくCSVに保存するのですから、きれいにしておきたいですね。そこで、@{  }の登場です。@{   } は、Key-Value 型の配列を表現しています。

わかりずらいので、図にしてみました。以下をご覧ください。Get-ACL の戻り値は、以下の図に書かれた表のように、LabelとExpressionの対で格納されています。

スライド1

つまり、 @{Label="Path";Expression={Convert-Path $_.Path}}   は、Label の値が「Path」の列のExpressionの値を「Convert-Path $_.Path 」という値に置き換える..ということを意味しています。

これで疑問解決ですね。

安心して、以下を実行してください。

PS C:\> Get-Acl C:\ |Select-object @{Label="Path";Expression={Convert-Path $_.Path}}, Owner, AccessToString |Export-Csv C:\tmp\accesslist.csv

保存された accesslist.csv ファイルをEXCEL等で開くと、以下のように見えるはずです。

Path Owner AccessToString
C:\ NT SERVICE\TrustedInstaller NT AUTHORITY\Authenticated Users Allow AppendData NT AUTHORITY\Authenticated Users Allow -536805376 NT AUTHORITY\SYSTEM Allow FullControl NT AUTHORITY\SYSTEM Allow 268435456 BUILTIN\Administrators Allow 268435456 BUILTIN\Administrators Allow FullControl BUILTIN\Users Allow ReadAndExecute, Synchronize

この表の中で、アクセス権が数値で書かれているものがあります。これらは、特殊なアクセス権を表現しています。

  • -536805376:サブフォルダーとファイルに対する特殊なアクセス権
    image
  • 268435456 :サブフォルダとファイルに対するフルコントロール

これら数値は、特殊なアクセス権の組み合わせによって変わります。

複数のファイルやフォルダのアクセス権を取得する際にはワイルドカードを使用することもできます。

PS C:\> Get-Acl *.txt

また、指定したフォルダ配下を全てなめてアクセス権を取得するには、Get-ChildItem を使用して、以下のように書きます。複数行にまたがっていますが、改行なしの1行です。

PS C:\tmp> Get-ChildItem -Recurse |Get-Acl | Select-object @{Label="Path";Expression={Convert-Path $_.Path}}, Owner, AccessToString |Export-Csv C:\tmp\accesslist.csv

長くなってしまったので、レジストリとActive Directoryについては次回で。

すぐに試してみた方は、PowerShellのコンソールで、「CD HKLM:」または「CD AD:」と入力してから Get-ACLしてみてください。感動すると思います。