読者です 読者をやめる 読者になる 読者になる

tech.guitarrapc.cóm

C#, PowerShell, Unity, Cloud Platfrom Technical Update and Features

AWS や Azure でWindows Server 2012 英語インスタンスを日本語化して PowerShell Remoting しようとしてCode="2" で実行できない場合の対処

PowerShell valentia Windows

AWS の EC2 インスタンスには、 Windows Server 2008 R2 と Windows Server 2012 が2/10 現在利用可能です。

日本語AMIを使わない限り、EC2インスタンスがデフォルトで提供しているのが英語OSなため、日本語化して使うことが多いと思います。

しかし、何も考慮せずに日本語化して、PSRemoting (PowerShell Remoting) の有効化を試みると以下のエラーで失敗します。

Enable-PSRemoting -Force
Set-WSManQuickConfig : <f:WSManFault xmlns:f="http://schemas.microsoft.com/wbem/wsman/1/wsmanfault" Code="2" Machine="localhost"><f:Message><f:ProviderFault provider="Config provider" path="%systemroot%\system32\WsmSvc.dll"><f:WSManFault
xmlns:f="http://schemas.microsoft.com/wbem/wsman/1/wsmanfault" Code="2" Machine="ServerHostName"><f:Message>ファイアウォールの状態を確認できません。 </f:Message></f:WSManFault></f:ProviderFault></f:Message></f:WSManFault>
発生場所 行:69 文字:17
+                 Set-WSManQuickConfig -force
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Set-WSManQuickConfig]、InvalidOperationException
    + FullyQualifiedErrorId : WsManError,Microsoft.WSMan.Management.SetWSManQuickConfigCommand

一方で、英語OSのままなら発生しません。

WinRM is already set up to receive requests on this computer.
WinRM is already set up for remote management on this computer.

今回は日本語OSで発生するエラーへの対応です。

目次

他の方の記事

このエラーコード2 に関して、世界を探しても記事が全然ありません。 しかし、いい記事があります。

ここにある通り、原因は4. WS-Management トラフィック用の Windows ファイアウォールの受信規則の例外を有効にします (HTTP のみ)。 で、対象とするファイアウォール規則名を見つけられないために起こります。

英語の場合:

WARNING: Disabling the session configurations does not undo all the changes made by the Enable-PSRemoting or
Enable-PSSessionConfiguration cmdlet. You might have to manually undo the changes by following these steps:
    1. Stop and disable the WinRM service.
    2. Delete the listener that accepts requests on any IP address.
    3. Disable the firewall exceptions for WS-Management communications.
    4. Restore the value of the LocalAccountTokenFilterPolicy to 0, which restricts remote access to members of theAdministrators group on the computer.

日本語の場合:

WinRM クイック構成
Windows リモート管理 (WinRM) サービスを使用して、このコンピューターのリモート管理を有効にするコマンド
"Set-WSManQuickConfig" を実行します。
 これには、次の処理が含まれます:
    1. WinRM サービスを開始または (既に開始されている場合は) 再起動します。
    2. WinRM サービスのスタートアップの種類を [自動] に設定します。
    3. どの IP アドレスでも要求を受け付けるリスナーを作成します。
    4. WS-Management トラフィック用の Windows ファイアウォールの受信規則の例外を有効にします (HTTP のみ)。

発生原因

これは Amazonというより、Windows の日本語言語パック適用自体が不完全なためです。

ただし条件があり、英語OSの時点で Enable-PSRemoting を一度でも行ってあれば発生しません。*1この場合は、日本語言語パック適用時に適切に変換されます。

一方で、英語OSの時点で実施せず、日本語言語パックを適用、システムロケールが日本語だと発生します。

また、最初から日本語のインスタンス == Windows Server 2012 日本語版 では起こりません。

対処

記事にもある通りですが、すべてのプロファイルWindows リモート管理 (HTTP 受信)TCP 5985許可 で作成すれば大丈夫です。

この時、上記の問題が起こると自分のプロファイルが プライベートだからといって、プライベートだけではだめで、必ずすべてのプロファイルで作成しないと WinRMが規則を見つけられないため気を付けてください。

真ん中の、プロファイルがすべて の規則が重要です。

f:id:guitarrapc_tech:20140210204230p:plain

正常な場合は ドメイン、プライベートパブリックでわかれているのですが、一度でもエラーにあうと、はい、残念。

コード

ということで、さくっとコードで追加しましょう。

これは valentia の Initialize-ValentiaEnvironment で呼び出しているファンクションにあります。

#Requires -Version 3.0

#-- Prerequisite OS Setting Module Functions --#

function New-ValentiaPSRemotingFirewallRule
{

<#

.SYNOPSIS 
Create New Firewall Rule for PowerShell Remoting

.DESCRIPTION
Will allow PowerShell Remoting port for firewall

.NOTES
Author: guitarrapc
Created: 18/Jul/2013

.EXAMPLE
Enable-PSRemotingFirewallRule
--------------------------------------------
Add PowerShellRemoting-In accessible rule to Firewall.

#>


    [CmdletBinding()]
    param
    (
        [Parameter(
            Position = 0,
            Mandatory = 0,
            HelpMessage = "Input PowerShellRemoting-In port. default is 5985")]
        [int]
        $PSRemotePort = 5985,

        [Parameter(
            Position = 1,
            Mandatory = 0,
            HelpMessage = "Input Name of Firewall rule for PowerShellRemoting-In.")]
        [string]
        $Name = "PowerShellRemoting-In",

        [Parameter(
            Position = 2,
            Mandatory = 0,
            HelpMessage = "Input Decription of Firewall rule for PowerShellRemoting-In.")]
        [string]
        $Description = "Windows PowerShell Remoting required to open for public connection. not for private network.",

        [Parameter(
            Position = 2,
            Mandatory = 0,
            HelpMessage = "Input Group of Firewall rule for PowerShellRemoting-In.")]
        [string]
        $Group = "Windows Remote Management"
    )

    if (-not((Get-NetFirewallRule | where Name -eq $Name) -and (Get-NetFirewallPortFilter -Protocol TCP | where Localport -eq $PSRemotePort)))
    {
        Write-Verbose ("Windows PowerShell Remoting port TCP $PSRemotePort was not opend. Set new rule '{1}'" -f $PSRemotePort, $Name)
        New-NetFirewallRule `
            -Name $Name `
            -DisplayName $Name `
            -Description $Description `
            -Group $Group `
            -Enabled True `
            -Profile Any `
            -Direction Inbound `
            -Action Allow `
            -EdgeTraversalPolicy Block `
            -LooseSourceMapping $False `
            -LocalOnlyMapping $False `
            -OverrideBlockRules $False `
            -Program Any `
            -LocalAddress Any `
            -RemoteAddress Any `
            -Protocol TCP `
            -LocalPort $PSRemotePort `
            -RemotePort Any `
            -LocalUser Any `
            -RemoteUser Any 
    }
    else
    {
        Write-Verbose "Windows PowerShell Remoting port TCP 5985 was alredy opened. Get Firewall Rule."
        Get-NetFirewallPortFilter -Protocol TCP | where Localport -eq 5985
    }

    if ((Get-WinSystemLocale).Name -eq "ja-JP")
    {
        $japanesePSRemoteingEnableRule = "Windows リモート管理 (HTTP 受信)"
        if (-not((Get-NetFirewallRule | where DisplayName -eq $japanesePSRemoteingEnableRule | where Profile -eq "Any") -and (Get-NetFirewallPortFilter -Protocol TCP | where Localport -eq $PSRemotePort)))
        {
            Write-Verbose ("日本語OSと検知しました。'{0}' という名称で TCP '{1}' をファイアウォールに許可します。" -f $japanesePSRemoteingEnableRule, 5985)
            New-NetFirewallRule `
                -Name $japanesePSRemoteingEnableRule `
                -DisplayName $japanesePSRemoteingEnableRule `
                -Description $Description `
                -Group $Group `
                -Enabled True `
                -Profile Any `
                -Direction Inbound `
                -Action Allow `
                -EdgeTraversalPolicy Block `
                -LooseSourceMapping $False `
                -LocalOnlyMapping $False `
                -OverrideBlockRules $False `
                -Program Any `
                -LocalAddress Any `
                -RemoteAddress Any `
                -Protocol TCP `
                -LocalPort $PSRemotePort `
                -RemotePort Any `
                -LocalUser Any `
                -RemoteUser Any 
        }
    }
}

まとめ

先般の記事だけでは、うまくいかない方は、試していただけると。

まぁ、英語OSで PSRemotingを有効化すればいいのですが。そもそも日本語OSは、サーバー運用上はびみょいのですががが。

*1:Disable-PSRemoting をしても問題ありません。