Print-friendly Version
過去数年間、Web アプリケーションをセキュリティー保護するための堅牢なソリューションを求める声が着実に高まってきました。十分なセキュリティーを確保するため、オンライン Web サービスを提供する企業のほとんどが、次の 2 つのサービスレベルでセキュリティーを実装しています。
認証 — あるユーザーが、そのユーザーが主張するとおりの人であるか確認すること。
承認 — アクセス対象リソースに対する権限をユーザーが持っているか確認すること。
これらのサービスレベル要件を満たすには、詳細かつ注意深いアーキテクチャー設計と骨の折れる実装が必要となります。
シリーズのパート 1 にあたるこの記事では、Sun Java System Access Manager (以下 Access Manager) を使って架空の健康保険会社 EB Health の承認要件を実現する方法を説明します。企業プラットフォームの 1 つである Access Manager は、Web アプリケーションをセキュリティー保護し、認証、シングルサインオン、承認の各機能を提供します。EB Health のニーズを実現するための実装の全体は、Access Manager 6.3 (Sun Java Enterprise System 2005Q2) のそのまま使える標準機能とカスタム拡張に基づいており、それを Access Manager 7.1 (Sun Java Enterprise System 5) に移行したものです—ソースコードや設定は一切変更していません 。
目次
EB Health のアプリケーションはすべて、Web 層と Enterprise JavaBeans (EJB) 層という、2 層セキュリティーモデルで構成されています。
承認モデルはロールに基づくアクセス制御 (RBAC) 設計であり、アプリケーションの特定部分へのアクセスを制限します。このモデルは次の 3 つの要件を満たします。
すべての認証済みユーザーのアクセス
ロールに基づく、アプリケーション URI へのアクセス
ロールに基づく、アプリケーションコンポーネント (Java EE コンポーネント、フォームフィールド、ポートレット) へのアクセス
Access Manager を使えば、集中管理された認証およびポリシー評価サービスと、動的なアクセス制御管理が可能になります。さらに、共通のユーザーインタフェースによって高い管理容易性が実現されます。
Access Manager を使って Web アプリケーションをセキュリティー保護するためのもっとも一般的な配備シナリオは、ポリシーエージェントベースのアーキテクチャーを使用することです。このアーキテクチャーではアプリケーションをホストするコンテナ上にポリシーエージェントをインストールしますが、このエージェントがポリシー適用ポイント (PEP) として機能します。ポリシーエージェントはさまざまなモードで動作可能ですが、もっとも重要なのは次の 2 つです。
URL_POLICY モード — このモードでは、ポリシーエージェントはすべての受信 HTTP または HTTPS 要求を横取りし、それを検証して認証、セッションの有効性確認、承認を行います。Access Manager ポリシーエージェントは、業界標準の Web コンテナの大部分でサポートされています。
J2EE_POLICY モード — このモードでは Java EE セキュリティーモデルと連携して、Java EE のプログラムによるセキュリティーと宣言型セキュリティーが正しく機能するように、対象の情報が Web 層と EJB 層に伝達されます。Access Manager ポリシーエージェントは、業界標準の Java EE コンテナの大部分でサポートされています。
図 1 はアーキテクチャーの概要レベルのビューであり、アプリケーションサーバー、ポリシーエージェント、および Access Manager が含まれます。
図 1:承認のアーキテクチャー
Java EE のセキュリティーモデルは承認用のフレームワークとして機能しますが、ポリシー定義の集中管理機能を備えていないため、保守作業や実行時のアクセス制御が複雑になってしまいます。さらに、Java EE 仕様では、ロールに対するリソースアクセスレベルを設定できません。たとえば、ADMIN ロールが、あるセッション Bean の READ ONLY アクセス権のみを持つ、といった定義を行えません。
これに対し、図 1 に示したモデルは、基本的なセキュリティーとアクセスレベルを使用する高度なモデルの両方を必要とするアプリケーションでも正しく動作します。きめ細かなアクセスレベル承認を使って Access Manager をカスタマイズする方法について次に説明します。
Access Manager の管理コンソール (amconsole) は、リソース用のポリシーを定義および管理するための Web ベースのインタフェースです。この節では、3 つの承認要件を満たすために管理コンソールまたはコマンド行インタフェース (CLI) を使って設定を行う方法について説明します。
前の節で説明したアーキテクチャーを採用すれば、最初の 2 つの要件はデフォルトのままで設定可能です。
すべての認証済みユーザーのアクセス
ロールに基づく、アプリケーション URI へのアクセス
次に手順の概要を示します。
アプリケーションをホストするアプリケーションサーバー上で、ポリシーエージェントをインストールし、URL_POLICY モードを使用できるようにします。
http://www.ebhealthinsurance.com/claims/* など、ある URL へのアクセスをすべての対象つまり認証済みユーザーに許可するポリシールールを作成します。
2 番目の要件に対して手順 1 と 2 を繰り返します。この場合の対象は、定義されたリソースにアクセスする権限を持つロールになります。
認証済みユーザーへのアクセス権の付与 EB Health の Claims アプリケーションへのアクセスをセキュリティー保護するには、ポリシー、ルール、および対象を次のように定義します。
管理コンソールで、「New Policy」をクリックしてポリシーを作成したあと、「New Rule」をクリックしてルールを作成します。
図 2 の画面で「URL Policy Agent (with resource name)」を選択します。「Next」をクリックします。
図 2:ルールのサービスタイプとして「URL Policy Agent」を選択する
図 3 の画面で次の手順を実行します。
「Name」フィールドに Claims Processing Application と入力します。
「Resource Name」フィールドに、Claims アプリケーションの URL http://www.ebhealthinsurance.com/claims/* を入力します。
「Actions」の下の「GET」と「POST」の両方で、「Allow」を選択します。「Finish」をクリックします。
図 3:ルールの詳細を定義する
別の対象を作成したあと、図 4 の画面で「Authenticated Users」を選択します。「Next」をクリックします。
図 4:対象タイプとして「Authenticated Users」を選択する
図 5 の画面で、「Name」フィールドに All Authenticated Users と入力します。「Finish」をクリックします。
図 5:対象の名前を指定する
すると、Access Manager は図 6 のような、ポリシー設定の確認画面を表示します。
図 6:ポリシー設定の確認
アプリケーション URI に対するアクセス権の付与 2 番目の要件を満たし、特定のロールだけにアクセス権を付与するには、前の節の手順 1 ~ 3 を繰り返したあと、次の手順を実行します。
図 7 の画面で「Access Manager Identity Subject」を選択します。「Next」をクリックします。
図 7:対象タイプとして「Access Manager Identity Subject」を選択する
図 8 の画面で、「Name」フィールドに Admin Role と入力したあと、「Filter」ドロップダウンメニューから「Role」を選択します。
「Available」の下で admin を選択し、「Add」をクリックしてそれを「Selected」領域に移動します。「Finish」をクリックします。
図 8:対象のパラメータを定義する
アプリケーションコンポーネントに対するロールに基づくアクセス権を付与する アプリケーションコンポーネントに対するアクセス権を付与する、という 3 番目の要件を満たすには、Access Manager をカスタマイズします。具体的には、URL リソース経由で提供されるレベルよりもずっと下のレベルでコンポーネントをセキュリティー保護するサービスを作成します。
セキュリティー要件 EB Health の目標は、次のことをプログラムで実現することです。
特定のロールが Claims アプリケーションの特定部分にアクセスすることを許可する。
承認されていないロールが Claims アプリケーションの特定部分にアクセスすることを拒否する。
ポリシーストア内に情報を中央集約する。
この目標を達成するには、EB Health はページレベルのリソースをセキュリティー保護し、それらのリソースごとにロール別のアクセスレベルを指定する必要があります。アクセスレベルは、CREATE、READ、UPDATE、DELETE、ALL、および NONE です。
たとえば、EB Health では、Claims アプリケーションの「User Profile」画面へのアクセスをロールに従って制御する必要があるものとします。Java EE アプリケーションは、リソースへのアクセスをユーザーに許可する際に、そのユーザーが表示および実行可能な部分をそのロールに従って制限するため、この画面もロールごとに異なる方法でレンダリングされます。
「User Profile」画面にアクセスできるロールは次の 2 つです。Admin および Employee。セキュリティー要件と関連 UI は次のとおりです (関連 UI は図 9 を参照)。
Admin — このロールは、「SSN」(Social Security Number) フィールド (SSN_FORM_FIELD) を含む画面全体に対するすべてのアクセス権を持ちます。このため、Admin が「User Profile」画面にアクセスすると、すべてのフィールド値が編集可能な値として表示されるほか、「Create」、「Update」、「Delete」、および「Cancel」ボタンも表示されます。
Employee — このロールは、「User Id」、「Email」、および「Phone」フィールドに対して UPDATE アクセス権を持ちますが、「SSN」フィールドに対しては READ アクセス権しか持ちません。Employee が「User Profile」画面にアクセスすると、「User Id」、「Email」、および「Phone」フィールドのみが編集可能な値として表示され、「SSN」フィールドはこのロールの READ ONLY アクセス権を反映してグレー表示されます。
図 9:Admin および Employee ロールに応じた「User Profile」画面へのアクセス
手順 まず、Access Manager サービスを拡張し、CustomClaimsAppPolicyService という名前のサービスを作成します。
文書型定義 (Document Type Definitions、DTD) sms.dtd に準拠し、かつ 6 つのアクセスレベルを指定した CustomClaimsAppPolicyService.xml という名前の XML スキーマを作成します。 また、このスキーマには、サービス名、サービス属性、およびそれらの属性の値も記述されます。
CLI 上で CustomClaimsAppPolicyService.xml ファイルを Access Manager にインポートします。次のコマンドをすべて 1 行で入力します。/opt/SUNWam/bin/amadmin --verbose --runasdn uid=amAdmin,ou=People,dc=ebhealthinsurance,dc=com --password admin-password --schema CustomClaimsAppPolicyService.xml すると、Access Manager によって次の出力が生成されます。
Info 109: Calling XML PARSER
Info 110: XML file to import:CustomClaimsAppPolicyService.xml
Info 103: Loading Service Schema XML CustomClaimsAppPolicyService.xml
Service Schema XML CustomClaimsAppPolicyService.xml
Info 115: Reading schema file :CustomClaimsAppPolicyService.xml
Info 105: Done loading Service Schema XML: [CustomClaimsApplicationPolicyService]
Success 0: Successfully completed.
注: サーバーを再起動しなくても変更が反映されます。
/opt/SUNWam/locale など、Access Manager のローカルディレクトリに CustomClaimsAppPolicyService.xml をコピーします。
次に、管理コンソール、CLI のいずれかでポリシーを作成します。 以下の手順では、両ツールから Claims Process Policy を作成し、関連するルールと対象を指定する方法を示します。
注: 多数のポリシールールを含む大規模アプリケーションを配備する場合、CLI のほうが適切な可能性があります。
管理コンソールから次の手順を実行します。
「New Policy」をクリックしてポリシーを作成します。
「Policy Name」フィールドと「Description」フィールドに必要な値を入力します。
「Rules」の下にある「New」をクリックします。 Access Manager によって、新しいカスタムポリシーサービスがデフォルトサービスタイプとともに表示されます。
図 10 の画面で、「CustomClaimsApplicationPolicyService (with resource name)」を選択し、「Next」をクリックします。
図 10:ルールのサービスタイプとして「CustomClaimsApplicationPolicyService」を選択する
図 11 の画面で、入力例に基づいて、リソースをアクセスレベルに関連付けるためのルールを定義します。
図 11:新しいルールの設定を定義する
リソース名には、承認を必要とするコンポーネント、ウィジェット、ページ、URL、またはその他の任意のオブジェクトの文字列表現を指定できるため、高い柔軟性と便宜性を実現できます。
ユーザーフォームに対する別のルールを、次の設定を使って作成します。
Service Type CustomClaimsApplicationPolicyService
Name UserForm_A1
Resource Name UserForm
Choose Permission ALL
対象 (ロール)、ここでは Access Manager ロール、をルールに割り当てるために、図 12 の画面で「Access Manager Identity Subject」を選択します。
次に、ロールで検索して使用可能なすべてのロールを一覧表示します。
図 12:対象タイプとして「Access Manager Identity Subject」を選択する
「SSN」フィールドの ALL アクセス権を Admin ロールに与えるために、図 13 の画面で、「Name」フィールドに Admin Role と入力します。「Filter」の下で、admin を「Selected」領域に追加します。「Finish」をクリックして前の画面に戻ります。
図 13:Access Manager アイデンティティー対象の設定を指定する
図 14 は、ユーザーが作成したルールと対象を要約したものです。
図 14:Claims Process Policy のルールと対象
CLI から次の手順を実行します。
DTD amAdmin.dtd に準拠し、かつポリシー情報を含む ClaimsApplicationPolicies.xml という名前の XML スキーマを作成します。
ClaimsApplicationPolicies.xml をインポートします。次のコマンドをすべて 1 行で入力します。/opt/SUNWam/bin/amadmin --verbose --runasdn uid=amAdmin,ou=People,dc=ebhealthinsurance,dc=com --password admin-password --data ClaimsApplicationPolicies.xml
すると、Access Manager によって次の出力が生成されます。
Info 107:Calling XML PARSER
Info 108:XML file to parse:ClaimsAppPolicies.xml
Info 101:Processing ClaimsAppPolicies.xml
Info 111:Requests generated by amadmin
Info 130:Created Policy under Organization dc=ebhealthinsurance,dc=com
Info 102:Done processing ClaimsAppPolicies.xml
Success 0:Successfully completed.
これで、Claims アプリケーションが自身のリソースをセキュリティー保護するために Access Manager に対してポリシー評価を呼び出せるようになりました。
この節では、Access Manager SDK を使って Claims アプリケーションのセキュリティーを実装する方法について説明します。
プロセスの紹介 このプロセスには、Claims アプリケーションをホストする Java EE コンテナ内に存在する、Access Manager SDK を含む Access Manager ポリシーエージェントのインストールが含まれます。ポリシーエージェントは、Access Manager と接続できるように、必要なクライアント Java アーカイブ (JAR) ファイルと構成を設定します。一方、この構成により、Java EE プラットフォームに準拠したアプリケーションが、ポリシーエージェントによる認証と URL ベースの荒削りな承認によってアクセスのセキュリティー保護を行えるようになります。
別のレベルの承認に関しては、アプリケーションコード内の Access Manager SDK が重要な役割を果たします。Access Manager はポリシー評価中に、サーバー側のポリシー変更を自動的に反映します。
サイズや間隔などのキャッシュパラメータを設定するには、AMAgent.properties ファイルを編集します。EB Health の場合、ポリシーエージェントがすでに十分なレベルのキャッシュ機能を提供してくれるため、カスタムのキャッシュメカニズムは必要ありません。
図 15 に概要レベルの配備シナリオを示します。
図 15:配備
コードの調査 この項では、承認プロセスを示すためにコードセグメントをいくつか引用します。
ポリシー評価とポリシー決定 次に、ポリシーを評価するコードセグメントを示します。
String serviceName = "CustomClaimsApplicationPolicyService";
String resourceName = "SSN_FORM_FIELD";
com.sun.identity.policy.client.PolicyEvaluator pe;
PolicyDecision policyDecision;
Map envParams = new HashMap();
/*
Note: The implementation of PolicyEvaluator is from package com.sun.identity.policy.client
*/
pe = new PolicyEvaluator(serviceName);
policyDecision = pe.getPolicyDecision(token, resourceName, actionNames, envParams);
String str = policyDecision.tostring();
String xml = policyDecision.toXml();
ここでは、クライアント PolicyEvaluator が適切なパラメータを指定して呼び出されます。Claims アプリケーションから渡されるパラメータに応じて、Access Manager はアクセスレベルを表すポリシー決定を返します。
PolicyDecision オブジェクトには、次の 2 つのメソッドのいずれかが含まれます。
toString — このメソッドは出力 permission=[all] を生成します。
toXML — このメソッドは次の出力を生成します。
<PolicyDecision>
<ResponseAttributes>
</ResponseAttributes>
<ActionDecision timeToLive="1179344504796">
<AttributeValuePair>
<Attribute name="permission"/>
<Value>all </Value>
</AttributeValuePair>
<Advices>
</Advices>
</ActionDecision>
</PolicyDecision>
あるリソースに複数のアクセス権が設定されている場合、Access Manager はその評価の一部としてそれらのアクセス権のリストを返します。たとえば、次の 2 つのロールを持つユーザーが居るとします。
Admin — リソース UserForm の ALL アクセス権
Employee — リソース UserForm の CREATE および READ アクセス権
Access Manager はポリシーの評価後、そのユーザーの UserForm に関する次の 2 つのシナリオのいずれか を返します。
toString メソッド: permission=[all, create, read] を生成します
toXML メソッド: 次の出力を生成します
<PolicyDecision>
<ResponseAttributes>
</ResponseAttributes>
<ActionDecision timeToLive="1179346529031">
<AttributeValuePair>
<Attribute name="permission"/>
<Value>all </Value>
<Value>create </Value>
<Value>read </Value>
</AttributeValuePair>
<Advices>
</Advices>
</ActionDecision>
</PolicyDecision>
アクセスレベルの決定 PolicyDecision として返されるアクセス権の情報は、実行時に AccessLevel などのクラス内に格納し、1 つのオブジェクトまたは一連のオブジェクトとして管理できます。ある特定のリソースに対する一連のアクセスレベルをどのように処理するかは、アプリケーションの要件に応じて異なる場合があります。EB Health では、後続の処理が容易になるように、アクセス権の情報を AccessLevel クラスの結果セットとして返す必要があります。Claims アプリケーションはセキュリティー対策として、アクセスの許可とページのレンダリングを行う前に、結果セットをクエリーして具体的なアクセス権を取得します。
この AuthZClientProxy クラス を参照してください。ここでは、クライアントプロキシクラス (AuthZClientProxy) が Access Manager SDK をカプセル化し、ActionDecision に従って AccessLevel オブジェクトを作成しています。この方式は、Access Manager SDK に固有のコードをカプセル化することで、背後の Access Manager SDK のファサードとして機能しています。
また、プロキシクライアントのインスタンス化は、Web 層から HttpSerlvetRequest を使って行うことも、EJB 層から EjBContext を使って行うことも可能です。どちらのコンテキストオブジェクトも、背後のポリシーエージェントによって作成された SSOToken をプロキシクライアントが取得できるようにします。EB Health では、パフォーマンスの向上を図るために、ポリシー決定も Access Manager SDK によってキャッシュされます。キャッシュの設定については、ポリシーエージェントの設定ファイルを参照してください。
EB Health では、Web コンポーネント内と EJB コンポーネント内でクライアントプロキシが実装されています。このプロキシは、Access Manager SDK に固有の呼び出しをカプセル化し、抽象化された情報をアプリケーションに送信します。背後のポリシーエージェントは、Web 層内での処理がスムーズに進むように、URL_POLICY モードを要求します。
重要: 対象の情報が各層に伝達されてポリシーが正しく評価されるように、必ず正しいモードを設定してください。そうしないと、アプリケーションへのアクセスが拒否されます。
関連するコードセグメントを次に示します。
public void doGetPost (HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
AuthZClientProxy client = new AuthZClientProxy(request);
AuthZResultSet levels = client.authorize(resource);
If (levels.hasAll()) {
//User has all permission to resource
} else if (level.hasCreate()) {
//User has create permission to resource
} else if (level.hasRead()) {
//User has read only permission to resource
} else if (level.hasUpdate()) {
//User has update permission to resource
} else if (level.hasDelete()) {
//User has delete permission to resource
} else {
//User has other access level or no permission to resource
}
EJB 層にも同じコードが存在しています。違いは、インスタンス化する際に EJBContext をコンストラクタに渡す必要がある点だけです。その後、Access Manager SDK は、リソースにアクセスしようとしている対象のアイデンティティートークンを、EJBContext を使って取得します。認証時に、Access Manager はユーザートークンを作成し、それを Web 層と EJB 層に伝えます。
次のコードセグメントは、このシナリオを示したものです。
EJBContext ctx;
AuthZClientProxy client = new AuthZClientProxy(ctx);
AuthZResultSet levels = client.authorize(resource);
If (levels.hasAll()) {
//User has all permission to resource
} else {
if (levels.hasCreate()) {
//User has create permission to resource
}
if (levels.hasRead()) {
//User has read-only permission to resource
}
if (levels.hasUpdate()) {
//User has update permission to resource
}
if (levels.hasDelete()) {
//User has delete permission to resource
}
} // else
重要: EJB 層のポリシー評価 API の実装が機能するためには、ポリシーエージェントを J2EE_POLICY または ALL モードに設定しておく必要があります。そうしないと、アプリケーションへのアクセスが拒否されます。
EB Health の例からわかるように、Java EE アプリケーションのリソースをセキュリティー保護するためのプラットフォームである Access Manager を使えば、最小限の労力を費やすだけで、必要な拡張をカスタマイズできます。EB Health の事例でも、ほかのすべての企業実装と同じく、サービスレベル要件を満たすためには周到なアーキテクチャーが必要となります。すべてのアプリケーションでのポリシー適用を制御できる適切なプロセスが存在している必要があります。
このシリーズのパート 2 では、一括処理によるポリシー評価の手法を使って Access Manager への要求送信数を減らし、パフォーマンスを向上させる方法について説明します。また、その記事では、Access Manager と Microsoft .NET サービスの相互運用方法や、EB Health が Access Manager を使って両プラットフォームをセキュリティー保護する方法についても説明します。引き続きお読みください。
貴重なフィードバックや提案を行ってくれた Bartosz Adamczyk、Rajeev Angal、Dilli Dorai、Rajeev Parekh、Pat Patterson、Aravindan Ranganathan の各氏に、深く感謝します。
Sun Java System Access Manager
関連出版物
Sun 開発者サービス