ちょっとしたきっかけから、AdmxPolicyというADMXファイルの中身を解析して各グループポリシーが使用するレジストリキーの値を取得するPowerShellモジュールを作ってみました。
ソースと基本的な使い方はGitHubに上げています。
またPowerShell Galleryでも公開しており以下のコマンドでインストール可能です。
Install-Module -Name AdmxPolicy -Scope CurrentUser
なお動作環境はPowerShell 2.0以上です。
PowerShell 2.0の環境ではReleaseにあるZipファイルを解凍してAdmxPolicy
フォルダをImport-Module
してください。
モジュールを作るきっかけ
このモジュールを作ろうと思ったきっかけはteratailのこの質問になります。
この質問で参考にして頂いているエントリに以下の様に書きましたが、各グループポリシーが取るレジストリ値を調べるのは容易ではありません。
そして各ポリシーがどの様なレジストリ値を取るのかについては、
* Group Policy Registry Reference や、
* Group Policy Settings Reference for Windows and Windows Server からダウンロードできるExcelファイルを参照することである程度わかります。
(2014/12/12追記:上記の他にポリシーのadm/admxファイルをテキストエディタ等で直接参照することでもレジストリ値の情報を知ることができます。)
そこでADMXファイルを解析するツールを作れば少しは楽ができるかなと思い作ってみました。
作った結果
現時点でこのモジュールは個々のADMXファイルを解析して各ポリシーが取りうるレジストのキーとその値を取得することができます。
ただし、各ポリシーが取りうる値は非常に多岐にわたり、このモジュールがあればグループポリシーの設定をすべて自動化できるという訳にはいきませんでした。
また、ADMXファイルに記載されているレジストリの設定情報はグループポリシーエディタのUIと非常に強く結びついており、一見しただけでは何の設定値か判別しにくい(グループポリシーエディタのUI上でみてはじめて意味が通る)ものも結構あります。
そのためコレはあくまでも補助ツールとして使うのが良いかなと思っています。
きっかけとなる問題に対して完璧なソリューションにはなりませんでしたが、それでも何もないよりはマシかなといったところです。
使用例
使用例として、実際のグループポリシーの設定とこのモジュールの結果を突き合わせてみます。
0. 試験環境について
適当なドメインcontoso.local
に設定したポリシーTextPolicy
を例にします。
このTestPolicy
ではコマンド プロンプトにアクセスできないようにする
ポリシーを有効に設定しておきます。
1. ポリシーの検索
まずはコマンド プロンプトにアクセスできないようにする
ポリシーを検索する必要があります。
ADMXファイルがインストールされているディレクトリ(ここではセントラルストア)のADMXファイルを対象に以下の様にポリシーを検索します。
$admxPath = "C:\Windows\SYSVOL\domain\Policies\PolicyDefinitions\*.admx" ls $admxPath | Get-AdmxPolicies | ? { $_.DisplayName -like "*コマンド プロンプト*" }
ちょっと時間がかかりますが、結果はこんな感じになり、Shell-CommandPrompt-RegEditTools.admx
にあるDisableCMD
というポリシーであることがわかります。
2. ポリシーの取得
該当のポリシーがわかったのでポリシー情報を取得してみます。
$admxPath = "C:\Windows\SYSVOL\domain\Policies\PolicyDefinitions\Shell-CommandPrompt-RegEditTools.admx" $policy = Get-AdmxPolicies -FilePath $admxPath | ? { $_.Name -eq "DisableCMD" }
取得した結果はこんな感じになります。
この結果のRegistryType
、RegistryRootKeys
、RegistryPath
プロパティからレジストリのキー情報を取得することができます。
$policy.RegistryType # マシンポリシー、ユーザーポリシー、その両方かの種別 $policy.RegistryRootKeys # RegistryTypeに応じたルートキー $policy.RegistryPath # レジストリのサブキー
結果、このポリシーはHKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\System
キーを使うことがわかります。
次に、レジストリ値についてはValueInfo
プロパティから取得可能です。
$policy.ValueInfo # レジストリ値情報
ここからが厄介なところで、ADMXファイルで定義されるレジストリ値は大きく3パターンに分類されます。
- 単純なEnabled/Disabled値
- RegistryValueName、EnabledValue、DisabledValue
- Enabled/Disabledのリストを取るEnabledList/DisabledList
- HasEnabledList、EnabledList、HasDisabledList、DisabledList
- グループポリシーエディタのUIと紐づく値となるElement値
- HasElements、Elements
今回のポリシーは3.のElement値だけをもっています。*1
ですので、このElement
にアクセスしてみると以下の様な情報を得ることができます。
この結果はElementの中の列挙体であるEnumElement
で、レジストリ値がDisableCMD
、取りうる値が1
または2
であることを示しています。
Key
のはい
、いいえ
についてはグループポリシーエディタのコンボボックスに表示される名称になり、こういったところがぱっと見でわからない感じになっています…
ちなみに、Element
はEnumElementを含めて
- BooleanElement
- DecimalElement
- LongDecimalElement
- TextElement
- MultiTextElement
- EnumElement
- ListElement
の7種類存在します。
これらの詳細はADMX Policy Definition Schemaに定義されています。
本エントリでは個々の詳細まで触れませんが、実際に見ればそれなりに予測はつくかと思います。
これで情報は全て集まり、
- キー :
HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\System
- 値 :
DisableCMD
- 設定値 :
1
または2
であることがわかりました。
3. 実際のポリシーと付け合わせる
前項の結果が正しければGet-GPRegistryValue
コマンドで値を取得できるはずです。
実際に確認してみます。
Get-GPRegistryValue -Name TestPolicy -Key HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\System
結果は以下の様になりAdmxPolicyモジュールで得た情報と合っていることがわかります。
補足 : POLファイルを解析する
AdmxPolicyモジュールではテンプレートであるADMXファイルの情報からレジストリ値を探しましたが、補足として、実際のポリシー定義の情報であるPOLファイルからレジストリ情報を取得する方法について説明します。
GPRegistryPolicyParser
PowerShell Teamが公式にグループポリシーのPOLファイルを解析するモジュールGPRegistryPolicyParser
を提供しているのでこれを使います。
このモジュールは、もともと、Nano Serverに対してグループポリシーを適用する・情報を取得することを目的としている様でPowerShell 5.0以上でないと動作しませんので注意してください。
POLファイルはSYSVOLなどから直接取得しても構いませんが、安全のためにBackup-GPO
コマンドでとったバックアップから抜くなどした方が良いでしょう。
本エントリではその辺の手順は端折りますが、取得したPOLファイルに対して以下のコマンドを実行するとPOLファイルの中身を見ることができます。
Parse-PolFile -Path [POLファイルのパス]
実行例)
テスト用のポリシーを自由に作れる環境であればこちらを使う方が楽ができるでしょう。
最後に
とりあえずこんな感じです。
グループポリシーで使うレジストリ値の取得は一筋縄ではいきませんが、AdmxPolicy、GPRegistryPolicyParserといったツールを使うことで多少は楽ができるかと思います。
*1:なお、これらのパターンはどれか一つというわけではなく組み合わせで設定されます…