2012/05/29

WinRM+HTTPS+Basic認証

拙作パソコンオン/オフを実装するに当たり、WinRMをサポートした時にハマったのでメモ。

1. レガシープラットホームは、事前準備が必要!
まず、WinRMのインストール状況を確認する。
Windows XPなどのレガシー環境には、デフォルトでインストールされていないので、
こちらをインストールする。


2. HTTPSには、専用鍵が必要!
OpenSSLなどでよくやるSSL鍵生成プロセスで作成したものは、対応していない。
EKU ( Enhanced KeyUsage )が必要となる。

WinRMでよく取り上げられる鍵生成は、
makecert -sk "test.net" -ss My -sr localMachine -r -n "CN=test.net, O=hoge, L=foobar" -a sha1 -eku "1.3.6.1.5.5.7.3.1"
などとWindows上で実行する方法がある。

OpenSSLでやる場合は、configファイルのv3_caセクションに、
extendedKeyUsage       = 1.3.6.1.5.5.7.3.1
と追記する。

3. 自己署名SSL鍵インポートが面倒くさい!
正確にインポートするには、mmcを開く→証明書スナップインを追加→ルート証明書+ドメイン証明書それぞれをインポートといった手順になる。
これを複数の環境に実施するは、面倒くさいのでバッチ処理するといい。
例えば、
using System.Security.Cryptography.X509Certificates;

class Program
{
  static void importCert(string certFile,StoreName storeName,string pswd){
    X509Certificate2 cert = null;
    if( pswd == null ){
      cert = new X509Certificate2(  GetAppPath() + "\\" + certFile );
    }else{
      cert = new X509Certificate2(  GetAppPath() + "\\" + certFile, pswd , X509KeyStorageFlags.PersistKeySet);
    }

    X509Store store = new X509Store(storeName, StoreLocation.LocalMachine);

    store.Open(OpenFlags.ReadWrite);
    store.Add(cert);
    store.Close();
  }

  public static string GetAppPath()
  {
    return System.IO.Path.GetDirectoryName(
        System.Reflection.Assembly.GetExecutingAssembly().Location);
  }

  static void Main()
  {
        importCert( "ca.crt", StoreName.Root,null);
        importCert( "ca.pfx", StoreName.My,"");
  }
}
といったimport.csなどを作成し、ca.crtとca.pfx( パスワード無し )をそれぞれ用意する。

後は、
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\csc.exe import.cs
import
として実行する。
.NET2.0のcsc.exeを利用しているのは、VistaやWin7では初期導入されている為。
WinXPで、未だに2.0すら導入していない環境なんて皆無だろう...きっと。


4. HTTPSリクエスト用ポートを追加するのが、一番面倒!
面倒というか、一番ハマった。
Vista以降に導入されているWinRM2.0は、ポート作成に失敗すると、
再起動するまで挙動不審な状態に陥った。
一度ハマったら、証明書をmmc経由で登録しないと正常にポート追加できなかった。
環境依存かもしれない。
ポートを追加するには、
winrm create winrm/config/listener?Address=*+Transport=HTTPS @{Hostname="test.net";CertificateThumbprint="680b3b27620317079c2c5fecbc05d8d10395abd3";Port="5986"}
などと実行する。

5. Basic認証に対応するには、Client/Serverを分けて設定する!
WinRMが、面倒かつ混乱しやすいところだろうClient/Server認証。
非Windows環境からWinRMへリクエストを送信するだけの場合は、Server上で、
winrm set winrm/config/service/Auth @{Basic="true"}
と実行する。

Windows環境からの場合は、上記およびClient上で、
winrm set winrm/config/client/Auth @{Basic="true"}
と実行する。

0 件のコメント: