WCFによるセキュアでリライアブルでトランザクティッドな分散アプリケーションの構築:Windows Communication Foundation概説(1/3 ページ)
セキュリティ、信頼性を高める機能、分散トランザクション機能を解説。最終回のまとめとしてWCFのアーキテクチャを概観。
前回は、Windows Communication Foundation(WCF)のプログラミング手順を簡単なサンプル・プログラムの作成を通じて見ていった。WCFのプログラミングあるいはコンフィグレーションに必要なA(アドレス)、B(バインディング)、C(コントラクト)といった概念をある程度ご理解いただけたのではないだろうか。
さて今回はWS-*を使用した「セキュアでリライアブルでトランザクティッドな分散アプリケーションの構築」に関して見ていき、WCFのアーキテクチャを概観したい。
なお、ここに記載した内容は製品出荷前(WinFX Beta2 段階)での内容であるため将来変更される可能性が十分あることをあらかじめご了承いただきたい。
1. WCFでのセキュリティ
■1-1. トランスポート・レベルのセキュリティ
今日、セキュリティの重要性は高まる一方である。分散アプリケーション構築においても、「なりすまし」「盗聴」「改ざん」「リプレイ」などのセキュリティの脅威からいかに防備するかが重要視されている。そういった背景を踏まえ、WCFではセキュリティを確保するためのさまざまな機能が提供されている。ここではその一端を紹介していこう。
まずはトランスポート・レベルのPoint-to-Pointでのセキュリティの確保に関してだ。その代表的な手法であるSSL/TLS(=Secure Sockets Layer/Transport Layer Security)といった既存のトランスポート・レベルのセキュリティ確保のためのソリューションは、Webでのフォーム認証でHTTPSがよく使われているように広く一般的に普及しており、堅実なPoint-to-Pointのデータ暗号化と認証を高いパフォーマンスで実装することが可能である。
下記のコードはSSLを使用したWCFサービス使用時のクライアント・サイドのコンフィグレーションである。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<client>
<!-- エンドポイント・アドレスにhttpsを指定 -->
<endpoint
name="Endpoint1"
address="https://localhost/ServiceModelSamples/service.svc"
binding="basicHttpBinding"
bindingConfiguration="Binding1"
contract="Microsoft.ServiceModel.Samples.ICalculator" />
</client>
<bindings>
<basicHttpBinding>
<!-- BasicHttpバインディングで、
トランスポート・セキュリティ・モードを指定し、
clientCredentialType属性をNoneに設定 -->
<binding name="Binding1">
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>
</configuration>
このサンプル・コードは、SDKに付属の「Basic Binding Samples」の中の「Basic Binding with Transport Security Sample」に掲載されている。
このコンフィグレーションでは、クライアントの<endpoint>要素のbinding属性に「basicHttpBinding」を、またbindingConfiguration属性に「Binding1」を指定している。そして、そのbasicHttpBindingの内容を、<bindings>要素中の<basicHttpBinding>要素内の<binding name="Binding1">でカスタマイズする構成になっている。
具体的には、
<security mode="Transport">
と設定することでトランスポート・レベル(つまりPoint-to-Point)のセキュリティが有効になる。また、
<transport clientCredentialType="None"/>
によりクライアントはサービスに対しクレデンシャル(=資格情報)の提出は不要であること、つまりはAnonymous認証(=匿名認証)であることを指定している。
■1-2. メッセージ・レベルのセキュリティ
さて、メッセージがそのあて先に到達するまでに1つ以上の中継ノードを通過しなければならない場合、SSLのPoint-to-Pointでのセキュリティ確保では各中継ノード間で新しいSSL接続を介してメッセージを転送する必要があるためオーバーヘッドもかかる。また、中間ノードでいったん復号化されるためその中継サーバをクライアントおよびサービス・サイドが信頼し得るといった前提条件が必要となる。
そこで、プロトコル非依存のEnd-to-Endでのセキュリティ確保が必要な場面が登場していく。それを規定したのがWS-Securityの仕様であり、WCFではコンフィグレーションの変更のみで容易にWS-Securityを使用したメッセージの署名暗号化によるセキュリティの確保が可能である。
下記はメッセージ・レベルのセキュリティを行う場合の、クライアント・サイドのコンフィグレーションの例である。ここでは、X.509証明書を使用したクライアント・サービスの双方向の認証を行っている。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<client>
<!-- サービスに提示するためのクライアント証明書を
設定するために、ビヘイビアを使用する -->
<endpoint
name="Endpoint1"
address="http://localhost:8000/servicemodelsamples/service"
binding="basicHttpBinding"
bindingConfiguration="Binding1"
behaviorConfiguration="ClientCertificateBehavior"
contract="Microsoft.ServiceModel.Samples.ICalculator"/>
</client>
<bindings>
<basicHttpBinding>
<!-- メッセージ・セキュリティ・モードを指定し、
clientCredentialType属性をCertificateに設定 -->
<binding name="Binding1">
<security mode="Message">
<message clientCredentialType="Certificate"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<behavior name="ClientCertificateBehavior">
<!-- clientCredentialsビヘイビアは、
サービスに提示するための証明書の定義を可能とする
クライアント証明書がサービス・サイドで
クライアントの認証のために使用され、
メッセージの暗号化を提供する -->
<clientCredentials>
<clientCertificate findValue="client.com"
storeLocation="CurrentUser" storeName="My"
x509FindType="FindBySubjectName" />
<serviceCertificate>
<authentication
certificateValidationMode = "PeerOrChainTrust" />
<defaultCertificate findValue="localhost"
storeLocation="LocalMachine" storeName="My"
x509FindType="FindBySubjectName" />
</serviceCertificate>
</clientCredentials>
</behavior>
</behaviors>
</system.serviceModel>
</configuration>
このサンプル・コードは、SDKに付属の「Basic Binding Samples」の中の「Message Security Sample」に掲載されている。
このコンフィグレーションでも、クライアントの<endpoint>要素のbinding属性に「basicHttpBinding」を、またbindingConfiguration属性に「Binding1」を指定している。さらに、ここで使用するbasicHttpBindingの内容を、<bindings>要素中の<basicHttpBinding>要素内でカスタマイズする構成になっている。
具体的には、
<security mode=" Message ">
と設定することでメッセージ・レベル(つまりEnd-to-End)のセキュリティが有効になる。また、
<message clientCredentialType="Certificate"/>
によりクライアントはサービスに対しクライアント証明書の提出が必要であること、つまりはサービス・サイドでのクライアント証明書認証であることを指定している。
ここで、どの証明書ストアからどの証明書をクライアント証明書として使用するのかなどの指定を行っているのが、<endpoint>要素のbehaviorConfiguration属性から参照されている<behavior>要素である。
<behavior>要素内の<clientCredentials>要素では、クライアントが使用する証明書に関する情報が<clientCertificate>要素に記載されている。
具体的には、サービス・サイドでのクライアントの認証用に使用するクライアント証明書(秘密鍵)のストアと名前「client.com」を指定することで証明書の在りかを明示する。また、クライアント・サイドでのサービス側の認証用にサービス側の証明書(公開鍵)のストアと名前「localhost」を指定することで証明書の在りかを明示している。
■1-3. ビヘイビア(Behavior)とは
前回まででWCFでの重要な概念である“ABC”を説明したが、実はもう1つ重要な概念としてビヘイビア(Behavior)がある。
ビヘイビアとは直訳すれば「振る舞い」となるが、サービスあるいはクライアントの対外的に表明の必要がない、いわばローカルな振る舞いでありながらWCFの通信に大きく影響する部分を定義するところがビヘイビアであるといえる。つまり、WCFで重要な概念としては正確には、「ABC+Bv(Behavior)」であるといえる。
例えば先ほどのセキュリティの設定の場合、バインディング(binding)の指定では、トランスポート・レベルのセキュリティなのか、あるいはメッセージ・レベルのセキュリティなのかを決定する。標準のバインディング(例えばwsHttpBinding)の使用ではデフォルトでセキュアであるので、下記のように設定することでセキュリティをOFFにすることもできる。
<wsHttpBinding>
<binding name="wsNoSecure">
<security mode="None"/>
</binding>
</wsHttpBinding>
このようにバインディングにおいては、「セキュリティをする/しない」といった指定や、セキュリティをかけるといっても「トランスポート・レベルなのかメッセージ・レベルなのか、あるいはその両方の併用なのか」などの指定を行う。
ここまではクライアントおよびサービス・サイドで合わせておかねばならない、いわば契約の部分であり、サービスのセキュリティ要件を満たさないクライアントからのリクエストは受け付けられない。
しかし、クライアント・サイドのどの証明書ストアから証明書を見つけ出すのかといった指定に関してはサービス・サイドとはまったく無縁のクライアント・ローカルな指定である。ただし、これはサービスとの通信を組み立てるうえで何がしかの指定が必要な部分であり、それをWCFではビヘイビアと呼び、コンフィグレーション上も明確に分離して扱っているのである。
2. WCFでのメッセージのリライアビリティ
従来、Webサービスでのメッセージ送信に関して、メッセージが確実に先方に到着し(メッセージの欠損が防止され)、重複を防ぎ、順序制御も正しく行われるようにするためには、何がしかの作り込みが必要となっていた。
例えばメッセージIDを付加して欠損を検出しリトライを試みたり、順序を管理したりといったものであるが、そもそもこういった汎用的なニーズに対してアプリケーション・サイドでいちいち作り込まなければならないというのは、非常にオーバーヘッドであったといえる。
そこで登場したのがWS-ReliableMessagingであるが、WCFではこれを使用しおりプロトコル非依存なEnd-to-Endでのメッセージを確実に送受信するといったことが容易に実現可能となっている。開発者はこういったニーズに関してWCFを使用するだけで特にアプリケーション・サイドで複雑な配管コードを作り込む必要はなくなるわけである。
例えば、WCFの標準のバインディングのうちデフォルトでリライアブルなものの代表格として、先述したwsHttpBindingが挙げられる。これはWS-*(=Webサービス拡張仕様)に対応した標準バインディングであるが、wsHttpBindingを指定すれば特に何も指定しなくてもWS-ReliableMessagingを使用したメッセージの確実な送受信がデフォルトで有効となる。
あえてこれを無効化しようとすると下記のようにコンフィグレーションを変更する必要がある。
<wsHttpBinding>
<binding name="wsNoReliable">
<reliableSession
enabled="false"
ordered="false"/>
</binding>
</wsHttpBinding>
逆に上記で、
<reliableSession enabled="true" ordered="true"/>
と記述すると、明示的にWS-ReliableMessagingを有効にした指定になる。なお、このコンフィグレーションのようなWS-ReliableMessagingの有効/無効に関しては、バインディングでのみ指定可能であり、(前章の)セキュリティのときに使用したビヘイビアでの指定は特にない。
【コラム】WS-ReliableMessagingのデモンストレーション
WS-Securityによってどのようにメッセージが署名暗号化され、改ざん防止、盗聴防止、なりすましや否認防止がなされるのかはパケット・トレースでの確認が有効である。しかし、WS-ReliableMessagingの有用性に関してはパケット・トレースではいま1つ体感しにくい。なぜなら、トレース上ではメッセージIDの自動的な付与と、それに対する肯定応答といったやりとりが行われているだけだからである。
そこで、WCFでクライアントとサービス間でイメージ・ファイルを分割して転送を行うアプリケーションを作成し、その間にWCFで作ったゲートウェイを介入させることで、データの欠損をシミュレーションし、WS-ReliableMessagingによる欠損時の再送や順序制御の有用性を体感できるデモ・アプリケーションがマイクロソフト本社社員のブログで公開されている。興味のある方は次のリンクからダウンロードしてお試しいただきたい。
このデモ・アプリケーションを実行すると、WS-ReliableMessagingが無効になっている場合には、次の画面のように、画像の一部が欠損するのが確認できる。
クライアントおよびサービス・サイドのコンフィグレーションの<reliableSession>要素をコメントアウトした場合のデモ・アプリケーションの画面
左のフォームの画像を分割して右のフォームに転送するといったWindowsフォーム間のWCFを使用したサンプル・プログラムであるが、その際、真ん中のフォームがゲートウェイを行っており、このフォーム上でメッセージのドロップ率を設定可能となっている。ゲートウェイでのメッセージ・ドロップの結果、右のフォームの画像が歯抜けとなっているのが分かる。
しかし、WS-ReliableMessagingが有効な場合には、欠損が生じない。
クライアントおよびサービス・サイドのコンフィグレーションの<reliableSession>要素を有効にした場合のデモ・アプリケーションの画面
ゲートウェイでのメッセージ・ドロップも自動リカバリされ、順序も乱れずきちんと画像が送信完了する。
Copyright© Digital Advantage Corp. All Rights Reserved.