Windows Server
 Computer >> コンピューター >  >> システム >> Windows Server

コード署名証明書でPowerShellスクリプト(PS1)に署名する方法【手順を徹底解説】

デジタル署名が付与されたスクリプトや実行ファイルは、そのファイルが本来のものであり、第三者によってコードが改ざんされていないことをユーザーが確認できるようにするためのものです。最新バージョンのPowerShellには、デジタル証明書を使用して*.ps1スクリプトファイルにコード署名を行うためのツールが標準で組み込まれています。

コード署名用証明書の種類と入手方法

PowerShellスクリプトに署名するには、「Code Signing(コード署名)」という特殊な種類の証明書が必要です。この証明書は、外部の商用認証局(CA)、社内のエンタープライズCAから入手するか、自己署名証明書を作成して利用できます。

Active Directory証明書サービスから証明書を要求する

ドメイン環境にPKIサービス(Active Directory Certificate Services)が展開されている場合は、新しい証明書を要求できます。ブラウザーで「https://CAサーバー名/certsrv」にアクセスし、「Code Signing」テンプレートを選択して証明書を要求します(事前に証明機関コンソールでCode Signingテンプレートを有効化しておく必要があります)。

また、MMCスナップインの「証明書」からも要求可能です。「個人」ストアを開き、「すべてのタスク」→「新しい証明書の要求」を選択します。

手動で証明書を要求した場合、拡張子.cerのX.509証明書ファイルが発行されます。この証明書は、コンピューターのローカル証明書ストアにインストールしておく必要があります。以下のPowerShellコマンドで、証明書をコンピューターの信頼されたルート証明機関に追加できます。

$certFile = Export-Certificate -Cert $cert -FilePath C:\ps\certname.cer
Import-Certificate -CertStoreLocation Cert:\LocalMachine\AuthRoot -FilePath $certFile.FullName

New-SelfSignedCertificateで自己署名証明書を作成する

自己署名証明書を使用する場合は、New-SelfSignedCertificateコマンドレットでCodeSigningタイプの証明書を作成します。以下はDNS名testPC1の証明書を作成する例です。

New-SelfSignedCertificate -DnsName testPC1 -Type CodeSigning
$cert = New-SelfSignedCertificate -Subject "Cert for Code Signing" -Type CodeSigningCert -DnsName test1 -CertStoreLocation cert:\LocalMachine\My

証明書の生成後は、証明書マネージャーコンソール(certmgr.msc)を使って、「中間証明機関」コンテナーから「信頼されたルート証明機関」へ証明書を移動します。

PowerShell実行ポリシーの設定

証明書を入手したら、署名済みスクリプトのみ実行を許可するよう、PowerShellのスクリプト実行ポリシーを構成します。Windows 10 / Windows Server 2016では、既定で実行ポリシーは「Restricted」(すべてのPowerShellスクリプトの実行をブロック)に設定されています。

File C:\ps\script.ps1 cannot be loaded because running scripts is disabled on this system.

署名済みPS1スクリプトのみ実行を許可するには、実行ポリシーを「AllSigned」または「RemoteSigned」に変更します。両者の違いは、RemoteSignedの場合、インターネットからダウンロードしたスクリプトにのみ署名が要求される点です。

Set-ExecutionPolicy AllSigned –Force

このモードで未署名のPowerShellスクリプトを実行すると、次のようなエラーが表示されます。

File C:\script.ps1 cannot be loaded. The file script.ps1 is not digitally signed. You cannot run this script on the current system.

グループポリシーを使って署名済みスクリプトの実行を許可することもできます。「コンピューターの構成」→「ポリシー」→「管理用テンプレート」→「Windowsコンポーネント」→「Windows PowerShell」にある「スクリプト実行を有効にする(Turn on Script Execution)」ポリシーを有効化し、値を「署名されたスクリプトのみ許可する(Allow only signed scripts)」に設定してください。

PowerShellスクリプトファイルへの署名手順

ここからは、実際にPowerShellスクリプトファイルへ署名する手順を説明します。まず、現在のユーザーのローカル証明書ストアからコード署名用証明書を取得します。最初に、コード署名に使用できる証明書の一覧を表示してみましょう。

Get-ChildItem cert:\CurrentUser\my –CodeSigningCert

今回は、ユーザーの個人証明書ストアから最初の証明書を取得し、変数$certに保存します。

$cert = (Get-ChildItem cert:\CurrentUser\my –CodeSigningCert)[0]

証明書を信頼されたルート証明書ストアに移動済みの場合は、次のコマンドを使用します。

$cert = (Get-ChildItem Cert:\LocalMachine\AuthRoot –CodeSigningCert)[0]

あとは、この証明書を使ってPS1ファイルに署名するだけです。

Set-AuthenticodeSignature -Certificate $cert -FilePath C:\PS\testscript.ps1

次のコマンドでも同様に署名できます(この例では、先ほど作成した自己署名証明書をDnsNameで指定して選択しています)。

Set-AuthenticodeSignature C:\PS\test_script.ps1 @(gci Cert:\LocalMachine\AuthRoot -DnsName testPC1 -codesigning)[0]

ヒント:Set-AuthenticodeSignatureコマンドレットには、タイムスタンプサービスのURLを指定する特別なパラメーター「TimestampServer」があります。このパラメーターを空のままにすると、証明書の有効期限が切れた後、PSスクリプトは実行できなくなります。タイムスタンプサーバーは次のように指定します。-TimestampServer "https://timestamp.verisign.com/scripts/timstamp.dll"

なお、通常のSSL/TLS証明書を使ってスクリプトに署名しようとすると、次のエラーが発生します。

Set-AuthenticodeSignature: Cannot sign code. The specified certificate is not suitable for code signing.

フォルダー内のすべてのPowerShellスクリプトファイルに一括で署名することも可能です。

Get-ChildItem c:\ps\*.ps1 | Set-AuthenticodeSignature -Certificate $Cert

署名の検証方法

PowerShellスクリプトファイルが正しく署名されているか確認しましょう。Get-AuthenticodeSignatureコマンドレットを使用するか、PS1ファイルのプロパティを開いて「デジタル署名」タブを確認します。

Get-AuthenticodeSignature c:\ps\test_script.ps1 | ft -AutoSize

Set-AuthenticodeSignatureコマンドの実行時に「UnknownError」という警告が表示される場合は、その証明書が信頼されていないことを意味します。証明書がユーザーの個人証明書ストアに置かれていることが原因です。

この場合は、証明書を「信頼されたルート証明機関」へ移動する必要があります(Windowsの証明書ストアに不審な証明書がないか定期的にチェックし、信頼されたルート証明書の一覧を更新することも忘れないでください)。

Move-Item -Path $cert.PSPath -Destination "Cert:\LocalMachine\Root"

これで、PS1ファイルの署名検証時に「Valid(有効)」ステータスが返されるようになります。

署名ブロックの仕組み

Set-AuthenticodeSignatureコマンドレットでスクリプトに署名すると、PS1テキストファイルの末尾にデジタル署名ブロックが追加されます。

# SIG # Begin signature block
...........
...........
# SIG # End signature block

この署名ブロックにはスクリプトのハッシュ値が含まれており、秘密鍵によって暗号化されています。

「信頼されていない発行元」警告への対処

初めてスクリプトを実行しようとすると、次のような警告が表示されます。

Do you want to run software from this untrusted publisher?
File C:\PS\script.ps1 is published by CN=testPC1 and is not trusted on your system. Only run scripts from trusted publishers.

ここで「[A] 常に実行する(Always run)」を選択すれば、同じ証明書で署名されたスクリプトを次回以降に実行しても、警告は表示されなくなります。

そもそもこの警告を表示させたくない場合は、証明書を「信頼された発行元(Trusted Publishers)」ストアにもコピーしておく必要があります。証明書コンソールでコピー&ペースト操作により、「信頼された発行元」→「証明書」へ証明書を複製してください。

これで、署名済みPowerShellスクリプトは、信頼されていない発行元の通知を表示せずに実行できるようになります。

補足:CAのルート証明書とスクリプト署名に使用した証明書は、信頼されている必要があります(そうでない場合、スクリプトは実行されません)。GPOを使えば、ドメイン内のコンピューターに証明書を一括配布できます。証明書はGPOの以下の公開キーポリシーセクションに配置してください。「コンピューターの構成」→「ポリシー」→「Windowsの設定」→「セキュリティの設定」→「公開キーのポリシー」→「信頼されたルート証明機関」および「信頼された発行元」。

ルート証明書が信頼されていない場合、PowerShellスクリプトの実行時に次のエラーが表示されます。

A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.

署名済みスクリプトのコードを変更した場合の挙動

署名済みのPowerShellスクリプトファイルのコードを変更するとどうなるのでしょうか? 実行がブロックされ、スクリプトの内容が変更されたことを示す通知が表示されます。

File xx.ps1 cannot be loaded. The contents of file xx.ps1 might have been changed by an unauthorized user or process, because the hash of the file does not match the hash stored in the digital signature. The script cannot run on the specified system.

Get-AuthenticodeSignatureコマンドレットでスクリプトの署名を検証してみてください。計算されたハッシュが署名内のハッシュと一致しない場合、「HashMismatch」というメッセージが表示されます。

つまり、署名済みPS1スクリプトのコードに何らかの変更を加えた場合は、必ず再署名が必要になるということです。

  1. PowerShellスクリプトに一時停止(ポーズ)を追加する方法【具体例つき】

    この記事では、PowerShellスクリプトに一時停止(ポーズ)を追加する方法を解説します。 一時停止や待機コマンドを追加する方法はいくつかあります。以下では、それぞれの方法を具体例とともにわかりやすく紹介していきます。 PowerShellスクリプトに一時停止を追加する基本の方法 最も基本的なのは、Start-Sleepコマンドレットを使う方法です。以下の手順で追加できます。 スタートメニューから「PowerShell ISE」を開きます 一時停止コマンドを追加したいPowerShellスクリプトを開きます 一時停止させたい箇所に、start-sleep -Seconds 5という行を追

  2. Windows 10/11でVisual Studio Codeを使ってPowerShellスクリプトを作成・実行する方法

    Windows 10やWindows 11でも、PowerShellスクリプトを作成できることをご存じでしょうか?WindowsにPowerShellをインストールしたら、次はPCで何ができるのか知りたくなるはずです。このガイドでは、Visual Studio Codeを使ってシンプルなスクリプトファイルを作成し、Windows 10およびWindows 11のPowerShellで実行する方法を解説します。 まずは基本的なPowerShellスクリプトの作り方を覚えましょう。これをマスターすれば、Windows 10とWindows 11の両方でスクリプトを作成・実行できるようになり、作業効