クレームと Azure と SharePoint を統合するツールキット パート 2

クレームと Azure と SharePoint を統合するツールキット パート 2

これは CASI キット、すなわちクレームと Azure と SharePoint を統合する (CASI: Claims, Azure and SharePoint Integration) ツール キットに関する 5 部構成の記事のパート 2 です。 パート 1 では このフレームワークとソリューションの全体像を示し、一連の記事で何を解き明かそうとしているかを説明しました。 今回の記事では、次の手法のパターンに焦点を当てます。

1. データやコンテンツのフロントエンドとしてカスタム WCF アプリケーションを使用する。

2. クレーム対応のアプリケーションにする。

3. Windows Azure クラウドへ移行できるように追加的な変更を行う。

WCF の使用

CASI キットによるフレームワークの主たる前提条件は、すべてのアプリケーション データで WCF アプリケーションをフロントエンドとして使用することです。 他のカスタム アプリケーションと同様に、開発者がこれを作成する必要があります。 プロジェクトのこの部分を実現するために必要な知識で SharePoint に特有なものはほとんどありません。Visual Studio を使用して WCF アプリケーションを作成できる .NET 開発者であれば誰でもこれを行えます。 この WCF サービスを Windows Azure でホストすることが最終目標であるならば、Windows Azure 開発キットを使用して Azure アプリケーション作成用のテンプレートをダウンロードし、最初から Azure WCF アプリケーションの作成に取り掛かることを強くお勧めします。 なお、現在のバージョンの CASI キットには、注意すべき制約があります。 それは CASI キットで WCF メソッドに送ることができる .NET のデータ型が基本データ型に限られることです。 つまり、文字列、ブール値、および日付値は問題なく使用できますが、カスタム クラスをパラメーターとして渡すメソッドはありません。 これを行う必要がある場合には、パラメーターを文字列として作成し、Xml に逆シリアル化してから WCF メソッドを呼び出し、その後、WCF コード内でシリアル化してオブジェクト インスタンスに戻すことをお勧めします。 これ以外に気になる制約は今のところ特にありませんが、これが広く採用されて使われるようになった暁には、それほど間を置かずに、いわゆる希望リストのようなものが作り上げられるものと思います。 ところで、現在のキットは、実際には、筆者の初期のアイデアを何とかまとめて、重要と思われる主なシナリオを満たすように設計したものにすぎません。 これが広く人々に使われるようになれば、改善すべき多くの課題が生じることは疑うべくもありません。

クレーム対応のアプリケーションにする

WCF アプリケーションを作成したならば、次にそれをクレーム対応のアプリケーションにする必要があります。 このステップに関して改めて説明することは特にありません。ここでは、非常に優れた 4 部構成のブログ投稿を紹介するに止めます。この投稿記事では、Office チームの Eric White が SharePoint の要求 (クレーム) を WCF アプリケーションに統合する方法を説明しています。 既に WCF サービスが作成してあるものと仮定し、Eric のブログ投稿のパート 2 ( https://blogs.msdn.com/b/ericwhite/archive/2010/05/13/determining-caller-identity-within-a-wcf-web-service.aspx (英語)) から開始するものとします。 さらに、パート 3 ( https://blogs.msdn.com/b/ericwhite/archive/2010/06/18/establishing-trust-between-a-wcf-web-service-and-the-sharepoint-2010-security-token-service.aspx (英語) ) の 「Procedure: Establish Trust between the Web Service and the SharePoint Server」以降の手順も実行する必要があります。 これ以降のすべての手順を実行する必要があります。これにより、SharePoint STS トークン署名証明書の拇印とその他の情報が WCF アプリケーション用の web.config ファイルにコピーされます。 パート 3 の SSL の手順を順に実行することはしません。アプリケーションを Windows Azure でホストするとき、自己署名証明書は実際には使われないからです。 他に使用可能なものがなければ、必要な作業は以上ですが、一般には、Windows Azure WCF アプリケーションのために適切な SSL 証明書を証明機関から取得する方法を計画する必要があります。 注意: Eric のブログ投稿のパート 4 の手順を実行する必要はありません。 以上の手順を実行すると、SharePoint クレーム対応の作業用 WCF アプリケーションが完成します。 次に、この投稿の最後のステップとして、Windows Azure に移行するための追加的な手順を説明します。

Windows Azure で機能するようにする

作成した作業用 WCF Azure アプリケーションで引き続き Windows Identity Framework (WIF) のトークンとクレーム認証をサポートし、それを Windows Azure クラウドでホストするためには、その他のいくつかの手順を実行する必要があります。 以下に手順を示します。

1. デバッグのためにローカルの仮想ディレクトリを使うように WebRole プロジェクト (すなわち、WCF プロジェクト) を構成します。 証明書が使われるようにするのが VS.NET 開発サーバーの本来の姿ですが、この変更はやってみると、それよりもずっと簡単です。 これを変更するには、WebRole プロジェクトのプロパティをダブルクリックし、[Web] (Web) タブをクリックします。 “ローカル IIS Web サーバーを使用する” というラジオ ボタンをオンにし、[仮想ディレクトリの作成] (Create Virtual Directory) ボタンをクリックします。 仮想ディレクトリを作成した後に、プロジェクトのプロパティを閉じることができます。

2. WebRole プロジェクトに Microsoft.Identity への参照を追加します。 この参照を変更して、必ず Copy Local = true、Specific Version = false としてください。 これでアプリケーション パッケージと共に WIF アセンブリもクラウドにコピーすることが必要になります。

3. 次の WCF 修正プログラムを入手します: https://code.msdn.microsoft.com/KB981002/Release/ProjectReleases.aspx?ReleaseId=4009 (英語) (Win2k8 R2 の場合)、 https://code.msdn.microsoft.com/KB971842/Release/ProjectReleases.aspx?ReleaseId=3228 (英語) (Win2k8 の場合)。

4. WCF クラスに必ず次の属性を追加してください: [ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]. たとえば、クラスは次のようになります。

namespace CustomersWCF_WebRole

{

    [ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]

    public class Customers : ICustomers

    {

5. サービスで使用される動作要素に必ず次の構成データを含めてください。 これは Azure 環境でポートをランダムに割り当てる場合に生じる問題を修正するものです。 これをローカルでテストするには、上記の手順 3. で示した修正プログラムを入手する必要があります。

      <useRequestHeadersForMetadataAddress>

            <defaultPorts>

              <add scheme="http" port="80" />

              <add scheme="https" port="443" />

            </defaultPorts>

          </useRequestHeadersForMetadataAddress>

筆者の WCF サービスにおける web.config の例 (関係する部分の抜粋) を示します。

    <behaviors>

      <serviceBehaviors>

        <behavior name="CustomersWCF_WebRole.CustomersBehavior">

          <federatedServiceHostConfiguration name="CustomersWCF_WebRole.Customers"/>

          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>

          <serviceDebug includeExceptionDetailInFaults="false"/>

          <useRequestHeadersForMetadataAddress>

            <defaultPorts>

              <add scheme="http" port="80" />

              <add scheme="https" port="443" />

            </defaultPorts>

          </useRequestHeadersForMetadataAddress>

        </behavior>

      </serviceBehaviors>

    </behaviors>

6. WCF アプリケーションで使用する SSL 証明書を最初に Azure Developer Portal にアップロードします。 注意: CASI キットの基本クラスは SSL を使用するように固定されているので、WCF Windows Azure アプリケーション内に SSL のサポートを必ず実装してください。 クラウド サービスと SharePoint ファームの間で機密性の高いデータをやり取りする場合には、当然、これが要件の 1 つとなるはずです。そこで、WebRole プロジェクト名 (Roles フォルダー内) をダブルクリックして、この証明書を Visual Studio の Azure ロール プロパティに追加します。 ワイルドカード証明書を試してみましたが、問題なく使うことができました。 しかし、必要なのは PFX 証明書なので、PFX ファイルを作成するときに、チェーン内のすべての証明書を必ずエクスポートしてください。 Developer Portal にアップロードすると、Azure によって展開されます。

7. Azure アプリケーションはすべて cloudapp.net でホストされますが、SSL 証明書の使用先を someName.yourDnsName.com にしてください。 たとえば、筆者の SSL 証明書は *.vbtoys.com を使用先とするワイルドカード証明書となります。 DNS に azurewcf.vbtoys.com という新しい CNAME レコードを作成し、そこから myAzureApp.cloudapp.net を参照するようにしました。 実際、 https://azurewcf.vbtoys.com に接続してみると、筆者の証明書は正常に機能します。筆者のリクエストと SSL 証明書の使用先は *.vbtoys.com ですが、DNS が CNAME レコード (myAzureApp.cloudapp.net) に基づいて筆者のリクエストをリダイレクトするからです。

8. Azure プロジェクトで、WebRole プロジェクト名 (Roles フォルダー内) をダブルクリックし、これらのプロパティを次のように設定します。

a. [構成] (Configuration) タブ: [次の場合にブラウザーを起動する] (Launch browser for) の [HTTP エンドポイント] (HTTP endpoint) および [HTTPS エンドポイント] (HTTPS endpoint) をオフにします。

b. [証明書] (Certificates) タブ: サービスの SSL で使用する証明書を追加します。 たとえば、筆者は自分の研究室では自分のドメインで自分のすべての Web サーバーに対して発行されるワイルドカード証明書を使うことにしているので、ここで自分のワイルドカード証明書を追加しました。

c. [エンドポイント] (Endpoints) タブ: HTTP と HTTPS の両方のボックスをオンにします (名前はそれぞれ HttpIn と HttpsIn)。 [HTTPS] (HTTPS) セクションにある SSL 証明書名のドロップ ダウン ボックスを開くと、上の手順 b. で追加した SSL 証明書が含まれているはずです。

9. スクリプトを値として返す WCF メソッドがある場合は、CASI キットの Web パーツとして使用したとき (あるいは独自の JavaScript 関数でタグの innerHTML に代入した場合に) 正常に機能するようにスクリプト タグに DEFER 属性を含める必要があります。 たとえば、スクリプト タグを次のようにします: <script defer language='javascript'>

10. <style> のような他のフォーマット タグを含むコンテンツを値として返す WCF メソッドがある場合は、それらを <pre> タグでラップする必要があります。そうしないと、CASI キットの Web パーツとして使用したとき、あるいは独自の JavaScript 関数でタグの innerHTML に代入した場合に、正しく処理されません。 たとえば、値として返されるコンテンツにスタイル タグが含まれる場合には、次のようにします: <pre><style>.foo {font-size:8pt;}</style></pre>

以上が、WCF アプリケーションを Azure でホストされるようにするための手順です。これに加えて、以下に示すいくつかの有用なヒントがあります。これらの一部は、実装の状況によっては、必須の手順になります。

1. サービスを消費する側のエンドポイント アドレスを作成するときは、完全修飾名を使用してください。たとえば、"machineName" ではなく、"machineName.foo.com" のようにします。 こうすると、Windows Azure でホストされる最終フォーマットへの移行がより明確になり、完全修飾ドメイン名を使用するように SSL 証明書を設計したときに生じるエラーも解決されます。

2. WSDL を SSL 経由で取得する場合は、本来ならば 属性 httpsGetEnabled="true" を要素 <serviceMetadata httpGetEnabled="true" /> に追加することになるでしょう。 しかし、現在のところ SharePoint Designer にバグがあるため、WSDL に対して SSL を使用することはできません。

3. デバッグやデータ接続については、筆者の投稿 ( https://blogs.technet.com/b/speschka/archive/2010/09/19/azure-development-tips-for-debugging-and-connection-strings.aspx (英語)) をご覧ください。

4. ほとんどの場合、WCF サービスの名前空間は https://tempuri.org になるものと考えてください。 この変更方法については、投稿 ( https://blogs.infosupport.com/blogs/edwinw/archive/2008/07/20/WCF_3A00_-namespaces-in-WSDL.aspx (英語)) をご覧ください。

完成した WCF サービス

以上のすべての構成手順を実行し、完成した WCF アプリケーションを Windows Azure に展開した場合は、ユーザーが SharePoint サイトからその WCF サービスを呼び出すと、そのユーザーのユーザー トークンの全体と、それに関連付けられているすべてのクレームが取得されます。 これらの変更を行った後は、社内でWCF サービスも動作するようになるので、追加的な変更を確認するとき、アプリケーションをクラウドに移行する前に簡単にテストできます。 このユーザー トークンがあると、WCF サービスで実に興味深いことを行えます。 たとえば、WCF サービス内でユーザーのすべてのクレームを列挙し、それに基づいて詳細な権限による決定を自由に行うことができます。 たとえば、次の例では、ユーザーのクレーム セットに対して LINQ を使用して、現在のユーザーが管理者かどうかを判断しています。ユーザーが管理者の場合には、次のレベルの詳細が返されます。

//look for the claims identity

IClaimsIdentity ci =

System.Threading.Thread.CurrentPrincipal.Identity as IClaimsIdentity;

if (ci != null)

{

//see if there are claims present before running through this

       if (ci.Claims.Count > 0)

       {

       //look for a group claim of domain admin

var eClaim = from Microsoft.IdentityModel.Claims.Claim c in ci.Claims

              where c.ClaimType ==

"https://schemas.microsoft.com/ws/2008/06/identity/claims/role" &&

                     c.Value == "Domain Admins"

                     select c;

              //see if we got a match

              if (eClaim.Count() > 0)

              //there’s a match so this user has the Domain Admins claim

                     //do something here

}

}

同様に WCF メソッドから直接権限を要求することもできます。 たとえば、データ ストアを照会して顧客の CEO の一覧を返す WCF メソッドがあるものと仮定します。 この情報を全社員には開示しないで、Sales Managers (営業部長) だけが使用できるようにすることを考えます。 これを実現するには、メソッドに次のような PrincipalPermission 要求を含めるだけで済みます。

//the customer CEO list should not be shared with everyone,

//so only show it to people in the Sales Manager role

[PrincipalPermission(SecurityAction.Demand, Role = "Sales Managers")]

public string GetCustomerCEOs()

{

//your code goes here

}

だれかがこのメソッドを呼び出そうとした場合、そのユーザーが “Sales Managers” に対応するクレームを持っていなければ、このメソッドを呼び出そうとしたコードを実行しているときにアクセスが拒否されたというエラーが返されます。 非常によくできたしくみです。

これはスプーフィングに対抗できる点も重要です。 たとえば、研究室に独自のドメインを作成し、そこにアカウントを追加し、Sales Manager ロールを作成してそこに先のアカウントを追加するようなことはできません。 これがうまくいかない理由は、以前実行した Eric White のブログの手順 (「クレーム対応のアプリケーションにする」で説明した手順) が関係しています。 そこでは、SharePoint STS で使用されるトークン署名証明書の拇印を追加しました。 これはクレームが WCF アプリケーションに送られたとき、SharePoint STS の公開キーで署名されたトークンが探されることを意味します。 そのトークン署名証明書の秘密キーを持つ唯一のエンティティである SharePoint STS だけが、これを公開キーで署名できます。 これにより、その SharePoint ファームに対して認証されたユーザーだけが WCF サービスを使用でき、ユーザーはログイン時に与えられたクレームだけを持つようになります。 しかし、ユーザー ディレクトリへの認証時に与えられたクレームに加えて、SharePoint のカスタム クレーム プロバイダーによるクレームの拡大によって与えられたその他のクレームもこれに含められることに注意してください。 そのため、これは真の意味で統合されたエンドツーエンド ソリューションだと言えます。

次のステップ

次回の投稿では、CASI キットに付属するカスタム基本クラスと Web パーツから説明します。これを使用すると、作成した Azure WCF アプリケーションに簡単に接続できます。 また、これ以降の手順では、機能説明のために CASI キットで作成した別の WCF サービスを使用することにします。 これまでの投稿でこのサービスのために使用した .cs ファイルを接続します。 これは、そのままでは使用できませんが、そこに含まれるさまざまなメソッドやデータ型を調べたり、このキットの機能を実装する方法を確認したりするのに役立ちます。 次回の投稿で主に使用するメソッドは、a) GetAllCustomersHtml、b) GetCustomerCEOs、c) GetAllCustomers methods です。 これらのメソッドで特に興味深い点は、a) から HTML (Web パーツでデータを表示するとき事実上の標準として使用される戻り型) が返されることと、b) で PrincipalPermission 要求が使用されることです。また、c) は、WCF アプリケーションからカスタム クラス型を取得する方法を示しており、そのデータを CASI キットで SharePoint に戻した後も同じように豊かなクラス型を使用できます。

これはローカライズされたブログ投稿です。原文の記事は、「The Claims, Azure and SharePoint Integration Toolkit Part 2」をご覧ください。