セキュリティ保護されたサービス コンポーネントを構築する
公開日: 2004年9月7日 | 最終更新日: 2004年9月7日
トピック
モジュールの内容
目的
適用対象
モジュールの使用方法
概要
脅威とその対策
設計に関する考慮事項
認証
承認
構成管理
機密性の高いデータ
監査とログ記録
セキュリティ保護されたサービス コンポーネントを構築する
コード アクセス セキュリティに関する考慮事項
展開の考慮事項
要約
その他のリソース
モジュールの内容
サービス コンポーネントとは、COM+ インフラストラクチャ サービス (別名 Enterprise Services) のことです。このコンポーネントは、マネージ コードからのアクセスが可能で、System.EnterpriseServices.ServicedComponent から派生したマネージ クラスから成ります。
このモジュールでは、Enterprise Services (COM+) セキュリティで Windows セキュリティを利用して呼び出し側の認証および承認を行う方法、および確実なコーディング技法や適切なカタログ構成によってサービス コンポーネントのセキュリティ保護された展開を確実に行うことができるしくみについて説明します。
このモジュールは、開発者に重点が置かれており、セキュリティ保護されたサービス コンポーネントの作成方法に関する例も挙げています。
目的
このモジュールの目的は次のとおりです。
-
COM+ インフラストラクチャ サービス (サービス コンポーネント) の設計時や展開時の考慮事項を理解する。
-
機密性の高いデータを保護する。
-
Enterprise Services (COM+) のロールを利用して呼び出し側を承認する。
-
最低限の権限を持つ run-as アカウントを使用する。
-
オブジェクト コンストラクタ文字列でシークレットをセキュリティ保護する。
-
中間層サービス コンポーネントで監査する。
-
セキュリティ保護されたサービス コンポーネントには完全な信頼が求められるため、部分的に信頼できる状況で行う必要のある処理を理解する。
-
ネットワーク盗聴、権限のないアクセス、無制限な委任、構成データの漏えい、および否認などの一般的な Enterprise Services の脅威に対処するために適用する対策について理解する。
適用対象
このモジュールは、次の製品およびテクノロジに適用されます。
モジュールの使用方法
このモジュールから最大限の成果を得るには、以下を参照してください。
-
このモジュールを、モジュール 17「アプリケーション サーバーをセキュリティ保護する」の「Enterprise Services」と組み合わせて使用します。モジュール 17 のこの部分では、Enterprise Services インフラストラクチャをセキュリティ保護する方法、および展開した Enterprise Services アプリケーションを制限する方法について説明します。
-
モジュール 7「セキュリティ保護されたアセンブリを構築する」に挙げた推奨事項に従います。このモジュールでは、サービス コンポーネント コードの開発時に適用できるセキュリティ保護されたコーディング手法を指導します。
概要
COM+ インフラストラクチャ サービス (別名 Enterprise Services) には、マネージ コードからアクセスすることもできます。Enterprise Services アプリケーションは、System.EnterpriseServices.ServicedComponent から派生したマネージ クラスである 1 つ以上のサービス コンポーネントから成ります。
一般に、サービス コンポーネントは、アプリケーションのビジネス ロジックやデータ アクセス ロジックをカプセル化するために使用され、また分散トランザクション、オブジェクト プール、キューに登録されたコンポーネントなどのインフラストラクチャ サービスがアプリケーションの中間層で必要な場合に使用されます。Enterprise Services アプリケーションは、多くの場合、図 11.1 に示す中間層アプリケーション サーバーに常駐します。
.jpg)
図 11.1:
中間層 Enterprise Services アプリケーションにおけるサービス コンポーネント
脅威とその対策
サービス コンポーネントの構築時に対処する必要のある主要な脅威は、以下のとおりです。
-
ネットワーク盗聴
-
権限のないアクセス
-
無制限な委任
-
設定データの漏えい
-
否認
図 11.2 は、こうした主要な脅威を一般的なサービス コンポーネントの脆弱性と共に示しています。
.jpg)
図 11.2:
Enterprise Services の脅威
ネットワーク盗聴
Enterprise Services アプリケーションは、一般に Web サーバーから離れた中間層アプリケーション サーバーで実行します。そのため、機密性の高いアプリケーション データは、ネットワーク盗聴者から保護する必要があります。Web サーバーとアプリケーション サーバーの間で Internet Protocol Security (IPSec) 暗号化チャネルを使用できます。このソリューションは、インターネット データ センターで一般的に使用されます。サービス コンポーネントでは、パケット ベースの暗号化を提供する Remote Procedure Call (RPC) パケット レベル認証もサポートしています。この機能は、デスクトップ ベースのクライアントに対する双方向の通信をセキュリティ保護するために最も一般的に使用されます。
権限のないアクセス
COM+ ロール ベースの承認を有効にすれば (Microsoft Windows 2000 の既定では無効)、匿名アクセスを防止し、サービス コンポーネントで公開された限定操作へのアクセスを制御するためにロール ベースの承認を提供できます。
無制限な委任
クライアントの偽装トークンを使用してリモート サーバーからネットワーク リソースにアクセスできるように Windows 2000 で委任を有効にしている場合、その委任は制限されません。つまり、構成できるネットワーク ホップ数は制限されないということです。Microsoft Windows Server 2003 では、制限された委任が導入されています。
設定データの漏えい
多くのアプリケーションでは、オブジェクト コンストラクタ文字列を使用してデータベース接続文字列のような機密性の高いデータを COM+ カタログに格納します。こうした文字列は、オブジェクトの作成時に COM+ によって取得されオブジェクトに渡されます。機密性の高い構成データは、カタログに格納する前に暗号化される必要があります。
否認
否認の脅威は、ユーザーが操作またはトランザクションの実行を拒否した場合や、クレームに対抗する証拠が十分でない場合に発生します。監査は、すべてのアプリケーション層で実行する必要があります。また、サービス コンポーネントでは、中間層でのユーザー アクティビティをログに記録する必要があります。通常、Enterprise Services シナリオではフロントエンド Web アプリケーションが偽装を有効にするため、ほとんどの場合、サービス コンポーネントは呼び出し元の ID にアクセスできます。
設計に関する考慮事項
コードの記述を開始する前に、設計時に数多くの重要な事項を考慮する必要があります。主な考慮事項は、次のとおりです。
-
ロール ベースの承認
-
機密性の高いデータ保護
-
監査要件
-
アプリケーションの起動の種類
-
トランザクション
-
コード アクセス セキュリティ
ロール ベースの承認
COM+ ロールに従った効果的なロール ベースの承認に備えて、サービス コンポーネントの呼び出しに呼び出し元のセキュリティ コンテキストが利用されていることを確認してください。これにより、呼び出し側のグループ メンバシップに基づく細かなロール ベースの承認を実行できます。つまり、ASP.NET Web アプリケーションでサービス コンポーネントを呼び出す場合は、コンポーネントを呼び出す前に Web アプリケーションで呼び出し側を偽装する必要があります。
機密性の高いデータ保護
サービス コンポーネントで機密性の高いデータ (従業員の詳細、財務トランザクション、カルテなど) を処理する場合は、そのデータがネットワークを行き来する場合にデータを保護する方法を考慮してください。IPSec がトランスポート レベルの暗号化を提供するセキュリティ保護されたインターネット データ センター (IDC) 環境でアプリケーションが動作しない場合、これに代わるオプションは RPC 暗号化を利用することです。このために、Packet Privacy 認証レベルを採用する必要があります。詳細については、このモジュールで後述する「機密性の高いデータ」を参照してください。
監査要件
否認の脅威に対処するために、Enterprise Service コンポーネントによって実行される機密性の高いトランザクションは記録しておく必要があります。設計時に、監査を要する操作の種類および記録する必要のある詳細事項を考慮してください。最低限、これにはトランザクションを開始した ID、およびトランザクションの実行に使用された ID が含まれている必要があります。ただし、これらが同じものであってもなくてもかまいません。
アプリケーションの起動の種類
設計時に、サービス コンポーネントの起動方法を決定します。Dllhost.exe プロセスのインスタンスを使用してコンポーネントを起動するか、クライアント プロセス内部でコンポーネントを実行できます。サーバー アプリケーションは、Dllhost.exe のインスタンスにおけるプロセス外で実行し、ライブラリ アプリケーションは、クライアントのプロセス アドレス空間で実行します。また、ライブラリ アプリケーションは、プロセス間通信がないため、さらに効率的です。ただし、このアプリケーションは構成しにくいので、プロセス レベルの隔離で保護されません。多くのセキュリティ設定 (認証レベルや偽装レベル) は、クライアント プロセスから継承されます。
トランザクション
分散トランザクションを利用する場合は、トランザクションの開始場所を考慮し、ファイアウォールで分離されたコンポーネントとリソース マネージャの間でトランザクションを実行した場合の影響を考慮してください。このシナリオでは、ファイアウォールは Microsoft 分散トランザクション コーディネータ (DTC) トラフィックをサポートするように構成されている必要があります。
実際の展開アーキテクチャに中間層アプリケーション サーバーが含まれている場合は、一般に、フロントエンド Web アプリケーションからではなく、アプリケーション サーバーの Enterprise Services アプリケーションからトランザクションを開始することをお勧めします。
コード アクセス セキュリティ
通常、サービス コンポーネントを使用するアプリケーションは完全に信用されるため、コード アクセス セキュリティは、その用途が呼び出し側のコードの承認に限られています。ただし、Enterprise Services では、呼び出し側のコードにはアンマネージ コードを呼び出すのに必要な権限が求められます。これによる主な影響は、部分的に信頼できる Web アプリケーションから Enterprise Services アプリケーションに対して直接呼び出すことができない点です。ASP.NET の部分的に信頼できるレベル (高、中、低、および最小) では、アンマネージ コードのアクセス許可は与えられません。部分的に信頼できるアプリケーションからサービス コンポーネントを呼び出す必要がある場合は、コンポーネントを呼び出す権限コードをサンド ボックスする必要があります。詳細については、このモジュールで後述する「コード アクセス セキュリティに関する考慮事項」を参照してください。
認証
Enterprise Services アプリケーションでは、Windows 認証を使用します。使用するのは、クライアントおよびサーバー オペレーティング システムによって NTLM 認証または Kerberos 認証のどちらかです。Windows 2000 または Windows Server 2003 環境では、Kerberos 認証が利用されます。
サービス コンポーネントの構築時に考慮する必要のある主要な事項は、すべての呼び出しを確実に認証して、匿名ユーザーがコンポーネントの機能にアクセスできないようにすることです。
呼び出しレベル認証 (最低限) を使用する
匿名の呼び出しを拒否するには、少なくとも呼び出しレベル認証を利用してください。この設定を構成するには、サービス コンポーネント アセンブリに次の属性を追加します。
[assembly:ApplicationAccessControl(
Authentication = AuthenticationOption.Call)]
注: これは、コンポーネント サービスにおいてアプリケーションの [プロパティ] ダイアログ ボックスの [セキュリティ] タブで呼び出しの認証レベルを [呼び出し] に設定することに相当します。
承認
Enterprise Services では、承認に COM+ ロールを使用します。アプリケーション、コンポーネント、インターフェイス、およびメソッドの承認の細かさを制御できます。アプリケーションのサービス コンポーネントによって公開された限定操作をユーザーに実行させないようにするには、以下のようにします。
ロール ベースのセキュリティを有効にする
ロール ベースのセキュリティは、Windows 2000 の既定では無効にされています。Windows Server 2003 では、逆に有効にされています。コンポーネントの登録時 (通常 Regsvcs.exe を使用) にロール ベースのセキュリティを自動的に有効にするには、サービス コンポーネント アセンブリに次の属性を追加します。
[assembly:ApplicationAccessControl(true)]
注: この属性を使用するのは、コンポーネント サービスにおいてアプリケーションの [プロパティ] ダイアログ ボックスの [セキュリティ] タブで [このアプリケーションへのアクセス確認を行う] をオンにすることに相当します。
コンポーネント レベルでのアクセス確認を有効にする
コンポーネント レベルでのアクセス確認は、コンポーネント、インターフェイス、またはメソッド レベルのロール確認をサポートするために有効にされている必要があります。コンポーネントの登録時にコンポーネント レベルでのアクセス確認を自動的に有効にするには、サービス コンポーネント アセンブリに次の属性を追加します。
[assembly:ApplicationAccessControl(AccessChecksLevel=
AccessChecksLevelOption.ApplicationComponent)]
注: この属性を使用するのは、コンポーネント サービスにおいてアプリケーションの [プロパティ] ダイアログ ボックスの [セキュリティ] タブで [プロセスおよびコンポーネント レベルでのアクセス確認を実行する] をオンにすることに相当します。
コンポーネント レベルでのアクセス確認を行う
個々のコンポーネントがアクセス確認を実行できるように、コンポーネント レベルでのアクセス確認を行う必要があります。この設定は、アプリケーション規模のセキュリティ レベルが、前述のようにプロセスおよびコンポーネント レベルに設定されている場合に限り有効です。コンポーネントの登録時にコンポーネント レベルでのアクセス確認を自動的に有効にするには、サービス コンポーネント クラスに次の属性を追加します。
[ComponentAccessControl(true)]
public class YourServicedComponent :ServicedComponent
{
}
注: この属性を使用するのは、コンポーネント サービスにおいてコンポーネントの [プロパティ] ダイアログ ボックスの [セキュリティ] タブで [コンポーネント レベルでのアクセス確認を行う] をオンにすることに相当します。
構成管理
COM+ でコンポーネント サービス ツールを介して管理者に提供される構成可能な設定のほかに、一般に開発者はコードで構成関連の機能を実行します。たとえば、この機能で、COM+ カタログに格納されたオブジェクトのコンストラクタ字列を取得できます。Enterprise Services で構成管理を採用するときに、こうした主要な事項を考慮してください。
最低限の権限を持つ run-as アカウントを使用する
開発中は、対話型ユーザー アカウントではなく、最低限の権限を持つローカル アカウントを使用してサービス コンポーネントの実行およびテストを行います。管理者が運用環境で使用する可能性の高い run-as アカウントにできるだけ合わせてアカウントを構成します。
オブジェクトのコンストラクタ文字列にシークレットを格納しないようにする
データベース接続文字列、パスワードなどのシークレットを COM+ カタログにおけるオブジェクトのコンストラクタ文字列に格納する場合は、ローカル管理者グループのどのメンバでもこのプレーン テキスト データを参照できます。シークレットを格納しないようにしてください。シークレットを格納する必要がある場合は、データを暗号化します。DPAPI が実装オプションとして優れているのは、このオプションにより、キー管理に関連する問題を回避できるためです。
実行時に、オブジェクトのコンストラクタ文字列を取得し、DPAPI を使用してデータを解読します。マネージ コードに基づいて DPAPI を使用する方法の詳細については、MSDN 記事「セキュリティ保護された ASP.NET アプリケーションの構築: 認証、認定、および通信のセキュリティ保護」の「DPAPI ライブラリを作成する方法」(http://www.microsoft.com/japan/msdn/net/security/SecNetHT07.aspx) を参照してください。
[ConstructionEnabled(Default="")]
public class YourServicedComponent :ServicedComponent, ISomeInterface
{
// オブジェクトのコンストラクタを最初に呼び出す
public YourServicedComponent() {}
// 次に、オブジェクトのコンストラクタ文字列を Construct メソッドに渡す
protected override void Construct(string constructString)
{
// DPAPI を使用して構成データを解読する
}
} 無制限な委任を回避する
サービス コンポーネント クライアントは、環境に応じて、NTLM 認証または Kerberos 認証で認証されます。Windows 2000 の Kerberos は、無制限な委任をサポートしています。つまり、クライアントの資格情報で構成できるネットワーク ホップ数に制限がないということです。
ASP.NET がクライアントである場合は、次のように Machine.config 内の <processModel> 要素に comImpersonation 属性を設定して、偽装レベルを構成できます。
comImpersonationLevel="[Default|Anonymous|Identify|Impersonate|Delegate]"
Enterprise Services サーバー アプリケーションに対して定義した偽装レベルにより、サービス コンポーネントがやりとりするリモート サーバーの偽装機能が決定されます。この場合は、サービス コンポーネントがクライアントです。サービス コンポーネントの偽装レベルを指定できますが、このレベルは、サービス コンポーネントがクライアントである場合に次の属性を使用して適用されます。
[assembly:ApplicationAccessControl(
ImpersonationLevel=ImpersonationLevelOption.Identify)]
注: この属性を使用するのは、コンポーネント サービスにおいてアプリケーションの [プロパティ] ダイアログ ボックスの [セキュリティ] ページで [偽装レベル] 値を設定することに相当します。
次の表は、こうした各偽装レベルの影響を説明しています。
表 11.1: 偽装レベル
| 偽装レベル | 説明 |
| 匿名 | サーバーはクライアントを識別できません。 |
| 識別 | サーバーはクライアントを識別し、クライアントのアクセス トークンを使用してアクセス確認を実行できます。 |
| 偽装 | サーバーはクライアントの資格情報を使用してローカル リソースにアクセスできます。 |
| 委任 | サーバーはクライアントの資格情報を使用してリモート リソースにアクセスできます (これには、Kerberos および特定のアカウント構成が必要です)。 |
詳細については、モジュール 17「アプリケーション サーバーをセキュリティ保護する」および MSDN 記事「セキュリティ保護された ASP.NET アプリケーションの構築: 認証、認定、および通信のセキュリティ保護の「Windows 2000 での Kerberos 委任の構成方法」」(http://www.microsoft.com/japan/msdn/net/security/SecNetHT05.aspx) を参照してください。
機密性の高いデータ
アプリケーションが機密性の高いデータをネットワーク経由でサービス コンポーネントとやりとりし、ネットワーク盗聴の脅威に対処する場合は、データを暗号化して秘密を維持し、改ざんされないようにする必要があります。IPSec でトランスポート レベルの保護を利用できます。あるいは、RPC パケット プライバシ認証レベルを採用するように Enterprise Services アプリケーションを構成すれば、アプリケーション レベルの保護を利用できます。このようにして、サービス コンポーネントとやりとりするデータの各パケットを暗号化し、プライバシおよび整合性を提供します。
パケット プライバシ認証を構成するには、コンポーネント サービス ツールを使用するか、サービス コンポーネント アセンブリに次の属性を追加します。
[assembly:ApplicationAccessControl(
Authentication = AuthenticationOption.Privacy)]
IPSec を利用して 2 台のコンピュータ間で送信されるすべてのデータを暗号化する方法の詳細については、Microsoft patterns & practices「セキュリティ保護された ASP.NET アプリケーションの構築: 認証、認定、および通信のセキュリティ保護」の「2 つのサーバー間の通信を IPSec で保護する方法」(http://www.microsoft.com/japan/msdn/net/security/SecNetHT18.aspx) を参照してください。
監査とログ記録
監査とログ記録は、ユーザーが特定のトランザクションまたは主要な操作の実行を拒否する潜在的な否認の脅威を回避するために、アプリケーション層全体で実行する必要があります。
ユーザー トランザクションを監査する
Web アプリケーションまたは Web サービスが偽装に備えて構成されている場合、呼び出し元の ID は、自動的に Enterprise Services アプリケーションに渡り、SecurityCallContext.OriginalCaller を使用して利用できます。この ID は、中間層での監査に役立ちます。次のコードは、この情報にアクセスする方法を示しています。
[ComponentAccessControl]
public class YourServicedComponent :ServicedComponent
{
public void ShowCallers()
{
SecurityCallers callers = SecurityCallContext.CurrentCall.Callers;
foreach(SecurityIdentity id in callers)
{
LogEvent(id.AccountName);
}
}
private void LogEvent(string message)
{
try
{
if (!EventLog.SourceExists(appName))
{
EventLog.CreateEventSource(appName, eventLog);
}
EventLog.WriteEntry(appName, message, EventLogEntryType.Information );
}
catch (SecurityException secex)
{
throw new SecurityException(
"Event source does not exist and cannot be created.", secex);
}
}
}
イベント ログを正しく書き込むには、Enterprise Services アプリケーションを特有のイベント ログに関連付けるイベント ソースが存在している必要があります。先ほどのコードでは、実行時にイベント ソースを作成します。つまり、サービス コンポーネント プロセス アカウントには、関連する権限がレジストリ内で設定されている必要があるということです。
もう 1 つの方法は、Installer クラスを使用してインストール時にアプリケーションのイベント ソースを作成することです。その場合は、管理者権限を利用できます。この方法の詳細については、モジュール 10 「セキュリティ保護された ASP.NET ページとコントロールを構築する」の「監査とログ記録」を参照してください。
セキュリティ保護されたサービス コンポーネントを構築する
サービス コンポーネントおよび Enterprise Services アプリケーションに当てはまる脅威や対策については詳しく説明したので、次のコードで、単純な Customer クラスを実装する場合のセキュリティ保護されたサービス コンポーネントの主な特徴を示します。メソッド実装の詳細は、見やすいように省略しています。
アセンブリの実装
assemblyinfo.cs の次のコードは、regsvcs.exe を使用してサービス コンポーネント アセンブリを Enterprise Services に登録するときに COM+ カタログを構成するために使用したアセンブリ レベル メタデータを示しています。
// (1) 厳密な名前を付ける。
[assembly:AssemblyKeyFile(@"..\..\Customer.snk")]
// Enterprise Services の構成
[assembly:ApplicationName("CustomerService")]
[assembly:Description("Customer Services Application")]
// (2) サーバー アプリケーション - dllhost.exe のプロセス インスタンスで実行する。
[assembly:ApplicationActivation(ActivationOption.Server)]
// (3) コンポーネント レベルでのアクセス確認を有効にする。
// (4) 呼び出しレベル認証を指定する。
// (5) 下流の呼び出しのための識別レベルを指定する。
[assembly:ApplicationAccessControl(
AccessChecksLevel=AccessChecksLevelOption.ApplicationComponent,
Authentication=AuthenticationOption.Call,
ImpersonationLevel=ImpersonationLevelOption.Identify)]
このコードには、以下のようなセキュリティの特徴 (コメント行の番号に対応) があります。
-
アセンブリに厳密な名前を付けます。これは、サービス コンポーネントの必須要件です。セキュリティの観点からは、さらにアセンブリがデジタル署名されるという利点が得られます。つまり、攻撃者によるあらゆる変更が検出され、アセンブリの読み込みに失敗するということです。
-
アプリケーションは、dllhost.exe の専用のインスタンスでサーバー アプリケーションとして実行するように構成されます。このようにすれば、展開時に最低限の権限を持つ run-as ID を指定できます。
-
アプリケーションは、コンポーネント レベルでのアクセス確認をサポートするように構成されます。このようにすれば、クラス、インターフェイス、メソッドの各レベルでロール メンバシップに基づいて呼び出し側を承認できます。
-
呼び出しレベル認証が指定されます。つまり、クライアントからの各メソッド呼び出しが認証されます。
-
このサービス コンポーネントからリモート サーバーの他のコンポーネントへの発信呼び出しの偽装レベルが、[識別する] に設定されます。つまり、ダウンストリーム コンポーネントでは呼び出し側の識別はできますが、偽装は実行できないということです。
注: 呼び出し側の ASP.NET Web アプリケーションまたは Web サービス クライアントの偽装レベルは、クライアント Web サーバーの Machine.config における <processModel> 要素で指定されます。
サービス コンポーネント クラスの実装
次のコードは、部分的に実装した Customer クラスのセキュリティ構成を示しています。
namespace busCustomer
{
// (1) メソッド レベル承認のパブリック インターフェイス ICustomerAdmin をサポートする明示的なインターフェイス定義
public interface ICustomerAdmin
{
void CreditAccountBalance(string customerID, double amount);
}
// (2) コンポーネント レベルでのアクセス確認を実施する。
[ComponentAccessControl]
public sealed class Customer :ServicedComponent, ICustomerAdmin
{
private string appName = "Customer";
private string eventLog = "Application";
// ICustomer 実装
// (3) CreditAccountBalance へのアクセスは、管理者および上級管理者の
// ロールを持つメンバに限定される。
[SecurityRole("Manager")]
[SecurityRole("Senior Manager")]
public void CreditAccountBalance(string customerID, double amount)
{
// (4) 実装を保護するために構造化された例外処理
try
{
// (5) セキュリティが有効になっていることを確認する。
if (ContextUtil.IsSecurityEnabled)
{
// 管理者だけが、総額が 1,000 ドルを上回る口座に
// 信用貸しを行うことができる。
if (amount > 1000) {
// (6) 信用操作を承認するためのプログラムによるロール確認
if (ContextUtil.IsCallerInRole("Senior Manager")) {
// データベースを更新するためにデータ アクセス コンポーネントを呼び出す。
. . .
// (7) トランザクションを監査する。
AuditTransaction(customerID, amount);
}
else {
throw new SecurityException("Caller not authorized");
}
}
}
else {
throw new SecurityException("Security is not enabled");
}
}
catch( Exception ex)
{
// 例外詳細をログに記録する。
throw new Exception("Failed to credit account balance for customer: " +
customerID, ex);
}
}
private void AuditTransaction(string customerID, double amount)
{
// (8) ログ記録のために呼び出しコンテキストから
// 呼び出し元 ID を取得する。
SecurityIdentity caller = SecurityCallContext.CurrentCall.OriginalCaller;
try
{
if (!EventLog.SourceExists(appName))
{
EventLog.CreateEventSource(appName,eventLog);
}
StringBuilder logmessage = new StringBuilder();
logmessage.AppendFormat("{0}User {1} performed the following transaction"
+ "{2} Account balance for customer {3} "
+ "credited by {4}",
Environment.NewLine, caller.AccountName,
Environment.NewLine, customerID, amount);
EventLog.WriteEntry(appName, logmessage.ToString(),
EventLogEntryType.Information);
}
catch(SecurityException secex)
{
throw new SecurityException(
"Event source does not exist and cannot be created", secex);
}
}
}
}
このコードには、以下のようなセキュリティの特徴 (コメント行の番号に対応) があります。
-
インターフェイスは、COM+ ロールによりインターフェイスおよびメソッド レベル承認をサポートするために定義され、明示的に実装されます。
-
クラスのコンポーネント レベルでのアクセス確認は、クラス レベルでの ComponentAccessControl 属性を使用して有効にされます。
-
SecurityRole 属性は、アクセスを管理者または上級管理者のロールを持つメンバに制限するために CreditAccountBalance メソッドで使用されます。
-
構造化された例外処理によって実装が保護されます。例外は捕捉され、ログに記録されて、該当する例外が呼び出し側に送信されます。
-
コードでは、明示的なロール確認の前にセキュリティが有効にされているかどうかを確認します。これは、アプリケーション セキュリティ構成が管理者によって不注意にまたは故意に無効にされている場合にトランザクションを実行できないようにする、リスク軽減の戦略です。
注: セキュリティが無効にされている場合、IsCallerInRole メソッドは常に True を返します。
-
メソッドで利用されている宣言型セキュリティのため、呼び出し側は、管理者または上級管理者のロールを持つメンバでなければなりません。きめの細かい承認を行うために、呼び出し側のロール メンバシップは、コードで明示的に確認されます。
-
トランザクションが監査されます。
-
監査の実装では、SecurityCallContext オブジェクトを使用して呼び出し元の ID を取得します。
コード アクセス セキュリティに関する考慮事項
通常、サービス コンポーネントを使用するアプリケーションは完全に信用されるため、コード アクセス セキュリティは、その用途が呼び出し側のコードの承認に限られています。呼び出し側のコードでは、以下の点を考慮する必要があります。
-
サービス コンポーネントでクロス コンテキスト呼び出しを起動および実行する場合には、アンマネージ コード アクセス許可が必要です。
-
サービス コンポーネントのクライアントが ASP.NET Web アプリケーションである場合、その信用レベルを次のように "Full" に設定する必要があります。
<trust level="Full" />
Web アプリケーションが "Full" 以外の信用レベルで構成されている場合、そのアプリケーションにはアンマネージ コード アクセス許可がありません。このような場合は、サンドボックスされたラッパー アセンブリを作成し、サービス コンポーネントとの通信をカプセル化する必要があります。また、ラッパー アセンブリにアンマネージ コード アクセス許可を与えるようにコード アクセス セキュリティ ポリシーを構成する必要もあります。高い権限を持つコードのカプセル化に利用されるサンドボックスの詳細については、モジュール 9「ASP.NET でコード アクセス セキュリティを使用する」を参照してください。
-
サービス コンポーネントの参照を信頼されていないコードに渡す場合は、サービス コンポーネントで定義したメソッドを信頼されていないコードから呼び出すことはできません。この規則の例外は、コンテキスト切り替えまたは遮断サービスを必要としないメソッドまたは System.EnterpriseServices のメンバを呼び出さないメソッドで生じます。このようなメソッドは、信頼されていないコードから呼び出される可能性があります。
展開の考慮事項
Enterprise Services アプリケーションは、一般に Web サーバーまたはリモート アプリケーション サーバーにインストールされます。図 11.3 は、Enterprise Services の 2 つの一般的な展開シナリオを示しています。セキュリティの点から、リモート展開シナリオと顕著に異なる点は、サービス コンポーネントとやりとりするデータが、多くの場合、内部ネットワークと境界ネットワークを分離するために使用される内部ファイアウォールを介してネットワーク経由で渡されることです。
.jpg)
図 11.3
Enterprise Services の一般的な展開構成
開発者および管理者は、展開に関連する以下の問題に注意する必要があります。
展開時にセキュリティ保護された構成を適用する方法の詳細については、モジュール 17「アプリケーション サーバーをセキュリティ保護する」を参照してください。
ファイアウォール制限
クライアントと Enterprise Services アプリケーションが内部ファイアウォールで分離されている場合、DCOM および DTC (アプリケーションが分散トランザクションを利用する場合) をサポートする関連ポートが開いている必要があります。
DCOM では、1024 より上のポート番号をランダムに選択する既定の RPC 動的ポート割り当てを採用しています。さらに、ポート 135 は RPC エンドポイント マッパーによって使用されます。内部ファイアウォールで DCOM をサポートするのに必要なポートを、次の 2 とおりの方法で制限できます。
-
ポート範囲を定義する。
この方法では、RPC で動的に割り当てたポートを制御できます。
-
静的なエンドポイント マッピングを利用する。
Windows 2000 SP3 (または Quick Fix Engineering [QFE] 18.1 以降) または Windows Server 2003 では、静的なエンドポイントを使用するように Enterprise Services アプリケーションを構成できます。静的なエンドポイント マッピングでは、ファイアウォールにおける 2 つのポートを開く必要があるだけです。具体的には、Enterprise Services アプリケーションの RPC 用のポート 135 および指定されたポートを開く必要があります。
ポート範囲および静的エンドポイント マッピングを定義する方法の詳細については、モジュール 17「アプリケーション サーバーをセキュリティ保護する」の「ファイアウォールの考慮事項」を参照してください。
Web サービスを使用する
内部ファイアウォールでポートを開くようにすることができない場合は、アプリケーション サーバーのサービス コンポーネントの前に Web サービス ファサード層を導入できます。つまり、図 11.4 に示すように HTTP トラフィック、特に SOAP (Simple Object Access Protocol) メッセージ用にポート 80 を開いて、双方向に流れるようにするだけです。
.jpg)
図 11.4:
Web サービス ファサード層を使用して HTTP で Enterprise Services とやりとりする方法
この方法では、クライアントからサーバーにトランザクション コンテキストを渡すことはできませんが、展開アーキテクチャに中間層アプリケーション サーバーが含まれているほとんどの場合には、アプリケーション サーバーのリモート サービス コンポーネントでトランザクションを開始した方が良いでしょう。
Web サービス ファサード層のようなサービス エージェントやサービス インターフェイスの物理的な展開要件については、MSDN 記事「Application Architecture for .NET: Designing Applications and Services」の「Reference」セクションにある「Physical Deployment and Operational Requirements」(英語) を参照してください。
DTC の要件
アプリケーションで COM+ 分散トランザクションを利用し、それが内部ファイアウォールによって分離された複数のリモート サーバーで利用される場合、ファイアウォールでは DTC トラフィックをサポートするために必要なポートを開く必要があります。
展開アーキテクチャにリモート アプリケーション層が含まれている場合、通常、トランザクションは Enterprise Services アプリケーション内で開始され、データベース サーバーに送信されます。アプリケーション サーバーがない場合は、Web サーバーの Enterprise Services アプリケーションでトランザクションが開始され、SQL Server リソース マネージャに送信されます。
DTC トラフィックをサポートするようにファイアウォールを構成する方法については、モジュール 18「データベース サーバーをセキュリティ保護する」を参照してください。
要約
Enterprise Services (COM+) のセキュリティでは、Windows セキュリティを利用して、呼び出し側の認証および承認が行われます。承認は、Windows グループまたはユーザー アカウントを含む COM+ ロールで構成され、制御されます。Enterprise Services アプリケーションおよびサービス コンポーネントに関連する大多数の脅威は、確実なコーディング技法および適切なカタログ構成で対処できます。
開発者は、宣言型属性を使用してサービス コンポーネント セキュリティ構成を設定する必要があります。この属性で、アプリケーションを (通常は Regsvcs.exe を使用して) Enterprise Services に最初に登録するときのアプリケーションの構成方法を決定します。
すべてのセキュリティ構成設定を属性で設定できるわけでありません。管理者は、サーバー アプリケーションの run-as ID を指定する必要があります。また、管理者は、展開時に Windows グループまたはユーザー アカウントをロールに設定する必要もあります。
サービス コンポーネントを開発している場合や、エンタープライズ セキュリティ ソリューションのセキュリティを評価している場合は、このガイドの「チェックリスト: Enterprise Services をセキュリティ保護する」を使用してください。
その他のリソース
詳細については、以下のリソースを参照してください。