グループポリシーとレジストリ

当記事はシステムに対する重要な設定変更を含みます。試してみる場合はくれぐれもご注意の上、自己責任にてお願いいたします。

f:id:cw_owashi:20150329215355p:plain

Infrastructure as a Code

クロスワープの大鷲です。

皆様、日々、息をするかのようにサーバーのセットアップをこなされているかと思います。
昨今は Infrastructure as a Code という概念が主流ですね。
MODD 開発チームでも徐々に取り組みを強化しているところです。

構成をコード化する上で障害となるのが、GUI でしか設定できない項目です。
Windows は GUI が豊富でわかりやすいのは利点ですが、自動化に際しては欠点ともなり得ます。

ところで Windows では、グループ ポリシーというツールを利用して、マシンの様々な設定を行うことができます。
ポリシーはローカル マシンのみならず、Active Directory ドメインを通じて配布することができ、集中管理することができます。
一昔前であれば、集中管理は美徳だったのですが、現代ではどうでしょうか。
Infrastructure as a Code を実践する立場としては、コードで表されたマシン構成と、AD によって管理されたポリシーの 2 箇所に、構成が分散しているとも言えます。
できれば、AD によるポリシー管理は行わず、同等のことを、各マシンについてスクリプトで自動化したいと思います*1

グループ ポリシーによって行うのと同等の構成を、どうにか、グループ ポリシー エディタを使わずにできないものでしょうか。
というのが本日のお題です。

「管理用テンプレート」の実体

グループ ポリシー エディタには多くの機能がありますが、中でも「管理用テンプレート」という項目は、設定値をレジストリに保存しています。
レジストリを操作する方法は沢山あります。コンソールアプリの reg.exe を使ってもいいし、PowerShell で読み書きすることもできます。
ポリシーに対応するレジストリの場所がどこなのかわかってしまえば、あとはスクリプト化することができます。
というわけで、グループ ポリシーとレジストリの対応を暴く方法をご紹介しましょう。

今回はサンプルとして、グループ ポリシーの、[コンピューターの構成] > [管理用テンプレート] > [システム] の中にある [シャットダウン イベントの追跡ツールを表示する] という項目を例にします。
サーバーを再起動するときにいちいち聞いてくるなよ! と思ったことのないサーバー管理者はいないであろう、アレを無効にする方法です*2

f:id:cw_owashi:20150329213409p:plain

ADMX と ADML

グループ ポリシーとレジストリの対応は、C:\Windows\PolicyDefinitions ディレクトリ以下にある、*.admx という XML 形式のファイルに書かれています。
というわけで、テキスト エディタを立ち上げて、このディレクトリ以下を検索しましょう。検索ワードは「シャットダウン イベントの追跡ツールを表示する」です。

見つかりましたでしょうか?
C:\Windows\PolicyDefinitions\ja-JP\Reliability.adml というファイルに書かれているはずです。
これは、レジストリの場所が書かれた ADMX ファイルではありません。ADML の L は Language だか Locale だか…ともかく、日本語のメッセージが書かれているだけのファイルです。
言語固有のメッセージは言語ごとの ADML ファイルに分離することで、ADMX ファイルは言語から中立になっているというわけです。

f:id:cw_owashi:20150329214212p:plain

ADML ファイルは、表示メッセージの ID と、実際のメッセージを対応付けています。
「シャットダウン イベントの追跡ツールを表示する」というメッセージに対応する ID は、直前に書いてある「ShutdownReason」です。
これが言語中立な ADMX のどこかに書いてあるはずなので、改めて、C:\Windows\PolicyDefinitions 以下を「ShutdownReason」で検索しましょう*3

Reliability.admx というファイル中で見つかるはずです。

f:id:cw_owashi:20150329214611p:plain

このポリシーに関する部分を抜粋してみましょう。

<policy name="ShutdownReason" class="Machine"
  displayName="$(string.ShutdownReason)" explainText="$(string.ShutdownReason_Help)" presentation="$(presentation.ShutdownReason)"
  key="Software\Policies\Microsoft\Windows NT\Reliability" valueName="ShutdownReasonOn">
  <parentCategory ref="windows:System" />
  <supportedOn ref="windows:SUPPORTED_WindowsXP" />
  <enabledValue>
    <decimal value="1" />
  </enabledValue>
  <disabledValue>
    <decimal value="0" />
  </disabledValue>
  <elements>
    <enum id="ShutdownReason_Box" valueName="ShutdownReasonUI" required="true">
      <item displayName="$(string.ShutdownReason_Always)">
        <value>
          <decimal value="1" />
        </value>
      </item>
      <item displayName="$(string.ShutdownReason_WkstnOnly)">
        <value>
          <decimal value="2" />
        </value>
      </item>
      <item displayName="$(string.ShutdownReason_SrvOnly)">
        <value>
          <decimal value="3" />
        </value>
      </item>
    </enum>
  </elements>
</policy>

グループ ポリシー エディタと見比べれば、なんとなく意味がつかめると思います。
レジストリとの対応で最も重要なのは、policy 要素の key 属性です。
class 属性が Machine となっていますので、HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows NT\Reliability が、この設定の保存場所です。
早速レジストリ エディタで見てみましょう。
Reliability キーが存在しない場合は、グループ ポリシー エディタの設定を「未構成」以外にしてください*4。「未構成」の場合、キーが存在しません。

f:id:cw_owashi:20150329220051p:plain

policy 要素の valueName 属性が、この設定が有効か無効かを記録する値の名前になっています。この場合は ShutdownReasonOn ですね。
enabledValue が 1、disabledValue が 0 ですから、有効ならば 1、無効ならば 0 です。
そして、有効にした場合は、さらに詳細な設定を行うことができ、それが elements 要素によって表されています。
このポリシーの場合、設定項目は 1 つのみで、以下のようになっています。

選択肢 ShutdownReasonUI の値
常に表示する 1
ワークステーションのみ 2
サーバーのみ 3

試してみましょう。
グループ ポリシー エディタで、この設定を「有効」にします。さらに選択肢を「常に表示する」にしましょう。
レジストリ エディタの表示を更新すると、ShutdownReasonOn と ShutdownReasonUI の両方が「1」になりましたか?
では、グループ ポリシー エディタの方を「未構成」に戻して、Reliability キーが削除されたことを確認してから、今度はレジストリ エディタを使って、手動で同じ状態にしてみましょう*5
この状態でコンピューターをシャットダウンしようとすると、Windows 8 等のクライアント OS でも、シャットダウン イベントの追跡ツールが表示されるはずです。
もちろん、ShutdownReasonOn を 0 にすれば、サーバー OS でも表示しない設定になります。

このように ADMX ファイルによってレジストリを編集できるということは、標準でグループ ポリシーに含まれない項目に関しても、自分で ADMX ファイルを作ってやれば、グループ ポリシーを通じて操作できるということでもあります。
実際、マイクロソフトからも、Office を管理するための ADMX ファイルが配布されています*6
もちろん、Active Directory による管理も可能です。
まぁ、冒頭で、グループ ポリシー使いたくないと言ったばかりですし、やろうとは思いませんが。

注意事項

レジストリの値を直接変更しても、グループ ポリシー エディタの方は連動して変更されません。
これは、グループ ポリシー エディタが厳密には「グループ ポリシー オブジェクト (GPO)」というのを読み書きしているためだと思われます。
GPO の変更はレジストリに反映されますが、レジストリに対して直接行った変更が、逆に GPO に反映されることはないようです。

グループ ポリシー エディタの左ツリーので最上位の「ローカル コンピューター ポリシー」を右クリックして「プロパティ」を見てみましょう。
グループポリシーのどこかの設定を変えるたびに、修正時刻とリビジョンの値が更新されますが、これらはレジストリに記録されていません*7
GPO の実体は、レジストリの別の場所*8と、ファイル*9だと思われます。

f:id:cw_owashi:20150329222230p:plain

もし AD でポリシーを管理している場合、ローカルでの変更は GPO の値で上書きされてしまいますのでご注意ください。
今回、AD に属していない Windows 8 マシンで実験してみたところ、ローカル グループ ポリシー エディタで「未構成」になっていても、レジストリ上で直接変更した値が勝手に消えてしまうことはありませんでした。

それと最後にもう一度。実験のために変更した値は、元に戻しておくことをお忘れなく。

*1:もっと過激なことを言ってしまえば、AD に参加させたくもないのです。

*2:当記事はシャットダウン イベントの追跡ツールを無効化することを推奨するものではありません。

*3:ja-JP ディレクトリを検索しなように注意してください。

*4:実験用に変更する場合、後で元に戻すのを忘れないでくださいね。

*5:未構成に戻す前に、レジストリ エディタでキーをエクスポートしておくと簡単ですね。

*6:Download 2007 Office system 管理用テンプレート ファイル (ADM、ADMX、ADML) および Office カスタマイズ ツール バージョン 2.0 from Official Microsoft Download Center

*7:少なくとも HKEY_LOCAL_MACHINE\Software\Policies 以下にはそれらしいものが見当たりません。

*8:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy

*9:C:\Windows\System32\GroupPolicy