tech.guitarrapc.cóm

Technical updates

NTFS の ACL (アクセス許可) をPowerShell DSC で制御しよう

Windowsにおいて、特定のフォルダのアクセス制御をするのはいくつか手段があります。

原則としては *nux系と同様、ファイルシステム(NTFS) のアクセス許可 (ACL) を制御するのが楽でしょう。

今回は、NFTSのアクセス許可という刺身タンポポを卒業しようというおすすめです。

NFTS のアクセス許可とは

Microsoft TechNetと @ITの説明がわかりやすいでしょう。

https://technet.microsoft.com/ja-jp/library/cc771375.aspx

https://www.atmarkit.co.jp/ait/articles/1407/17/news130.html

Windowsで制御したい対象のフォルダ/ファイルのプロパティ > セキュリティ > 詳細をみてみてください。次のような画面になります。

Permissions一覧が、そのフォルダやファイルのNTFS制御を示しています。このアクセス許可の一覧をアクセスコントロールリスト (ACL) と称します。(https://msdn.microsoft.com/ja-jp/library/Windows/desktop/aa374872(v=vs.85).aspx)

Inherit (日本語OSなら 継承) は、上位フォルダからそのアクセス許可を継承しているかどうかです。

対象のアクセス許可を上位から継承していない場合は、Noneとして継承がないことが明示されます。(これが明示的なアクセス許可です)

ACLの制御

アクセス許可とその一覧は、各フォルダ/ファイルに設定していると、個別にユーザー/グループでの許可/拒否指定が必要になりすぐにカオスになります。

そのため、極力シンプルに保つには「上位フォルダでアクセス許可を設定して下位フォルダはACLを継承」することが大事です。

しかし、ACL制御にはいくつかの問題があります。

  • アクセス許可の不透明さ
  • 個別設定の手間
  • 設定時の影響

問題を順に見ていきましょう。

アクセス許可状態の不透明さ

どこに何が設定されたのか、設定が不透明になりやすいことです。

たとえば、D:\HogeとD:\FugaそれぞれがどんなACLを持っているのかをTechNetで調べても、その設定変更点をフォルダを横断してみる方法には言及がありません。

https://technet.microsoft.com/ja-jp/library/cc771586.aspx

なかには3rd Partyに簡易GUIとExcelでACL一覧をみるというのもあるぐらいで..。

https://www.teppi.com/acldump/

ACLのcsv書き出し程度ならワンライナーで書いてもいいんすが、求めるのは変更状態の透明性であって使い心地は良くないでしょう。

Get-ChildItem <対象のパス> -Recurse | Get-ACL |Export-Csv <書き出し先パス> -Encoding Default

個別設定の手間

設定したいフォルダを個別にプロパティ > セキュリティ > 詳細とやっていく作業を、100フォルダに行いたいでしょうか?

サーバーを作りなおすたびに、サーバーのACLを都度設定したいでしょうか?

こういった各フォルダにACLを設定していくだけの作業は、「決まり決まった手順」でありプログラム化です。こんなことは人のやることではないと考えます。

設定時の影響

最大の問題はこれです。ファイル数が10000程度だったり、共有アクセスがないフォルダなら対した影響はありません。

しかしNASや実行ファイルがあるフォルダ(かつファイルを排他的にロックする場合) は、アクセス許可を変更した際に操作中のファイルへの処理が拒否されます。

ACL を PowerShell DSC で制御する

*nuxでもchmodeを使ったACL操作を、Chefで自動化するように、WindowsでもPowerShell DSCでACL制御の自動化が可能です。これにより、先ほどの問題がある程度解消します。

今回必要があって、NTFSのアクセス許可の継承を制御するDSC Resourceを作成しました。以前からACLを制御するリソースは作ってあったので、これで継承もアクセス許可も制御できるようになりました。

PowerShell DSCやChefによる、Configuration Managerにアクセス許可を任せることで、先ほどの問題がどう変わるのか見てみましょう。

アクセス許可状態の不透明さ

コードで記述するため、変更箇所が透明化されます。

ただし、「アクセス許可一覧を取るのではなく変更箇所をコードで指定する」だけなため、そのフォルダにどんなACLが設定されているかは、コードからだけで読み解くのは少し違うシーンがあるでしょう。

大事なのは、「ACL一覧を知ることが目的」ではなく「ACLを適切に制御できていること」というのが基本的な考えになります。*1

個別設定の手間

CI (継続的デリバリー)環境を構築してあれば、DSCのConfigurationに落としこんでPULLモードで自動展開されます。

ACLに更新があったら、コンフィグレーションを更新してCommit > CI > Test > 展開でおしまいです。人の手がかかることなく、刺身タンポポ卒業です。

設定時の影響

ここは改善が困難な問題です。そもそもプロセスレベルでのファイルアクセス状態の制御は、副作用(プロセスやユーザーアクセス状態の変化)を伴うため好ましくないでしょう。

サービス環境で影響になることがないので、いったん見ないふり! していますが。

PowerShell DSC リソース

GitHubで公開しています。

https://github.com/guitarrapc/DSCResources

この中の、cACLとcInheritACLがACLの制御に利用するリソースです。

cACL

cInheritACL

サンプル

例えば、D:\ACLフォルダ内部で以下の構成を作ってみましょう。

C:\ACL\hoge

  • 親フォルダからのACL継承を継承する
  • アクセス許可として、everyoneユーザーをフルコントロール許可する

C:\ACL\fuga

  • 親フォルダからのACL継承を破棄する
  • 継承破棄時に、親フォルダから継承していたアクセス許可を明示的なアクセス許可として持つ

コードです。

https://gist.github.com/guitarrapc/2eead693cf7452d91193

実行してみて、

結果です。

継承を戻す

アクセス許可の継承は戻すこともできます。

とはいえ、ACLは状態が一意に定まらないパターンがあります。今回の「継承をやめる際に明示的なアクセス許可にして、再びアクセス許可の継承を行う。にACL継承設定を戻したりすると、明示的なアクセス許可が継承後も残る」が該当します。

そのため、この操作は副作用を伴うということは把握しておく必要があります。

https://gist.github.com/guitarrapc/784ef125fa433204529f

まとめ

ACLはDSCで制御しないと生きていけないですね。

cACLは必要な用途に限定しているので、まだ若干細かい操作に対応できないパターンがある気がします。PRお待ちしています。

*1:一覧が欲しいなら一覧をレポートするリソースなどを作ればいいでしょう。いらないけど。