あなたは PowerShell スクリプトをダウンロードし、それを実行して以下の悪名高いエラーメッセージに遭遇したことがありますか?そうであれば、Set-ExecutionPolicy コマンドレットとこのチュートリアルが必要です!

この投稿では、PowerShell の実行ポリシーとそれを管理するための Set-ExecutionPolicy コマンドレットについて学びます。この投稿の終わりまでに、スクリプトの実行方法だけでなく、実行ポリシーの使用方法も理解できるようになるでしょう!
このチュートリアルは Windows PowerShell を対象に書かれており、すべてのデモンストレーションは Windows PowerShell で実行されています。実行ポリシーは Windows PowerShell に固有のものではなく、PowerShell 6+ でも非常に似たような動作をします。ただし、PowerShell 6+ を使用している場合は、動作にわずかな違いがあるかもしれません。
実行ポリシーとは何ですか?
上記で説明されたエラーに遭遇したことがあれば、実行ポリシーに遭遇したことになります。PowerShell の実行ポリシーは、悪意のあるスクリプトの実行からシステムを保護するためのセキュリティメカニズムです。実行ポリシーは、コンソールとしての PowerShell コードの実行を防ぐのではなく、スクリプトの実行を制限します。
Microsoft によれば、実行ポリシーは厳密には「セキュリティ」対策ではなく、開閉可能なゲートのようなものです。なぜなら、定義された実行ポリシーを簡単にバイパスできる方法を後で学ぶからです。
実行ポリシーは信頼に基づいています。スクリプトを信頼できる場合、それは悪意のあるものではない可能性があります。実行ポリシーは通常、すべてのスクリプトの実行を防止しません。その主な目的(特に厳密に設定された場合)は、実行しているスクリプトが証明書で暗号化されていることを信頼することです。
実行ポリシーのスコープ
実行ポリシーはスクリプトの実行を制限しますが、PowerShellは多くの異なるコンテキストでスクリプトを実行することができます。PowerShellはユーザーがログインしているコンテキストまたはグローバルマシンコンテキスト、SYSTEMとして実行されるスケジュールされたタスク、または単一のオープンされたPowerShellコンソールのスコープ内でスクリプトを実行します。
これらすべてのコンテキストに対応するために、PowerShellには5つの異なるコンテキストまたはスコープがあり、実行ポリシーを定義することができます。
- MachinePolicy – このスコープは単一のコンピューターに限定されています。そのコンピューターにログインするすべてのユーザーに影響を与え、Active Directoryのグループポリシーオブジェクトで設定されます。定義されている場合、他のすべてのスコープより優先されます。
- LocalMachine。これは、すべてのコンピュータユーザーに影響を与えるデフォルトのスコープであり、HKEY_LOCAL_MACHINEレジストリのサブキーに保存されます。
Set-ExecutionPolicy
を使用して実行ポリシーを設定する場合、このスコープがデフォルトになります。
LocalMachineの実行ポリシーは、レジストリキーHKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShellに保存されます。
- UserPolicy – UserPolicyスコープは、コンピューター上の単一のユーザーにのみ影響を与え、Active Directoryグループポリシーオブジェクトで設定されます。
Set-ExecutionPolicy
ではこのポリシーを変更することはできません。 - CurrentUser。 CurrentUserポリシースコープは、現在のユーザーに対してのみ実行ポリシーを設定し、HKEY_CURRENT_USERレジストリハイブに保存されます。
Set-ExecutionPolicy
ではこのポリシーを変更することはできません。
CurrentUserの実行ポリシーは、レジストリキーHKEY_CURRENT_USER\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShellに保存されます。
- Process – このスコープは、単一のユーザーの単一のPowerShellセッションの実行ポリシーを定義します。 Process実行ポリシースコープは、定義できる最も細かい実行ポリシーです。他の実行ポリシーとは異なり、このポリシーはレジストリではなく、
PSExecutionPolicyPreference
という環境変数に保存されます。
実行ポリシータイプ
実行ポリシーにはさまざまな「セキュリティレベル」があります。これらのレベルは、実行ポリシーの厳格さを規定します。たとえば、何もしない実行ポリシーを設定することができます。無効化されていますが、一方で、実行ポリシーはスクリプトの実行を完全に無効化することもあります。
最も緩やかなセキュリティレベルから最も制限のあるレベルまで、実行ポリシーのセキュリティレベルを設定する方法について説明しましょう。
制限なし
最も制限のないポリシーは、何も影響を与えないものです。これが「制限なし」です。制限なしの実行ポリシーは、基本的には無効化されています。実行ポリシーが制限なしの場合、ユーザーは信頼性に関係なくすべてのスクリプトを実行できます。
バイパス
制限なしタイプと同様に、バイパスに設定された実行ポリシーは何もブロックしません。
ただし、バイパス実行ポリシータイプは、厳密にはタイプではありません。定義された実行ポリシーを完全にスキップします。
未定義
あまり一般的ではありませんが、実行ポリシーを未定義に設定することで、実行ポリシーを実質的に削除することができます。実行ポリシーを未定義に設定すると、PowerShellは割り当てられたスコープからすべての実行ポリシーを完全に削除します。
非Windowsコンピュータでは、実行ポリシーは常に制限なしに設定されており、変更することはできません。
すべてのスコープが未定義に設定されている場合、PowerShellはすべてのスコープを制限されたものとして扱います。
RemoteSigned
前述の通り、実行ポリシーはスクリプトのデジタル署名によって得られた信頼に関するものです。PowerShellは、そのスクリプトの出所も考慮しています。それは、ローカルコンピュータで作成されたものなのか、インターネット上のランダムな人物によって作成されたものなのかを意味します。
ローカルコンピュータ以外で作成されたスクリプトには、基本的な信頼は置かれません。これがPowerShellが提供するRemoteSigned実行ポリシーです。RemoteSigned実行ポリシーは、すべてのスクリプトがローカルコンピュータ以外の場所で作成され、暗号化されていることを強制します。
インターネットからダウンロードされたファイルに対して、この実行ポリシーを一部回避することもできます。
Unblock-File
コマンドレットを使用してください。この動作に関する詳細情報は、後の「RemoteSignedポリシーの動作方法」セクションで説明します。
Windows Serverでは、デフォルトのポリシーとしてRemoteSignedが割り当てられています。
AllSigned
すべてのPowerShellスクリプトに暗号化署名が必要であることを確認したい場合は、実行ポリシーをAllSignedに設定してください。 RemoteSignedと同様に、この実行ポリシーはスクリプトの実行前に署名が必要です。
実行ポリシーがAllSignedに設定されている場合でも、後で説明するように、実行ポリシーを回避することはできます。
Restricted
最も制限の厳しい実行ポリシーは制限されたです。実行ポリシーが制限された場合、信頼されたかどうかに関わらず、スクリプトは一切実行されません。このポリシーはスクリプトの実行を完全に無効にします。
また、他の制限の緩いタイプとは異なり、制限されたタイプではPowerShellのフォーマットと設定ファイル(PS1XML)、モジュールスクリプトファイル(PSM1)、PowerShellプロファイルを実行できません。
デフォルトでは、すべてのWindowsクライアントは制限された実行ポリシーに設定されています。
技術的には、MicrosoftはDefaultという7番目の実行ポリシーを定義していますが、このタイプは実質的にはRemoteSigned(Windows Server)と制限された(Windowsクライアント)の別名です。
RemoteSignedポリシーの動作方法
特定のシナリオを指摘するために、RemoteSigned実行ポリシーの動作方法について説明します。この実行ポリシーは、ローカルコンピュータ以外で作成されたスクリプトの実行を防止する(学んだ通り)
しかし、PowerShellはどのようにしてスクリプトが他の場所で作成されたものであることを知るのでしょうか?データストリームです。
NTFSデータストリームの理解とクエリ
NTFSファイルシステム上でファイルを作成すると、NTFSはファイルに代替データストリーム(ADS)属性を適用します。ADSには2つのファイル属性、$Dataとzone.Identifierがあります。PowerShellはzone.Identifier属性を使用して、PowerShellスクリプトファイルが他の場所で作成されたかどうかを識別します。
他の属性(CompressedやRead Onlyなど)とは異なり、ADS属性はファイルエクスプローラーでは非表示になっています。ただし、PowerShellを使用することで、これらのデータストリームを調査することができます。
以下のように、スクリプトへのパスとStream
パラメータを指定して、Get-Item
コマンドレットを実行します。この例では、Hello World.ps1がローカルコンピュータに作成されました。Stream
プロパティに割り当てられた属性は$DATA
のみです。ADS属性はありません。

次に、インターネットからダウンロードしたスクリプトに対して同じコマンドを実行します。すると、今度はGet-Item
が別のオブジェクトを返し、Stream
はZone.Identifier
です。

ファイルにADSがあることがわかったら、Get-Content
コマンドを使用してゾーンを調べることができます。ゾーンはファイルの出所を定義します。
Get-Content
はZoneId
値を返します。これはファイルの出所を表します。

可能なゾーンの値は以下の通りです:
実行ポリシーの優先順位
前述の通り、さまざまな実行ポリシーが同時に存在します。これらの実行ポリシーは組み合わさることによって、現在のセッションの設定を決定します。複数の実行ポリシーが有効な場合、優先順位が必要です。
ポリシーの優先順位は、PowerShellがさまざまなスコープで設定された異なるポリシーを適用する順序です。一部の実行ポリシーは他のものよりも優先度が高いです。
Get-ExecutionPolicy -List
を実行すると、現在有効なすべての実行ポリシーが優先度の低い順に表示されます。たとえば、MachinePolicyは優先度が低いため、LocalMachineおよびCurrentUserのポリシーが優先されます。

実行ポリシーの操作
実行ポリシーの操作には、Get-ExecutionPolicy
コマンドを使用して現在定義されているポリシーを確認することと、Set-ExecutionPolicy
コマンドを使用して新しいポリシーを設定することの2つのコマンドがあります。
現在割り当てられているポリシーの取得
実行ポリシーを変更する前に、作業する内容を把握する必要があります。そのためには、Get-ExecutionPolicy
コマンドを使用します。このコマンドは、コンピュータ上に現在割り当てられているすべてのポリシーを列挙します。
Get-ExecutionPolicy
コマンドをパラメータなしで直接PowerShellコンソールで実行すると、現在のPowerShellセッションに設定されている実行ポリシーが表示されます。

スコープに設定されている実行ポリシーを表示するには、Scope
パラメータを使用し、結果を表示したいスコープ名を指定します。

すべてのスコープとその実行ポリシーを表示するには、以下に示すようにList
パラメータを使用します。

実行ポリシーの変更
現在割り当てられている実行ポリシーを知ると、それらを変更することもできます。単一のコンピューターでポリシーを変更するには、Set-ExecutionPolicy
コマンドを使用します。ただし、組織内でポリシーを一括変更する場合は、Active Directoryドメインにいる場合は常にグループポリシーを使用できます。
Set-ExecutionPolicy
を使用する
まず、管理者としてPowerShellを開きます。
次に、Set-ExecutionPolicy
コマンドを単一のパラメーター(ExecutionPolicy
)と共に実行します。実行ポリシーの名前を指定します。PowerShellは実行ポリシーを変更するかどうかを確認します。変更する場合は、YまたはAを入力し、

上記の例でY
を入力すると、PowerShellは各ステップについて続行するかどうかを確認するプロンプトを表示する場合があります。 A
を押すと、すべての後続のステップに対して続行します。
プロンプトなしでSet-ExecutionPolicy
を実行する
デフォルトでは、Set-ExecutionPolicy
を実行すると、実行ポリシーを変更するかどうか尋ねられます。コマンドにForce
パラメータを追加することで、このプロンプトをスキップすることができます。Force
パラメータを使用すると、確認プロンプトがすべて抑制されます。

レジストリを介してPowerShellの実行ポリシーを設定する
ほとんどの実行ポリシーはレジストリに保存されています(Processを除く)。したがって、レジストリを直接変更することで実行ポリシーを変更することもできます。
レジストリを介して実行ポリシーを変更するには:
- Windowsレジストリエディター(regedit)または選択したレジストリ編集ツールを開きます。
2. 変更したい実行ポリシーのスコープのレジストリキーに移動します。
LocalMachine – HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell
CurrentUser – HKEY_CURRENT_USER\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell
3. レジストリキーを右クリックし、ExecutionPolicyという新しい文字列値を作成します。
4. 新しく作成したExecutionPolicy文字列値をダブルクリックし、実行ポリシーの名前(Restricted、RemoteSigned、AllSigned、Unrestricted、またはUndefined)を入力します。
5. 同じキーに別の文字列値を作成し、Pathと呼びます。 Pathの文字列値はPowerShellエンジンへのパスを表します。 Pathの値は、Windows PowerShellエンジンを指すC:\Windows\System32\WindowsPowerShell\v1.0\powershell.exeになるようにしてください。

CurrentUserの実行ポリシーは、LocalMachineのポリシーを上書きします。レジストリにCurrentUserポリシーが設定されており、Set-ExecutionPolicy
を使用して実行ポリシーを変更しようとすると、デフォルトではポリシーはLocalMachineのスコープに設定されますが、PowerShellは以下のエラーを返します。

グループポリシーを使用してPowerShell実行ポリシーを設定する
Active Directoryを使用する組織の場合、すべてのWindowsマシンに回り、Set-ExecutionPolicy
コマンドレットを実行する必要はありません。代わりに、グループポリシーで一括管理することができます。
グループポリシーを使用して実行ポリシーを管理するには:
グループポリシーオブジェクトを作成する
- ドメインコントローラーまたはドメインに参加しているワークステーションで、グループポリシーマネージメントアプリケーションを開きます。

2. ドメイン —> Active Directoryのフォレスト —> グループポリシーオブジェクトを展開します。

3. グループポリシーオブジェクトを右クリックし、新規をクリックします。
4. GPOに名前を付けてください。このチュートリアルでは、GPOの名前は「PowerShell実行ポリシー」とします。

5. 新しく作成したGPOを右クリックし、「編集」をクリックしてください。
6. 「コンピュータの構成」→「ポリシー」→「管理用テンプレート」→「Windowsコンポーネント」→「Windows PowerShell」に移動してください。

7. 右ウィンドウペインの設定を開き、「スクリプトの実行を許可する」設定を開いてください。

8. 「スクリプトの実行を許可する」ボックスで、「有効」オプションを選択してください。以下に表示されるオプションのいずれかを選択できます:
9. 今、望むポリシーに実行ポリシーを変更してください。
- 署名されたスクリプトのみ許可 – 信頼できるパブリッシャーが署名したスクリプトのみを実行できます。
- ローカルスクリプトとリモート署名スクリプトを許可 – ローカルスクリプトは実行できますが、インターネットからダウンロードしたスクリプトは信頼できるパブリッシャーによって署名されている必要があります。
- すべてのスクリプトを許可 – すべてのスクリプトを実行できます。

グループポリシーオブジェクトを割り当てる
GPOが作成されたら、それを対象のコンピュータに割り当てる時が来ました。そのためには、GPOをActive Directoryの組織単位(OU)に割り当てる必要があります。
新しいGPOを作成する代わりに既存のGPOを編集した場合、そのGPOは既にOUに割り当てられている可能性があります。
- グループポリシー管理で、ドメイン —> <ご使用のActive Directoryフォレスト> —> <お好きなOU>に移動します。
2. OUを右クリックし、既存のGPOをリンクする…を選択します。

3. 作成したGPO(PowerShell実行ポリシー)を選択し、OKをクリックします。

以下のように、OUに割り当てられたGPOが表示されます。

この時点で、定義されたグループポリシーの更新間隔を待つか、対象のコンピュータでgpupdateコマンドを実行して更新を強制することができます。
ローカルポリシーの変更をロックする
実行ポリシーを変更するGPOが有効になると、ローカルユーザーはローカルのPowerShellコンソールを介してポリシーを変更できなくなります。試みると、以下のようなエラーが表示されます。

実行ポリシーを完全にバイパスする
先述のように、実行ポリシーは必ずしもセキュリティ対策として意図されたものではありません。なぜなら、いくつかの方法で完全にバイパスすることができるからです。
-ExecutionPolicy Bypass
パラメータを使用する
他の実行ポリシーとは異なり、Bypassポリシーは通常、PowerShellコンソールではなくpowershell.exeエンジン実行時に管理者として設定されます。
たとえば、実行ポリシーを完全にスキップしてHello World.ps1というスクリプトを実行するには、powershell.exeを呼び出し、Bypass
パラメータを使用し、ファイルパスを以下のように指定します。

スクリプトの読み込みと生コードの実行
また、スクリプトの内容を最初に読み込んでそれを直接PowerShellエンジンに渡すことで、実行ポリシーを回避することもできます。これにより、各コマンドが個別に実行され、一度にスクリプト全体としてではなく実行されます。
以下のように、実行ポリシーがRestrictedに設定されていますが、スクリプトを読み込んでpowershell.exeに渡すことで、それでも動作します。
このアプローチは、PowerShell ISEやVisual Studio CodeなどのPowerShellエディタでスクリプトを開き、行を選択してF8キーを押すのと似ています。

結論
これでPowerShellの実行ポリシーに関するすべてを知ることができるはずです。これらは厳密にはセキュリティ対策ではありませんが、組織のポリシーに従って組織内で管理する必要があります。