Share via


セキュリティ保護された ASP.NET アプリケーションの構築 : 認証、認定、および通信のセキュリティ保護 第 9 章 Enterprise Services セキュリティ

patterns and practices home

J.D. Meier, Alex Mackman, Michael Dunner, and Srinath Vasireddy
Microsoft Corporation

November 2002
日本語版最終更新日 2003 年 3 月 17 日

適用対象:
    Microsoft® ASP.NET

全体の概要については、「セキュリティ保護された ASP.NET アプリケーションの構築」の開始ページを参照してください。

要約 : この章では、Enterprise Services アプリケーションに格納されるサービス対象のコンポーネントのビジネス機能をセキュリティで保護する方法について説明します。Enterprise Services (COM+) ロールを認定に使用する方法とタイミングについて、および RPC 認証と偽装を構成する方法についての内容も含めています。また、ASP.NET Web アプリケーションからセキュリティで保護された状態でサービス対象のコンポーネントを呼び出す方法や、中間層のサービス対象のコンポーネントを介して最初の呼び出し元のセキュリティ コンテキストを識別し、フローさせる方法についても説明します。

目次

セキュリティ アーキテクチャ
セキュリティの構成
セキュリティのプログラミング
プロセス ID の選択
ネットワーク リソースへのアクセス
最初の呼び出し元のフロー
RPC 暗号化
サービス対象のコンポーネントの作成
DCOM とファイアウォール
ASP.NET からのサービス対象のコンポーネントの呼び出し
セキュリティの概念
まとめ

.NET コンポーネントでは、従来の COM+ サービス (分散トランザクション、ジャスト イン タイム アクティベーション、オブジェクト プーリング、同時実行管理など) を利用できます。.NET では、このような COM+ サービスを Enterprise Services と呼びます。Enterprise Services は、.NET アプリケーション内で実行される中間層の .NET コンポーネントにとって必要不可欠なサービスです。

サービスを .NET コンポーネントへ追加するには、EnterpriseServices.ServicedComponent ベース クラスからコンポーネント クラスを派生し、コンポーネントをホストするアセンブリにコンパイルされた .NET 属性を使用して詳細なサービス要件を指定します。

この章では、セキュリティで保護されたサービス対象のコンポーネントの作成方法と、ASP.NET Web アプリケーションからこのサービス対象のコンポーネントを呼び出す方法について説明します。

セキュリティ アーキテクチャ

Enterprise Services アプリケーションによりサポートされる認証機能、認定機能、および通信保護機能を図 9.1 に示します。図 9.1 のクライアント アプリケーションは ASP.NET Web アプリケーションです。

図 9.1 Enterprise Services ロールに基づいたセキュリティ アーキテクチャ

認証機能と通信保護機能は、分散 COM (DCOM) で使用される基礎 RPC トランスポートにより提供される点に注意してください。認定機能は、Enterprise Services (COM+) ロールにより提供されます。

Enterprise Services セキュリティ アーキテクチャの主な特長は次のとおりです。

  • Enterprise Services アプリケーションでは、呼び出し元の認証に RPC 認証機能が使用されます。つまり、認証を無効にしない限り、Kerberos 認証または NTLM 認証を使用して呼び出し元が認証されます。

  • 認定機能は Enterprise Services (COM+) ロールにより実現します。Enterprise Services (COM+) ロールには、Microsoft® Windows® オペレーティング システムのシステム グループやユーザー アカウントを含めることができます。ロール メンバシップは、COM+ カタログ内に定義されており、[コンポーネント サービス] ツールを使用して管理します。

    メモ Enterprise Services アプリケーションで偽装が使用されている場合には、Windows ACL を使用して呼び出し元を認定することもできます。

  • 認証プロセスの完了後にASP.NET Web アプリケーションなどのクライアントからサービス対象のコンポーネントに対してメソッドが呼び出されると、クライアントのロール メンバシップを確認するため、Enterprise Services インターセプション層が COM+カタログへアクセスします。次に、現在のアプリケーション、コンポーネント、インターフェイス、およびメソッドへの認定アクセスが、ロール メンバシップで許可されているかどうかが確認されます。

  • クライアントのロール メンバシップでアクセスが許可されている場合には、メソッドが呼び出されます。クライアントが適切なロールに属していない場合には、呼び出しは拒否されます。また、設定によっては、アクセスの失敗を反映するセキュリティ イベントも生成されます。

    重要 ASP.NET Web アプリケーションにより呼び出される Enterprise Servicesアプリケーションでロールに基づいた認証機能を適切に実装するには、Windows の認証機能と偽装機能を ASP.NET Web アプリケーション内で使用する必要があります。これにより、最初の呼び出し元のセキュリティ コンテキストがサービス対象のコンポーネントへフローされます。

  • クライアントとサーバー アプリケーションとの間の DCOM 通信リンクをセキュリティで保護するには、認証レベルとしてメッセージの統合性を維持する RPC Packet Integrity またはメッセージの機密を保護する RPC Packet Privacy のいずれかを使用できます。

ゲートキーバーおよびゲート

Enterprise Services ランタイムは、サービス対象のコンポーネントのゲートキーパーとして機能します。Enterprise Services アプリケーション内の各ゲート、つまり認定ポイントを図 9.2 に示します。これらのゲートを構成するには、Enterprise Services ロールを使用します。このロールへは Windows グループおよびユーザー アカウントを追加する必要があります。

メモ ロール ベースのセキュリティによるアクセス チェックがEnterprise Services アプリケーションに対して有効になっており、適切なレベルの認証が使用されていることを確認してください。セキュリティの構成方法の詳細については、後の「セキュリティの構成」を参照してください。

図 9.2 Enterprise Services アプリケーションのゲートキーパー

サービス対象のコンポーネントに対してクライアントがメソッド呼び出しを発行すると、これに対応して次の 3 種類のアクセス チェックが実行されます。これらの アクセス チェックは、図 9.2 に示されています。

  1. サービス対象のコンポーネントを呼び出した結果、アクティブ化が要求され、COM+ プロキシ プロセスである Dllhost.exe の新規インスタンスが作成されると、Enterprise Services アプリケーションをアクティブ化するサブシステム (COM サービス コントロール マネージャ (SCM)) が初期アクセス チェックを実行します。

    このアクセス チェックを通過するには、呼び出し元がアプリケーションで定義されている 1 つ以上のロールのメンバである必要があります。

  2. クライアントの呼び出しが Dllhost.exe プロセス インタンスに到達すると、2 番目のアクセス チェックが実行されます。

    このアクセス チェックを通過するには、呼び出し元が、アプリケーションで定義されている 1 つ以上のロールのメンバである必要があります。

  3. クライアントの呼び出しがサーバーまたはライブラリ アプリケーションに到達すると、3 番目の最終アクセス チェックが実行されます。

    このアクセス チェックを通過するには、呼び出し元が、クライアントによる呼び出しのターゲットであるインターフェイス、クラス、またはメソッドに関連付けられているロールのメンバである必要があります。

重要 サービス対象のコンポーネントが同一アプリケーションの他のコンポーネントと通信する場合、呼び出しによってサービス対象のコンポーネントに対するメソッドが呼び出された後には、アクセス チェックは実行されません。ただし、コンポーネントが別のアプリケーション (ライブラリまたはサーバー) 内のコンポーネントを呼び出す場合には、アクセス チェックが実行されます。

サーバー アプリケーションを使用したセキュリティの強化

サービス対象のコンポーネントへの送信データがネットワーク経由で転送されるときに、データの機密を保護し、改ざんを防止するために暗号化を必要とする場合など、アプリケーションの認証レベルを強化する必要がある場合には、サーバー アプリケーションを使用します。

サーバー アプリケーションには認証レベルを強制的に適用できますが、ライブラリ アプリケーションはホスト プロセスの認証レベルを継承します。

Enterprise Services アプリケーションのアクティブ化タイプを構成するには、アセンブリ レベルで ApplicationActivation 属性を次のように設定します。

[assembly: ApplicationActivation(ActivationOption.Server)]

これは、コンポーネント サービスでアプリケーションの [プロパティ] ダイアログ ボックスの [アクティブ化] ページで、[アクティブ化の種類] に [サーバー アプリケーション] を設定する操作と同等です。

サーバー アプリケーションとライブラリ アプリケーションのセキュリティ

ロール ベースのセキュリティは、イン プロセス ライブラリ アプリケーションとアウト プロセス サーバー アプリケーションの場合と同様に機能します。

次に示すライブラリ アプリケーションでの相違点に注意してください。

  • 特権 ライブラリ アプリケーションの特権は、クライアント (ホスト) プロセスの特権によって決定します。たとえば、クライアント プロセスが管理者特権で実行される場合には、ライブラリ アプリケーションにも管理者特権が付与されます。

  • 偽装 ライブラリ アプリケーションの偽装レベルはクライアント プロセスから継承されます。偽装レベルを明示的に設定することはできません。

  • 認証 ライブラリ アプリケーションの認証レベルはクライアント プロセスから継承されます。ライブラリ アプリケーションでは、認証を明示的に有効または無効にできます。認証を有効または無効にするには、ライブラリ アプリケーションの [プロパティ] ダイアログ ボックスの [セキュリティ] タブを使用します。

    このオプションは、他のアウト プロセス COM コンポーネントからの未認証コールバックをサポートするときに一般的に使用されます。

クラス、インターフェイス、メソッドへのロールの割り当て

ライブラリ アプリケーションでは、クラス、インターフェイス、またはメソッドのレベルでロールを割り当てます。サーバー アプリケーションの場合も、このロール割り当て方法が適しています。

ライブラリ アプリケーションのロールで定義されているユーザーをクライアント プロセスのセキュリティ記述子へ追加することはできません。つまり、ライブラリ アプリケーションでロールに基づいた認定を可能にするには、クラス レベル以上のセキュリティを使用している必要があります。

コード アクセス セキュリティの要件

コード アクセス セキュリティ (CAS) では、特定の操作を実行したり、アクセスが制限されているリソースへアクセスしたりするための特別なアクセス許可がコードに付与されている必要があります。CAS は、インターネットからコードをダウンロードするクライアント環境で、役に立つセキュリティ機能です。このようなクライアント環境では、コードを完全に信頼することはできません。

一般に、サービス対象のコンポーネントを使用するアプリケーションは完全に信頼されています。このため、CAS の用途は限られています。ただし Enterprise Services では、アンマネージ コードを呼び出すために必要なアクセス許可が呼び出し元コードに付与されている必要があります。次の条件が前提となります。

  • サービス対象のコンポーネントに対してコンテキスト間呼び出しをアクティブ化して実行するには、アンマネージ コード アクセス許可が必要です。
  • サービス対象のコンポーネントのクライアントが ASP.NET Web アプリケーションの場合、このアプリケーションにはアンマネージ コード アクセス許可が必要です。
  • サービス対象のコンポーネントへの参照が信頼されていないコードへ渡される場合、サービス対象のコンポーネントで定義されているメソッドは、信頼されていないコードから呼び出すことはできません。

セキュリティの構成

ここでは、次のセキュリティ構成方法について説明します。

  • Enterprise Services サーバー (アウト プロセス) アプリケーションで実行されているサービス対象のコンポーネント
  • ASP.NET Web アプリケーション クライアント

サーバー アプリケーションの構成

Enterprise Services サーバー アプリケーションの構成手順を図 9.3 に示します。

図 9.3 Enterprise Services セキュリティの構成

開発時の構成と展開時の構成

ほとんどのセキュリティ設定は、開発時に COM+ カタログで構成できます。開発時にセキュリティ設定を構成する場合には、サービス対象のコンポーネントが含まれているアセンブリの .NET 属性を使用します。Regsvcs.exe ツールを使用してサービス対象のコンポーネントが COM+ に登録されると、この .NET 属性を使用して COM+ カタログにデータが追加されます。

Windows グループ アカウントとユーザー アカウントが含まれるロールの作成や、サーバー アプリケーション (Dllhost.exe インスタンス) の実行時 ID の構成などのその他の構成操作は、展開時にコンポーネント サービス管理ツールまたはスクリプトを使用して実行する必要があります。

認証の構成

宣言を使用してアプリケーション認証レベルを設定するには、アセンブリ レベルで ApplicationAccessControl 属性を次のように使用します。

[assembly: ApplicationAccessControl(
Authentication = AuthenticationOption.Call)]

これは、コンポーネント サービスでアプリケーションの [プロパティ] ダイアログ ボックスの [セキュリティ] タブで、[呼び出しの認証レベル] の値を設定する操作と同等です。

メモ 最高レベルのネゴシエーション プロセスが採用されており、2 つの設定値のうち高い方の設定が常に使用されるので、クライアントの認証レベルは Enterprise Services アプリケーションの認証レベルにも影響します。

ASP.NET クライアント アプリケーションにより使用される DCOM 認証レベルの構成方法の詳細については、後の「ASP.NET クライアント アプリケーションの構成」を参照してください。

DCOM 認証レベルと認証レベルのネゴシエーションの詳細については、後の「セキュリティの概念」を参照してください。

認定 (コンポーネント レベル アクセス チェック) の構成

コンポーネント、インターフェイス、またはメソッド レベルでのきめ細かな認定を有効にするには、次の操作を行ってください。

  • アプリケーション レベルでアクセス チェックを有効にします。

    アプリケーション全体でのアクセス チェックを有効にします。

[assembly: ApplicationAccessControl(true)]
これは、コンポーネント サービスでアプリケーションの \[プロパティ\] ダイアログ ボックスの \[セキュリティ\] タブで、\[このアプリケーションへのアクセス確認を行う\] チェック ボックスをオンにする操作と同等です。

**重要** この属性を設定しないと、アクセス チェックが実行されません。
  • プロセス レベルまたはコンポーネント レベルでアプリケーションのセキュリティ レベルを構成します。

    適切なロール ベースのセキュリティを設定するため、次に示す .NET 属性を使用してプロセス レベルとコンポーネント レベルでのアクセス チェックを有効にします。

[assembly: ApplicationAccessControl(AccessChecksLevel=
    AccessChecksLevelOption.ApplicationComponent)]
    
これは、コンポーネント サービスでアプリケーションの \[プロパティ\] ダイアログ ボックスの \[セキュリティ\] タブで、\[プロセスおよびコンポーネント レベルでのアクセス確認を実行する\] チェック ボックスをオンにする操作と同等です。

**メモ** ライブラリ アプリケーションでは、プロセス レベルとコンポーネント レベルのアクセス チェックを常に有効にしてください。
  • コンポーネント レベルのアクセス チェックを有効にします。

    コンポーネント レベルのアクセス チェックを有効にするには、クラス レベルで ComponentAccessControl 属性を次のように使用します。

[ComponentAccessControl(true)]
    public class MyServicedComponent : ServicedComponent
    {
    }
    
これは、コンポーネント サービスでアプリケーションの \[プロパティ\] ダイアログ ボックスの \[セキュリティ\] タブで、\[コンポーネント レベルでのアクセス確認を行う\] チェック ボックスをオンにする操作と同等です。

**メモ** この設定が有効となるのは、アプリケーション レベルのアクセス チェックを有効にしており、プロセス レベルとコンポーネント レベルのアクセス チェックを前に説明したとおりに構成している場合のみです。

ロールの作成と割り当て

ロールの作成と割り当ては、アプリケーション、コンポーネント (クラス)、インターフェイス、およびメソッドのレベルで実行できます。

アプリケーションへのロールの追加

アプリケーションにロールを追加するには、アセンブリ レベルで SecurityRole 属性を次のように使用します。

[assembly:SecurityRole("Employee")]
[assembly:SecurityRole("Manager")]

これは、コンポーネント サービス ツールを使用してアプリケーションにロールを割り当てる操作と同等です。

メモ アセンブリ レベルでの SecurityRole 属性の設定は、アプリケーションへロールを追加する操作と同等です。ただし、個別のコンポーネント、インターフェイス、またはメソッドへロールを割り当てる操作とは異なります。この属性を設定すると、これらのロールのメンバにより、アプリケーションに添付されるセキュリティ記述子の構成が決定します。この処理は、アプリケーションへアクセスおよび起動が可能な特権を持つユーザーを判断する目的でのみ使用されます。

この属性の設定よりも効果的なロール ベースの認定を実行するには、常に、コンポーネント、インターフェイス、およびメソッドへロールを適用します。ロールの適用方法については、以降の節で説明します。

コンポーネント (クラス) へのロールの追加

コンポーネントにロールを追加するには、クラス定義よりも前で SecurityRole 属性を次のように適用します。

[SecurityRole("Manager")]
public class Transfer : ServicedComponent
{
}

インターフェイスへのロールの追加

インターフェイス レベルでロールを適用するには、インターフェイス定義を作成してから、サービス対象のコンポーネント クラス内でこの定義を実装します。次に、SecurityRole 属性を使用してインターフェイスにロールを関連付けます。

重要 開発時には、クラスにも SecureMethod 属性を注釈付けしてください。この属性の設定により、Enterprise Services に、メソッド レベルのセキュリティ サービスが使用されることが通知されます。展開時に、管理者はユーザーをシステム定義ロール Marshaler に追加する必要があります。SecureMethod が設定されているクラスがコンポーネント サービスへ登録されると、COM+ カタログ内に Marshaler ロールが自動的に作成されます。

Marshaler ロールについては、以下で詳しく説明します。

Manager ロールを特定のインターフェイスに追加する方法を、次の例に示します。

[SecurityRole("Manager")]
public interface ISomeInterface
{
void Method1( string message );
void Method2( int parm1, int parm2 );
}

[ComponentAccessControl]
[SecureMethod]
public class MyServicedComponent : ServicedComponent, ISomeInterface
{
public void Method1( string message )
  {
// Implementation
  }
public void Method2( int parm1, int parm2 )
  {
// Implementation
  }
}

メソッドへのロールの追加

クラスのパブリック メソッドが COM+ カタログに含まれるようにするには、このメソッドを定義するインターフェイスを明示的に実装します。次に、メソッドを保護するため、クラス レベルで SecureMethod 属性を使用するか、メソッド レベルで SecureMethod 属性または SecurityRole 属性を使用します。

メモ SecureMethod 属性と SecurityRole 属性は、インターフェイス定義の中でメソッド実装より前に記述します。

メソッド レベルのセキュリティを有効にするには、次の手順に従います。

  1. 保護するメソッドを含むインターフェイスを定義します。次に、例を示します。
public interface ISomeInterface
{
void Method1( string message );
void Method2( int parm1, int parm2 );
}

  1. サービス対象のコンポーネント クラスでインターフェイスを実装します。
[ComponentAccessControl]
public class MyServicedComponent : ServicedComponent, ISomeInterface
{
public void Method1( string message )
  {
// Implementation
  }
public void Method2( int parm1, int parm2 )
  {
// Implementation
  }
}

  1. コンポーネント サービス ツールを使用してロール管理を構成するには、次に示すようにクラスに SecureMethod 属性を注釈付けします。
[ComponentAccessControl]
[SecureMethod]
public class MyServicedComponent : ServicedComponent, ISomeInterface
{
}

  1. 開発時に .NET 属性を使用してメソッドにロールを追加する場合には、メソッド レベルで SecurityRole 属性を適用します。この場合、クラス レベルで SecureMethod 属性を適用する必要はありません。ただし、コンポーネント レベルのアクセス チェックを構成するので、ComponentAccessControl 属性が必要です。

    次に示す例では、Manager ロールと Employee ロールのメンバが Method2 を呼び出すことができますが、Method1 を呼び出すことができるのは Manager ロールのメンバだけです。

[ComponentAccessControl]
    public class MyServicedComponent : ServicedComponent, ISomeInterface
    {
    [SecurityRole("Manager")]
    public void Method1( string message )
      {
    // Implementation
      }
    [SecurityRole("Manager")]
    [SecurityRole("Employee")]
    public void Method2( int parm1, int parm2 )
      {
    // Implementation
      }
    }
    
  1. 展開時に、管理者が、クラスのメソッドまたはインターフェイスへアクセスする必要のあるユーザーを、あらかじめ定義されている Marshaler ロールへ追加します。

    メモ Enterprise Services インフラストラクチャでは、すべてのサービス対象のコンポーネントにより公開されている多くのシステム レベル インターフェイスが使用されます。このようなインターフェイスには、IManagedObject、IDisposable、および IServiceComponentInfo があります。インターフェイス レベルまたはメソッド レベルでアクセス チェックが有効になっていると、Enterprise Services インフラストラクチャからこれらのインターフェースへのアクセスは拒否されます。

    その結果、Enterprise Services により Marshaler という特殊なロールが作成され、このロールがこれらのインターフェイスに関連付けられます。Marshaler ロールと前に述べたインターフェイスを参照するには、コンポーネント サービス ツールを使用します。

    アプリケーション管理者は、クラスのメソッドまたはインターフェイスすべてにアクセスする必要があるすべてのユーザーを、展開時に Marshaler ロールに追加することが必要です。Marshaler ロールへのユーザーの追加操作を自動処理するには、次の 2 とおりの方法があります。

    • コンポーネント サービス オブジェクト モデルを使用して他のロールに割り当てられているすべてのユーザーを Marshaler ロールにコピーするスクリプトを記述する。
    • 他のすべてのロールをこの 3 つの特別なインターフェイスに割り当てるスクリプトを記述して、Marshaler ロールを削除する。

サービス対象のコンポーネントの登録

サービス対象のコンポーネントを、次の 2 つの機能に登録します。

  • グローバル アセンブリ キャッシュ COM+ サーバー アプリケーションでホストされるサービス コンポーネントはグローバル アセンブリ キャッシュにインストールする必要がありますが、ライブラリ アプリケーションでホストされるサービス コンポーネントについてはインストールの必要はありません。

    グローバル アセンブリ キャッシュに、サービス対象のコンポーネントを登録するには、コマンド ライン ユーティリティ Gacutil.exe を使用します。グローバル アセンブリ キャッシュにMyServicedComponent.dll というアセンブリを登録するには、次のコマンドを実行します。

gacutil -i MyServicedComponent.dll
**メモ** グローバル アセンブリ キャッシュの内容を表示、操作するには、\[管理ツール\] プログラム グループの Microsoft .NET Framework Configuration ツール を使用します。
  • COM+ カタログ COM+ カタログに MyServicedComponent.dll というアセンブリを登録するには、次のコマンドを実行します。
regsvcs.exe MyServicedComponent.dll
このコマンドを実行すると、COM+ アプリケーションが作成されます。アセンブリ内の .NET 属性は、COM+ カタログにデータを追加するときに使用されます。

ロールへのアカウントの追加

ロールにアカウントを追加するには、コンポーネント サービス ツールを使用するか、スクリプトで COM+ 管理オブジェクトを使用して COM+ カタログをプログラミングします。

Windows グループの使用

柔軟性を最大限に引き出すには、Windows 2000 グループ アカウントを Enterprise Services ロールに追加します。Windows グループを使用すると、1 つの管理ツール (ユーザーとコンピュータの管理 ツール) で Windows と Enterprise Services の両方のセキュリティを管理できます。

  • Enterprise Services アプリケーションのロールごとに Windows グループを作成します。

  • 各グループを該当するロールへ割り当てます。

    たとえば、Manager というロールに対して Managers という Windows グループを作成し、Managers グループを Manager ロールへ割り当てます。

  • ロールへグループを割り当てた後に、ユーザーとコンピュータの管理 ツールを使用して各グループでユーザーを追加、削除します。

    たとえば、David という Windows 2000 ユーザー アカウントを Windows 2000 グループ Managers に追加すると、David が Manager ロールへマップされます。

■ コンポーネント サービスを使用して Windows グループを Enterprise Services ロールに割り当てるには

  1. コンポーネント サービス ツールを使用して、Windows 2000 グループを追加するロールが含まれているアプリケーションを展開します。
  2. [ロール] フォルダを展開し、Windows グループを割り当てる特定のロールを展開します。
  3. ロールの下にある [ユーザー] フォルダを選択します。
  4. フォルダを右クリックし、[新規作成] をポイントし、[ユーザー] をクリックします。
  5. [ユーザー または グループ の選択] ダイアログ ボックスで、グループ (またはユーザー) をロールに追加します。

詳細情報

COM+ 管理オブジェクトを使用した COM+ カタログのプログラミングの詳細については、MSDN ライブラリの「Component Development」の「Automating COM+ Administration」(英語情報) を参照してください。

ID の構成

Enterprise Services アプリケーションの ID を構成するには、コンポーネント サービス ツールまたはスクリプトを使用します。アプリケーションをホストするDllhost.exe のインスタンスを実行するために使用されるアカウントは、ID プロパティにより決定します。

■ ID を構成するには

  1. コンポーネント サービス ツールを使用して該当のアプリケーションを選択します。
  2. アプリケーション名を右クリックし、[プロパティ] をクリックします。
  3. [ID] タブをクリックします。
  4. [このユーザー] をクリックし、アプリケーションの実行に使用する構成済みサービス アカウントを指定します。

詳細情報

Enterprise Services アプリケーションを実行するための適切な ID の選択方法の詳細については、後の「プロセス ID の選択」を参照してください。

ASP.NET クライアント アプリケーションの構成

クライアント アプリケーションが DCOM を使用してサービス対象のコンポーネントと通信する場合には、クライアント アプリケーションで使用される DCOM 認証レベルと偽装レベルを設定する必要があります。

認証の構成

ASP.NET Web アプリケーションがサービス対象のコンポーネントと通信するときに、ASP.NET Web アプリケーションで使用される既定の認証レベルを構成するには、Machine.config の <processModel> 要素の comAuthenticationLevel 属性を編集します。

Machine.config は、次のフォルダに格納されています。

%windir%\Microsoft.NET\Framework\v1.0.3705\CONFIG

comAuthenticationLevel 属性に、次のいずれかの値を設定します。

comAuthenticationLevel=
[Default|None|Connect|Call|Pkt|PktIntegrity|PktPrivacy]

詳細情報

DCOM 認証レベルの詳細については、後の「セキュリティの概念」の「認証」を参照してください。

偽装の構成

クライアントが設定する偽装レベルによって、サーバーの偽装レベル機能が決まります。Web アプリケーションがサービス対象のコンポーネントと通信するときに Web アプリケーションで使用される既定の偽装レベルを構成するには、Machine.config の <processModel> 要素の comImpersonationLevel 属性を編集します。comImpersonationLevel 属性に、次のいずれかの値を設定します。

comImpersonationLevel="[Default|Anonymous|Identify|Impersonate|Delegate]"

詳細情報

DCOM 偽装レベルの詳細については、後の「セキュリティの概念」の「偽装」を参照してください。

Enterprise Services アプリケーションの偽装レベルの構成

あるアプリケーションのサービス対象のコンポーネントが 第 2 (サーバー) アプリケーションのサービス対象のコンポーネントを呼び出す場合には、クライアント アプリケーションの偽装レベルを構成する必要があります。

重要 Enterprise Services アプリケーション向けに、このアプリケーションの [プロパティ] ダイアログ ボックスの [セキュリティ] タブで構成された偽装レベルは、アプリケーション内のコンポーネントにより発行される発信呼び出しで使用されます。この偽装レベルは、アプリケーションのサービス対象のコンポーネントが偽装を実行するかどうかには影響しません。サービス対象のコンポーネント内でクライアントを偽装するには、プログラムによる偽装手法を使用する必要があります。プログラムによる偽装については、後の「最初の呼び出し元のフロー」で詳しく説明します。

宣言を使用してアプリケーション偽装レベルを設定するには、アセンブリ レベルで ApplicationAccessControl 属性を次のように使用します。

[assembly: ApplicationAccessControl(
ImpersonationLevel=ImpersonationLevelOption.Identify)]

これは、コンポーネント サービスでアプリケーションの [プロパティ] ダイアログ ボックスの [セキュリティ] タブで、[偽装レベル] の値を設定する操作と同等です。

セキュリティのプログラミング

.NET コンポーネントでは、ContextUtil クラス、SecurityCallContext クラス、および SecurityIdentity クラスにより Enterprise Services セキュリティ機能が実現します。

プログラムによるロール ベースのセキュリティ

きめ細かな認定判断を実現するため、ContextUtil クラスの IsCallerInRole メソッドを使用してプログラムでロール メンバシップをテストできます。IsCallerInRole メソッドを呼び出す前に、常にコンポーネント レベルのアクセス チェックが有効であることを確認します。この確認操作を実行するコードを次に示します。セキュリティが無効になっていると、IsCallerInRole は常に true を返します。

public void Transfer(string fromAccount, string toAccount, double amount)
{
// Check that security is enabled
if (ContextUtil.IsSecurityEnabled) 
  {
// Only Managers are allowed to transfer sums of money in excess of $1000
if (amount > 1000)
    {
if (ContextUtil.IsCallerInRole("Manager"))
      {
// Caller is authorized
      }
else
      {
// Caller is unauthorized
      }
    }
}

呼び出し元の識別

サービス対象のコンポーネントからすべての上位呼び出し元を識別する方法を次に示します。

[ComponentAccessControl]
public class MyServicedComponent : ServicedComponent
{
public void ShowCallers()
  {
SecurityCallContext context = SecurityCallContext.CurrentCall;
SecurityCallers callers = context.Callers;
foreach(SecurityIdentity id in callers)
    {
Console.WriteLine(id.AccountName);
    }
  }
}

メモ 最初の呼び出し元の ID は、SecurityCallContext.OriginalCaller プロパティを使用して取得できます。

プロセス ID の選択

サーバーからアクティブ化された Enterprise Services アプリケーションは、Dllhost.exe プロセスのインスタンス内で実行されます。コンポーネント サービス ツールを使用し、このプロセスを実行するために使用するアカウントを COM+ カタログで構成する必要があります。

メモ .NET 属性を使用して実行時 ID を指定することはできません。

対話ユーザーとして実行しない

サーバー アプリケーションを実行するときには、既定の設定である、対話式にログオンしたユーザーの ID を使用しないことをお勧めします。対話ユーザーとして実行しない理由として、次の 2 つの事項があります。

  • サーバーに対話的にログオンするユーザーによって、アプリケーションの特権とアクセス権限が異なります。管理者がログオンすると、アプリケーションには管理者特権が設定されます。
  • ユーザーが対話的にログオンしているときにサーバー アプリケーションが起動されると、このユーザーがログオフするときにこのサーバー アプリケーションがシャットダウンされます。別のユーザーが対話的にログオンするまで、このサーバー アプリケーションを再起動できません。

対話ユーザー設定は開発者が開発時に使用するものです。展開時には対話ユーザー設定を使用しないでください。

最低限の特権が設定されたカスタム アカウントの使用

最低限の特権のアカウントを使用すると、プロセスが悪用される脅威を軽減できます。悪意のあるユーザーが、サーバー プロセスを突破した場合、そのプロセス アカウントに付与された特権やアクセス権を簡単に継承し、利用することができます。アカウントを最低限の特権で構成すると、発生する可能性のある損害が限定されます。

プロセス アカウントを使用してネットワーク リソースへアクセスする必要がある場合には、リモート コンピュータでプロセス アカウントを認証できるように設定しておく必要があります。この場合、次の 2 とおりの方法が可能です。

  • 2 つのコンピュータが、同一ドメインまたは信頼されているドメインに属している場合には、ドメイン アカウントを使用できます。

  • ローカル アカウントを使用し、リモート コンピュータに同じユーザー名とパスワードが設定された重複アカウントを作成します。この方法では、2 つのアカウントのパスワードを常に同期する必要があります。

    リモート コンピュータが信頼関係のない別のドメインに属する場合、またはリモート コンピュータがファイアウォールにより保護されており、ファイアウォールのポート設定が Windows 認証を許可しない場合には、重複ローカル アカウントを作成する必要があります。

ネットワーク リソースへのアクセス

サービス対象のコンポーネントが、リモート リソースへアクセスしなければならないことがあります。この場合、次の項目を特定できることが重要です。

  • コンポーネントがアクセスする必要のあるリソース。このようなリソースには、ファイル共有のファイル、データベース、他の DCOM サーバー、Active Directory® ディレクトリ サービス オブジェクトなどがあります。
  • リソースへのアクセスを実行するために使用される ID。サービス対象のコンポーネントがリモート リソースへアクセスするときに使用する ID (既定では、プロセス ID) は、リモート コンピュータにより認証可能である必要があります。

メモ リモートの SQL Server データベースへのアクセスについての詳細は、「第 12 章 データ アクセス セキュリティ」を参照してください。

Enterprise Services アプリケーションのコンポーネントから、次のいずれかの ID を使用してリモート リソースへアクセスできます。

  • CoImpersonateClient を使用して明示的に偽装している場合、最初の呼び出し元
  • サーバー アプリケーションに対して COM+ カタログで構成されている現在のプロセス ID
  • 特定のサービス アカウント

最初の呼び出し元の使用方法

リモート リソースへアクセスするときに最初の呼び出し元の ID を使用する場合の条件を次に示します。

  • プログラムを使用して CoImpersonateClient を呼び出し、最初の呼び出し元を偽装できる場合。
  • Enterprise Services アプリケーションをホスティングするアプリケーション サーバーから、リモート コンピュータへ呼び出し元のセキュリティ コンテキストを委任できる場合。これは、Enterprise Services アプリケーションとクライアント アプリケーションの間で Kerberos 認証を使用していることを前提としています。

スケーラビリティに関する警告 最初の呼び出し元の偽装 ID を使用して、アプリケーションのデータ サービス層へアクセスすると、アプリケーションの拡張性に重大な影響を及ぼします。この原因は、各データベース接続のセキュリティ コンテキストが多くの呼び出し元に結びついているために、データベース接続プールが効率的に機能できなくなるためです。

詳細情報

呼び出し元の偽装の詳細については、後の「最初の呼び出し元のフロー」を参照してください。

現在のプロセス ID の使用方法

サーバー アプリケーションとして実行されるように構成されているアプリケーションの場合、構成済みプロセス ID を使用してリモート リソースへアクセスできます。これが既定の設定です。

サーバー プロセス アカウントを使用してリモート リソースへアクセスするには、次のいずれかの操作を実行してください。

  • 最低限の特権が付与されているドメイン アカウントを使用してサーバー アプリケーションを実行します。これは、クライアントおよびサーバーのコンピュータが同じドメインまたは信頼関係のあるドメイン内にあることを前提としています。
  • リモート コンピュータに、同一のユーザー名とパスワードを使用するプロセス アカウントを複製します。

管理を容易にすることを目的としている場合には、最低限の特権が付与されたドメイン アカウントを使用してください。

ライブラリ アプリケーションとして実行するよう構成されているアプリケーションの場合、プロセス ID はホスト プロセスから継承されます。このようなホスト プロセスは、多くの場合 Web ベース アプリケーションのホスト プロセスです。ASP.NET プロセス ID を使用して、リモート リソースへアクセスする方法の詳細については、「第 8 章 ASP.NET セキュリティ」を参照してください。

特定のサービス アカウントの使用方法

特別に構成されたサービス アカウント、つまり、非ユーザー Windows アカウント を使用して Enterprise Services アプリケーションからリモート リソースへアクセスすることができます。ただし、このアクセス方法は LogonUser API を呼び出すことを前提としているので、Windows 2000 ではこの方法でアクセスすることはお勧めできません。

Windows 2000 で LogonUser を使用する場合には、Enterprise Services プロセス アカウントに "オペレーティング システムの一部として動作する" 特権を付与する必要があります。この特権を付与すると、アプリケーションのセキュリティが著しく低下します。

メモ Windows Server 2003 では、この制限が改善される予定です。

最初の呼び出し元のフロー

既定では、ローカル リソースまたはリモート リソースへアクセスする場合などにコンポーネントが発行した発信呼び出しを、ホスト プロセスから取得したセキュリティ コンテキストを使用して作成しています。サーバー アプリケーションの場合、これは構成済み実行時 ID です。ライブラリ アプリケーションの場合、これは (ホスト) クライアント プロセスの ID です。たとえば、ASP.NET Web アプリケーションがクライアントの場合、クライアント プロセスは Aspnet_wp.exe です。

■ Enterpries Services アプリケーションを介して最初の呼び出し元のコンテキストをフローするには

  1. CoImpersonateClient を呼び出します。

    この呼び出しにより、現在のスレッドにスレッド偽装トークンが追加されます。

  2. ローカル リソースまたはリモート リソースへのアクセスを実行します。

    偽装が有効になっている場合には、偽装トークンの定義に従い、クライアントのセキュリティ コンテキストを使用して発信呼び出しが発行されます。

    ローカル リソースにアクセスする場合、呼び出し元のクライアント プロセスでは Impersonate 以上のレベルの偽装を指定している必要があります。リモート リソースにアクセスする場合、呼び出し元では Delegate レベルの偽装を指定している必要があります。

    呼び出し元が ASP.NET Web アプリケーションの場合、ASP.NET ワーカー プロセスの既定の偽装レベルは Impersonate です。したがって、最初の呼び出し元を下位リモート コンピュータへフローするには、既定レベルの Impersonate を Delegate へ変更する必要があります。既定レベルを変更するには、クライアント コンピュータの Machine.config の <processModel> 要素を編集します。

    メモ 最初の呼び出し元のセキュリティ コンテキストを使用してリモート リソースへアクセスするには、委任できるように構成されているアカウントで Kerberos 認証を使用してください。Enterprise Services サーバー アプリケーションの実行に使用するアカウントは、Active Directory で "アカウントは委任に対して信頼されている" としてマークされている必要があります。

  3. 偽装を終了するため、CoRevertToSelf を呼び出します。

    これにより、偽装トークンが削除されます。この時点以降に現在のメソッドから行われる呼び出しでは、プロセスのセキュリティ コンテキストが使用されます。CoRevertToSelf を呼び出すことができなかった場合には、メソッドの終了時にランタイムにより CoRevertToSelf が暗黙に呼び出されます。

メモ 最初の呼び出し元の ID は、Enterprise Services アプリケーションへ自動的にフローします。この ID を利用するには SecurityCallContext.OriginalCaller を使用します。これは、監査の目的で利用すると便利です。

CoImpersonateClient の呼び出し

CoImpersonateClient および CoRevertToSelf は OLE32.dll 内にあります。P/Invoke を介して CoImpersonateClient と CoRevertToSelf を呼び出すことができるようにするため、DllImport 属性を使用してこれらの関数の定義をインポートする必要があります。以下のコードは、この処理を示したものです。

class COMSec 
{ 
[DllImport("OLE32.DLL", CharSet=CharSet.Auto)] 
public static extern uint CoImpersonateClient(); 

[DllImport("OLE32.DLL", CharSet=CharSet.Auto)] 
public static extern uint CoRevertToSelf(); 
} 
. . .
void SomeMethod()
{
// To flow the original caller's security context and use it to access local
// or remote resources, start impersonation 
COMSec.CoImpersonateClient(); 
// Perform operations as the caller
// Code here uses the context of the caller - not the context of the process 
  . . .
COMSec.CoRevertToSelf();
// Code here reverts to using the process context
}

詳細情報

完全な Kerberos 委任シナリオの構成方法の詳細については、「第 5 章 イントラネット セキュリティ」の「最初の呼び出し元をデータベースにフローする」を参照してください。この章では、最初の呼び出し元のセキュリティ コンテキストを、ASP.NET Web アプリケーション、Enterprise Services アプリケーション、およびデータベースへフローする方法を説明しています。

RPC 暗号化

クライアント アプリケーションからリモート サービス対象のコンポーネントへ DCOM 経由で送信されるデータを保護するには、クライアントとサーバーの間で RPC Packet Privacy 認証レベルを使用します。この認証レベルを使用することで、メッセージの機密と整合性が維持されます。

クライアントとサーバーで認証レベル RPC Packet Privacy を構成する必要があります。

クライアントが ASP.NET Web アプリケーションである ASP.NET を構成するには、machine.config の <processModel> 要素の comAuthenticationLevel 属性に PktPrivacy を設定します。

Enterprise Services サーバー アプリケーションを構成するには、アプリケーション レベルで認証レベルを設定します。認証レベルを設定するときには、コンポーネント サービス ツールを使用するか、サービス対象のコンポーネント アセンブリ内で次の .NET 属性を使用します。

[assembly: ApplicationAccessControl(
Authentication = AuthenticationOption.Privacy)]

詳細情報

  • 認証レベルなどのセキュリティの構成方法の詳細については、前の「セキュリティの構成」を参照してください。
  • RPC/DCOM 認証レベルの詳細については、後の「認証」を参照してください。
  • 認証レベルのネゴシエーションの詳細については、後の「認証レベルのネゴシエーション」を参照してください。

サービス対象のコンポーネントの作成

サービス対象のコンポーネントの作成手順については、このガイドの「パート IV : 参照」の「Enterprise Servises でロールを基準としたセキュリティを使用する方法」を参照してください。

DLL ロックの問題

サービス対象のコンポーネントを再作成するときに DLL がロックされている場合には、次のように対処します。

  • コンポーネント サービスを使用して COM+ サーバー アプリケーションをシャットダウンします。
  • ライブラリ アプリケーションを開発している場合には、Aspnet_wp.exe プロセスにアプリケーションがロードされている可能性があります。コマンド プロンプトから IISReset を実行するか、タスク マネージャを使用して Aspnet_wp.exe プロセスを停止します。
  • https://www.sysinternals.com/ Non-MS link の FileMon.exe を使用してファイル ロックの問題を解決します。

バージョン管理

新しいプロジェクトを作成すると Microsoft Visual Studio® .NET 開発システムにより、次の既定の AssemblyVersion 属性が生成されます。

[assembly: AssemblyVersion("1.0.*")]

プロジェクトを再作成するたびに、新しいアセンブリ バージョンが生成されます。また、サービス対象のコンポーネントのクラスを識別する新しいクラス ID (CLSID) も生成されます。Regsvcs.exe を使用してコンポーネント サービスにアセンブリを登録する操作を繰り返し実行する場合は、重複するコンポーネント (厳密にはクラス) に異なる CLSID が割り当てられます。この CLSID の一覧は、コンポーネント フォルダの下に示されます。

この CLSID 割り当ては厳密な COM バージョン管理セマンティクスに準拠しており、既存のマネージ クライアントとアンマネージ クライアントの破損を防ぎますが、開発時には煩わしいことがあります。

テストと開発の段階では、次に示すアセンブリ レベル AssemblyVersion 属性を使用して明示的にバージョンを設定することを検討してください。

[assembly: AssemblyVersion("1.0.0.1")]

この設定では、プロジェクト ビルドのたびに新しい CLSID が生成されることが防止されます。必要に応じて、インターフェイス ID (IID) も固定します。クラスが明示的なインターフェイスを実装する場合には、特定のインターフェイスの IID を固定できます。IID を固定するには、Guid 属性を次のように使用します。

[Guid("E1FBF27E-9F11-474d-8DF6-58916F798E9D")]
public interface IMyInterface
{
}

■ 新しい GUID を生成するには

  1. Visual Studio .NET の [ツール] メニューの [GUID の作成] をクリックします。
  2. [Registry Format] をクリックします。
  3. [New GUID] をクリックします。
  4. [Copy] をクリックします。
  5. クリップ ボードの GUID をソース コードに貼り付けます。

重要 テストおよび本稼動用にサービス対象のコンポーネント アセンブリを展開する前に、修正した GUID をすべて削除し、"1.0.*" などを使用して自動アセンブリ バージョン管理メカニズムに戻します。自動アセンブリ バージョン管理メカニズムに戻さないと、コンポーネントの新しいリリースが原因で既存のクライアントが壊れる可能性が高くなります。

詳細情報

展開のためのバージョン管理の詳細については、MDSN ライブラリの「.NET における Enterprise Services (COM+) について」を参照してください。

QueryInterface の例外

IRoleSecurity インターフェイスに対する QueryInterface 呼び出しが失敗した場合、アセンブリ内でインターフェイス定義が更新されていますが、Regsvcs.exe を使用してコンポーネント サービスにアセンブリが再登録されていないことを示します。

重要 Regsvcs.exe を実行するたびに、サーバー アプリケーションの実行時 ID を再構成し、ユーザーをグループに追加し直す必要があります。この操作を自動的に実行する単純なスクリプトを作成できます。

DCOM とファイアウォール

Windows 2000 (SP3 または QFE 18.1) または Windows Server 2003 では、静的エンドポイントを使用するように Enterprise Services アプリケーションを構成できます。クライアントとサーバーの間にファイアウォールが構築されている場合には、ファイアウォールの 2 つのポートを開く必要があります。開く必要のあるポートは、RPC 用のポート 135 と Enterprise Services アプリケーション用のポートです。

これに代わる方法としては、Enterprise Services アプリケーションを Web サービスとして公開する方法があります。Enterprise Services アプリケーションを公開すると、ポート 80 経由で SOAP を使用し、サービス対象のコンポーネントをアクティブ化して呼び出すことができます。ただし、この方法の問題点は、クライアントからサーバーへトランザクション コンテキストをフローできない点です。このため、リモート サービス対象のコンポーネントでトランザクションを開始する必要があります。

詳細情報

詳細については、以下の Microsoft サポート技術情報の Knowledge Base の文書を参照してください。

ASP.NET からのサービス対象のコンポーネントの呼び出し

ここでは、ASP.NET アプリケーションからサービス対象のコンポーネントを呼び出す際の主な課題を中心に説明します。

呼び出し元の ID

ASP.NET アプリケーションからサービス対象のコンポーネントを呼び出すと、アプリケーションの Win32® スレッド ID から呼び出しのセキュリティ ID が取得されます。呼び出し元を偽装するように Web アプリケーションが構成されている場合には、これが呼び出し元の ID になります。呼び出し元の偽装が構成されていない場合には、ASP.NET プロセス ID (既定では、ASPNET) になります。

ASP.NET アプリケーションから現在の Win32 スレッド ID を取得するには、WindowsIdentity.GetCurrent() を呼び出します。

サービス対象のコンポーネントから最初の呼び出し元の ID を取得するには、SecurityCallContext.OriginalCaller を使用します。

Web ベース アプリケーションでの Windows 認証と偽装の使用方法

Enterprise Services アプリケーション内で適切なロール ベースのセキュリティを有効にするには、Windows 認証を使用して偽装を有効にします。これにより、サービス対象のコンポーネントが最初の呼び出し元を認証し、最初の呼び出し元の ID に基づいて認定を決定できます。

Machine.config での認証と偽装の構成方法

DCOM 認証レベルは、クライアント (Web ベース アプリケーションなど) とサーバー (Enterprise Services アプリケーションなど) の間でネゴシエートされます。2 つのセキュリティ設定のいずれか高い方の設定が使用されます。

ASP.NET 認証レベルを構成するには、Machine.config の <processModel> 要素の comAuthenitcation 属性を使用します。

偽装レベルはWeb ベース アプリケーションなどのクライアントにより制御されます。サーバーで使用できる偽装のレベルをクライアントが決定できます。

すべての発信 DCOM 呼び出しの ASP.NET 偽装レベルを構成するには、Machine.config の <processModel> 要素の comImpersonationLevel 属性を使用します。

インターフェイス プロキシの構成方法

各インターフェイス プロキシに適用されるセキュリティ設定は、一般に既定のプロセス レベル セキュリティ設定から取得されます。ASP.NET では、前に述べたように既定のセキュリティ設定 (偽装レベルや認証レベルなど) が Machine.config で構成されています。

必要に応じて、各インターフェイス プロキシにより使用されるセキュリティ設定を変更できます。たとえば、ASP.NET アプリケーションと通信するサービス対象のコンポーネントにより 2 つのインターフェイスが公開されており、機密データがそのうちの 1 つのインターフェイス経由でのみ受け渡される場合には、認証レベル Packet Privacy の暗号化サポートを機密データのインターフェイスでのみ使用し、もう 1 つのインターフェイスで Packet 認証を実行するように設定できます。つまり、両方のインターフェイスに対して暗号化をかけた際に発生するパフォーマンス低下を回避することができます。

インターフェイス プロキシに適用するセキュリティ設定のまとまりは、セキュリティ ブランケットと呼ばれます。次に示す COM の関数を使用して、各インターフェイス プロキシのセキュリティ ブランケット設定を照会、操作することができます。

  • CoQueryProxyBlanket
  • CoSetProxyBlanket
  • CoCopyProxy

これらの関数を ASP.NET Web アプリケーション (DCOM クライアント) から呼び出すには、必ず P/Invoke を使用してください。Packet Privacy 認証レベルを使用して特定のインターフェイスを構成するコードを次に示します。このコードは、リモート サービス対象のコンポーネントと通信する ASP.NET Web アプリケーションから使用できます。

// Define a wrapper class for the P/Invoke call to CoSetProxyBlanket
class COMSec 
{ 
// Constants required for the call to CoSetProxyBlanket
public const uint RPC_C_AUTHN_DEFAULT           = 0xFFFFFFFF;
public const uint RPC_C_AUTHZ_DEFAULT           = 0xFFFFFFFF;
public const uint RPC_C_AUTHN_LEVEL_PKT_PRIVACY = 6;
public const uint RPC_C_IMP_LEVEL_DEFAULT       = 0;
public const uint COLE_DEFAULT_AUTHINFO         = 0xFFFFFFFF;
public const uint COLE_DEFAULT_PRINCIPAL        = 0;
public const uint EOAC_DEFAULT                  = 0x800;

// HRESULT  CoSetProxyBlanket( IUnknown * pProxy,
//                             DWORD dwAuthnSvc,
//                             DWORD dwAuthzSvc,
//                             WCHAR * pServerPrincName, 
//                             DWORD dwAuthnLevel,
//                             DWORD dwImpLevel,
//                             RPC_AUTH_IDENTITY_HANDLE pAuthInfo,
//                             DWORD dwCapabilities ); 
[DllImport("OLE32.DLL", CharSet=CharSet.Auto)] 
public unsafe static extern uint CoSetProxyBlanket( 
IntPtr pProxy,
uint dwAuthnSvc,
uint dwAuthzSvc,
IntPtr pServerPrincName,
uint dwAuthnLevel,
uint dwImpLevel,
IntPtr pAuthInfo,
uint dwCapababilities);
} // end class COMSec


// Code to call CoSetProxyBlanket
void CallComponent()
{
// This is the interface to configure
Guid IID_ISecureInterface = new Guid("c720ff19-bec1-352c-bb4b-e2de10b858ba");
IntPtr pISecureInterface;

// Instantiate the serviced component
CreditCardComponent comp = new CreditCardComponent();
// Get its IUnknown pointer
IntPtr pIUnk = Marshal.GetIUnknownForObject(comp);
// Get the interface to configure
Marshal.QueryInterface(pIUnk, ref IID_ISecureInterface, 
out pISecureInterface);
try
  {
// Configure the interface proxy and set packet privacy authentication
uint hr = COMSec.CoSetProxyBlanket( pISecureInterface, 
COMSec.RPC_C_AUTHN_DEFAULT,
COMSec.RPC_C_AUTHZ_DEFAULT,
IntPtr.Zero,
COMSec.RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
COMSec.RPC_C_IMP_LEVEL_DEFAULT,
IntPtr.Zero,
COMSec.EOAC_DEFAULT );
ISecureInterface secure = (ISecureInterface)comp;
// The following call will be encrypted as ISecureInterface is configured
// for packet privacy authentication.Other interfaces use the process 
// level defaults (normally packet authentication).
secure.ValidateCreditCard("123456789");
  }
catch (Exception ex)
  {
  }
}

詳細情報

  • サービス対象のコンポーネントを呼び出すように ASP.NET クライアント アプリケーションを構成する方法の詳細については、前の「ASP.NET クライアント アプリケーションの構成」を参照してください。
  • DCOM 認証レベルの詳細については、後の「認証」を参照してください。
  • DCOM 偽装レベルの詳細については、後の「偽装」を参照してください。
  • Web ベース アプリケーションで Windows 認証を使用して偽装を有効にする方法の詳細については、「第 8 章 ASP.NET セキュリティ」を参照してください。

セキュリティの概念

ここでは、Enterprise Services セキュリティの概念について説明します。COM+ を使用した経験がある場合は、ここで説明する概念の多くをすでに把握している場合があります。

Enterprise Services の背景情報については、MSDN ライブラリの「.NET における Enterprise Services (COM+) について」を参照してください。

理解しておくべき主要なセキュリティの概念を次に示します。

  • サービス対象のコンポーネントと Enterprise Services アプリケーションのセキュリティ設定は、COM+ カタログで管理されます。ほとんどの設定は、.NET 属性を使用して構成できます。すべての設定は、コンポーネント サービス管理ツールまたは Microsoft Visual Basic® Scripting Edition 開発システム スクリプトを使用して構成できます。
  • 認定機能は Enterprise Services (COM+) のロールにより実現します。Enterprise Services (COM+) ロールには、Windows オペレーティング システムのシステム グループやユーザー アカウントを含めることができます。これは .NET ロールとは別のものになります。
    • ロール ベースのセキュリティは、アプリケーション、インターフェイス、クラス、およびメソッドのレベルで適用できます。
    • プログラムによりメソッド内で強制ロール チェックを実行するには、ContextUtil クラスの IsCallerInRole メソッドを使用します。

Enterprise Services アプリケーション内で実行されるロール ベースの認定機能は、サービス対象のコンポーネントを呼び出すときに Windows ID を使用することに依存します。

  • ASP.NET Web アプリケーションが呼び出すサービス対象のコンポーネントが Enterprise Services (COM+) ロールに依存している場合には、ASP.NET Web アプリケーションで偽装と Windows 認証を組み合わせて使用する必要があります。
  • ASP.NET Web アプリケーションまたは Web サービスからサービス対象のコンポーネントを呼び出すと、WindowsIdentity.GetCurrent() に定義されている、発信 DCOM 呼び出しに使用される ID が Win32 スレッド ID により決定します。

サービス対象のコンポーネントは、サーバー アプリケーションまたはライブラリ アプリケーションで実行できます。

  • サーバー アプリケーションは Dllhost.exe の個別インスタンスで実行されます。
  • ライブラリ アプリケーションはクライアントのプロセスのアドレス空間で実行されます。
  • ロール ベースの認定は、サーバー アプリケーションとライブラリ アプリケーションでは同様に機能しますが、ライブラリ アプリケーションとサーバー アプリケーションにはセキュリティの面からわずかに異なる点があります。詳細については、前の「サーバー アプリケーションとライブラリ アプリケーションのセキュリティ」を参照してください。

認証機能は、DCOM および RPC の基礎となるサービスにより実現します。サービス対象のコンポーネントとの通信には、クライアントの認証レベルとサーバーの認証レベルを組み合わせた認証レベルが使用されます。

偽装はクライアント アプリケーション内で構成されます。クライアント アプリケーションで構成された偽装により、サーバーの偽装レベルが決定します。

Enterprise Services (COM+) ロールと .NET ロール

Enterprise Services (COM+) ロールは、アプリケーション内で同一セキュリティ特権を共有するユーザーの共通カテゴリを表します。Enterprise Services (COM+) ロールは .NET ロールと概念の面で類似していますが、.NET ロールからは完全に独立しています。

Enterprise Services (COM+) ロールには、Windows のユーザー アカウントとグループ アカウントを含めることができます。この点が、任意の非 Windows ユーザー ID を含めることができる .NET ロールとは異なります。したがって Enterprise Services (COM+) ロールは、呼び出し元のセキュリティ コンテキストを Enterprise Services アプリケーションにフローするために、Windows 認証と偽装を使用するアプリケーションのみに効果的な認定メカニズムです。

表 9.1 Enterprise Services (COM+) ロールと .NET ロールの比較

機能 Enterprise Services (COM+) ロール .NET ロール
管理 [コンポーネント サービス] 管理ツール。 カスタム
データ ストア COM+ カタログ。 カスタム データ ストア (SQL Server、Active Directory など)
宣言型 可能。
[SecurityRole("Manager")]
可能
[PrincipalPermission(SecurityAction.Demand, Role="Manager")]
強制型 可能。
ContextUtil.IsCallerInRole()
可能
IPrincipal.IsInRole
クラス、インターフェイス、およびメソッド レベルの細分化 可能。 可能
拡張性 不可。 可能
(カスタム IPrincipal 実装を使用)
すべての .NET コンポーネントでの使用 ServicedComponent ベース クラスに基づくコンポーネントのみ。 可能
ロール メンバシップ Windows のグループ アカウントまたはユーザー アカウントを含むロール。 WindowsPrincipal を使用する場合、ロールは Windows グループ (特別なレベルの抽象化なし)
明示的なインターフェイス実装の必要性 はい。
メソッド レベルの認定を取得するには、インターフェイスの明示的な定義および実装が必要。
いいえ

認証

Enterprise Services は COM+ と DCOM/RPC により提供される基礎インフラストラクチャに依存しているので、Enterprise Services アプリケーションで利用できる認証レベルは、RPC で定義され、DCOM で使用される認証レベルです。

表 9.2 Enterprise Services アプリケーションの認証設定

認証レベル 説明
既定値 標準のネゴシエーション ルールを使用して認証レベルを選択します。
None 認証なし。
Connect クライアントが初めてサーバーに接続するときにだけ資格情報を認証します。
Call リモート プロシージャ コールを開始するたびに認証を行います。
Packet クライアントから受信したすべてのデータを認証します。
Packet Integrity すべてのデータを認証し、転送データが一切変更されていないことを確認します。
Packet Privacy すべてのデータを認証し、各リモート プロシージャ コールのパラメータ状態を暗号化します。

認証レベルの昇格

特定の認証レベルは暗黙に昇格されることに注意してください。次に、例を示します。

  • Connect レベルと Call レベルは TCP などの接続指向トランスポートでのみ有効なので、UDP (User Data Protocol) データグラム トランスポートが使用される場合には Connect レベルと Call レベルが Packet レベルに昇格されます。

    メモ Windows 2000 では、既定で RPC over TCP が DCOM 通信に使用されます。

  • 1 台のコンピュータでのプロセス間呼び出しの場合は、すべての認証レベルが常に Packet Privacy に昇格されます。ただし、この場合、データがネットワーク経由で転送されないので、機密保持のためのデータ暗号化は実行されません。

認証レベルのネゴシエーション

Enterprise Services でクライアントの認証に使用される認証レベルは、次の 2 つの設定によって決まります。

  • プロセス レベルの認証レベル サーバーによりアクティブ化されたアプリケーション (Dllhost.exe 内で実行されているアプリケーション) の場合、プロセス レベルの認証レベルは COM+ カタログで構成されています。

  • クライアントの認証レベル サービス対象のコンポーネントと通信するクライアント プロセスの構成済み認証レベルは、使用される認証レベルに影響します。

    ASP.NET Web アプリケーションの既定の認証レベルは、Machine.config の <processModel> 要素の comAuthenticationLevel 属性によって決まります。

クライアントとサーバーの 2 つの認証レベルのいずれか高い方の認証レベルが常に選択されます。これを図 9.4 に示します。

図 9.4 認証レベルのネゴシエーション

詳細情報

Enterprise Services アプリケーションの認証レベルの構成方法については、前の「セキュリティの構成」を参照してください。

偽装

Enterprise Services アプリケーションに対して定義されている偽装レベルにより、アプリケーション内から発行される発信 DCOM 呼び出しの偽装レベルが決まります。

重要 アプリケーションのサービス対象のコンポーネントが呼び出し元を偽装するかどうかは決定しません。既定では、サービス対象のコンポーネントは呼び出し元を偽装しません。呼び出し元を偽装するには、サービス対象のコンポーネントが CoImpersonateClient を呼び出す必要があります。CoImpersonateClient 呼び出しについては、前の「最初の呼び出し元のフロー」で詳しく説明しています。

偽装はクライアント側の設定です。クライアントはサーバーの偽装機能を制限できるので、偽装を利用することでクライアントを保護できます。

表 9.3 設定できる偽装レベル

偽装レベル 説明
Identify サーバーがクライアントを識別し、クライアントのアクセス トークンを使用してアクセス チェックを実行できます。
Impersonate サーバーがクライアントの資格情報を使用してローカル リソースへアクセスできます。
Delegate サーバーがクライアントの資格情報を使用してリモート リソースへアクセスできます。この場合、Kerberos および特定のアカウント構成が必要となります。

Web ベースのアプリケーションがサービス対象のコンポーネントまたは DCOM を使用するコンポーネントと通信するときに、この Web ベースのアプリケーションで使用される既定の偽装レベルを設定するには、Machine.config の <processModel> 要素の comImpersonationLevel 属性を編集します。

クローク

クロークは、偽装時にクライアントの ID が COM オブジェクト プロキシを介してサーバーに反映される方法を詳細に決定します。次の 2 種類のクロークがあります。

  • 動的クローク Enterprise Services サーバー アプリケーションは、動的クロークを使用します。この動的クロークは構成することができません。ライブラリ アプリケーションのクロークは、ASP.NET ワークプロセス (Aspnet_wp.exe) などのホスト プロセスにより決定されます。Web ベースのアプリケーションも動的クロークを使用します。Enterprise Services サーバー アプリケーションと同様に、このクロークは構成することができません。

    動的クロークでは、偽装時にクライアントの ID を表すためにスレッド偽装トークンが使用されます。つまり、サービス対象のコンポーネント内で CoImpersonateClient を呼び出すと、この時点以降、CoRevertToSelf が呼び出されるか、CoRevertToSelf が暗黙に呼び出され、メソッドが終了するまで、同一メソッドにより発行される発信呼び出しでは、クライアントの ID が想定されます。

  • 静的クローク 静的クロークでは、発信呼び出し時にスレッドが偽装するかどうかにかかわらず、クライアントからサーバーへの初めての呼び出しで使用された資格情報がサーバーで使用されます。

詳細情報

Enterprise Services アプリケーションの偽装レベルの構成方法については、前の「セキュリティの構成」を参照してください。

クロークの詳細については、MSDN ライブラリの Platform SDK の「Cloaking」 (英語情報) の情報を参照してください。

まとめ

この章では、Enterprise Services アプリケーション内でセキュリティで保護されたサービス対象のコンポーネントを作成する方法について説明しました。また、サービス対象のコンポーネントを呼び出す ASP.NET Web ベース クライアント アプリケーションの構成方法についても説明しました。この章のまとめは以下のとおりです。

  • セキュリティを強化するには、サーバーによりアクティブ化された Enterprise Services アプリケーションを使用します。プロセス ホップを追加することでもセキュリティが強化されます。

  • 最低限の特権が設定されたローカル アカウントを使用してサーバー アプリケーションを実行します。

  • サービス対象のコンポーネントからネットワーク経由でクライアント アプリケーションへ送信するデータをセキュリティで保護する必要がある場合には、Packet Privacy レベルの認証を使用します。この場合、Packet Privacy レベルの認証がサーバーとクライアントの両方で設定されている必要があります。

  • ロール ベースのセキュリティを適切に実装するために、コンポーネント レベルのアクセス チェックを有効にします。

  • ロール ベースのセキュリティに依存している Enterprise Services アプリケーション内でコンポーネントを呼び出す前に、Windows 認証を使用し、ASP.NET Web アプリケーションで偽装を有効にします。

  • Enterprise Services アプリケーションのエントリ ポイントとして、セキュリティで保護されているゲートウェイ クラスを使用します。

    ロールを割り当てる必要のあるクラスの数を削減するには、クライアントに対し Enterprise Services アプリケーションへのエントリ ポイントとなるゲートウェイ クラスの数を減らします。その他の内部ヘルパ クラスでは、ロール ベースのチェックが有効になっている必要があります。ただし、これらのクラスにはロールは割り当てません。つまり、外部クライアントは内部ヘルパ クラスを直接呼び出すことができませんが、同一アプリケーションのゲートウェイ クラスは内部ヘルパ クラスへ直接アクセスすることができます。

  • ロール メンバシップをプログラムでチェックする直前に、IsSecurityEnabled を呼び出します。

  • 中間層では偽装を実施しないでください。中間層で偽装を実施すると、データベース接続プールを有効に利用できず、アプリケーションのスケーラビリティが大幅に低下します。

  • 柔軟性を向上し、管理を容易にするため、Windows グループを Enterprise Services (COM+) ロールに追加します。

patterns and practices home