Windows Azure 仮想マシンに PowerShell でリモート接続する

結構苦労してしまったので備忘がてら。

PowerShell のリモート接続

今さらの話ではありますが、PowerShell 2.0 からリモート処理が行える様になっています。
細かい設定は こちら を見て頂くか、あるいはちょっとググればいくらでも出てきます。
普通にやる分にはとても簡単みたいです。素晴らしいですね。

Azure VM へのリモート接続

で、タイトルです。

結論から言うと SSL 使いましょうというただそれだけの話です。
ホントそれだけなのに、まずは接続出来ることだけ確認しようと思って HTTP で やったせいでやたら時間使ってしまいました。変にオリジナリティきかすとろくなこと無いですね。

手順としては こちら のまんまですが、日本語の情報が無かったってのがあるのと、OS は日本語化しているので、まぁ、無意味ではないかと。備忘ですしね(言い訳)

前提

Azure で Windows Server 2012 R2 の仮想マシンを立てていることが前提です。
Active Directory とかそういう面倒なのはなしです。また、Azure VM は OS が英語設定になっているので、今回は日本語化もします。OS 日本語化については こちらの記事 を参考にして下さい。

WinRM の有効化

PowerShell のリモート処理は、Windows リモート管理サービス(WinRM) 経由で行われます。
リモートとクライアントの両方で WinRM が有効になってないといけません。
Azure VM 側はインスタンスを作ったタイミングで既に有効になっているのでローカルの WinRM を有効化しましょう。

PS C:\> Enable-PSRemoting

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

続行しますか?
[Y] はい(Y)  [A] すべて続行(A)  [N] いいえ(N)  [L] すべて無視(L)  [S] 中断(S)  [?] ヘルプ (既定値は "Y"): 

ネットワークプロファイルがドメインやプライベートの場合はすんなり上手くいくはずです。
プロファイルがパブリックの場合は -SkipNetworkProfileCheck パラメータを付けて実行すれば良いようです。

信頼済ホストを変更する

ドメイン外のホストに対してリモート操作を行う為、クライアント側でリモートホストを信頼済ホスト(TrustedHosts)に追加します。

PS C:\> Set-Item wsman:\localhost\Client\TrustedHosts * -Force
PS C:\> Get-Item wsman:\localhost\Client\TrustedHosts


   WSManConfig: Microsoft.WSMan.Management\WSMan::localhost\Client

Name                      Value                                                             Type
----                      -----                                                             ----
TrustedHosts              *                                                                 System.String

今回は * (全てのホスト) を信頼してますが、127.0.0.* みたいにIP 指定も出来ます。仮想マシンだと IP 変わっちゃうから難しいと思いますが。

証明書を信頼する

このタイミングでリモートアクセスしてみます。コマンドは Enter-PSRemoting です。

PS C:\> Enter-PSSession -ComputerName <your machine name>.cloudapp.net -Credential <your account name> -UseSSL
Enter-PSSession : リモート サーバー <your machine name>.cloudapp.net への接続に失敗し、次のエラー メッセージが返されました: 宛先のコンピューター (<your machine name>.cloudapp.net:5986)  のサーバー証明書に次のエラーがあります:    
SSL 証明書が不明の証明機関によって署名されています。詳細については、about_Remote_Troubleshooting のヘルプ トピックを参照してください。
発生場所 行:1 文字:1
+ Enter-PSSession -ComputerName <your machine name>.cloudapp.net -Credential <your account name> -UseSSL
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (<your machine name>.cloudapp.net:String) [Enter-PSSession]、PSRemotingTransportException
    + FullyQualifiedErrorId : CreateRemoteRunspaceFailed

証明書が不明の証明機関によるものだと怒られました。ここで使われている証明書はオレオレ証明書なのでそりゃそうですね。
なので、そのオレオレ証明書を信頼する作業を行います。

まず、証明書をローカルに入手します。
ブラウザで https://<your machine name>.cloudapp.net/:5986 にアクセスしてください。 そしたら、証明書のエラーになると思いますので、証明書のプロパティを開きましょう。chrome だとここです。

f:id:kendik:20140110234430j:plain

プロパティを開いたら、[詳細]タブの[ファイルにコピー]ボタンから証明書を取得します。 ウィザードが出ますが、次へ次へってやってしまって問題ないです。

落としてきた証明書ファイルをダブルクリックすると、証明書のプロパティが開きますので[証明書のインストール]ボタンを押します。 証明書のインポートウィザードが開きますので、信頼されたルート証明機関に証明書を追加してください。こんな感じになってたら OK です。

f:id:kendik:20140110235142j:plain

リモート接続を開始する

お疲れ様でした。再度 Enter-PSRemoting コマンドレットを実行してください。今度は上手くいくはずです。

PS C:\> Enter-PSSession -ComputerName kendik.cloudapp.net -Credential kendik -UseSSL

[kendik.cloudapp.net]: PS C:\Users\kendik\Documents> 

どうしても HTTP で接続する

こんな簡単な事なのに、HTTP で接続しようとして苦労しました。

どうしても HTTP で接続したい方は、WinRM リスナーの HTTP 要求受け入れポートが 5985 なので、Azure ポータルから仮想マシンのエンドポイントに Port 5985 を追加するのと、仮想マシンファイアウォールを開ける、そしてリモートホスト上で Enable-PSRemoting を再実行する必要があります。面倒ですね。SSL 使いましょう。

エンドポイントの追加はこんな感じです。

f:id:kendik:20140110235716j:plain

ファイアウォールは、[受信の規則]の[Windows リモート管理 (HTTP 受信)]です。最初から有効になっていると思いますが、プロパティの[スコープ]で[リモート IP アドレス]が[ローカルサブネット]のみになっているので、これを[任意の IP アドレス]に変更してください。

Enable-PSRemoting は、OS を日本語化していると多分失敗すると思います。システムロケールを英語に設定してから実行してください。なぜ日本語化していると失敗するかはちゃんと調べてないんですが、多分 ここ で言っているのと同じ理由なんだろうと思います。