この章では、JavaEEアプリケーションおよびJavaSEアプリケーションで認可を開発、構成する方法を説明します。この章の内容は次のとおりです。
この章の情報では、第13.3.3項「プログラム的な認可」の内容を十分に理解していることが前提となっています。
この項では、JavaEEとJAASのモデルで使用可能な認可を比較検討しています。この項の内容は次のとおりです。
Java 2ポリシーは、特定の場所からロードされた署名付きコードに付与されるパーミッションを指定します。JAASポリシーは、オプションのプリンシパル・リストを指定できるようにすることで、Java 2の権限を拡張します。これにより、特定の場所からロードされた(多くの場合は署名付きの)コードにのみパーミッションが付与され、このリストにあるプリンシパルで表されるユーザーによって実行されます。
ポリシー・ストアは、システムおよびアプリケーションに固有のポリシーとロールを格納するリポジトリです。アプリケーション・ロールは、アプリケーション固有のエンタープライズ・ユーザーおよびグループ(管理ロールなど)に付与(マップ)できます。ポリシーでは、これらのロール、グループまたはユーザーにプリンシパルとしてパーミッションを付与できます。
ポリシー関連のセキュリティ・アーティファクトの詳細は、第3章「ポリシー・ストアの基本」を参照してください。
アプリケーションでは、認可の適用をコンテナに委任できるほか、checkPermission、checkBulkAuthorization、getGrantedResourcesなどのメソッドのコールによってポリシー確認を自身で適用する実装も可能です。
APIコールを使用したポリシー確認の詳細は、「ポリシーの確認」を参照してください。
JavaEE認可モデルでは、ロール・メンバーシップを使用して、EJBメソッドおよびURLで参照するWebリソースへのアクセスを制御します。ポリシーによってユーザーとロールにパーミッションが割り当てられ、ポリシーがコンテナで適用されてリソースが保護されます。
JavaEEモデルでは、次のいずれかの方法で認可が実装されます。
宣言的。この方法では、認可ポリシーがデプロイメント・ディスクリプタで指定されます。コンテナはデプロイメント・ディスクリプタから認可ポリシーを読み取って実施します。認可を実施するための特別なアプリケーション・コードは必要ありません。
プログラム的。この方法では、アプリケーション・コードで認可ポリシーを確認します。このコードによって、特定のコード・セクションの実行に適したパーミッションがサブジェクトにあるかどうかを確認します。サブジェクトに適切なパーミッションが与えられていない場合、コードは例外をスローします。
表17-1は、各方法の長所と短所を示しています。
表17-1 Java EEモデルの認可の比較
| 認可のタイプ | 長所 | 短所 |
|---|---|---|
|
宣言的 |
コーディングが不要。デプロイメント・ディスクリプタのみを変更すればよいため、更新が簡単。 |
認可のレベルが大まかであり、URLレベルまたはメソッド・レベル(EJBの場合)で指定される。 |
|
プログラム的 |
アプリケーション・コードで指定され、よりきめ細かいレベルでコードを保護できる。 |
コード変更や再コンパイルを伴うため、更新は容易ではない。 |
コンテナは、その内部で稼働中のアプリケーションに対して、宣言的およびプログラム的という2つの方法で認可を提供できます。次の各項ではこれらの方法を説明して例を示します。
宣言的な認可では、URLベースのリソース(サーブレットやページなど)やEJBのメソッドに対するアクセスを制御できます。
宣言的な認可を構成する基本手順は、次のとおりです。
標準のデプロイメント・ディスクリプタで、保護するリソース(Web URL、EJBメソッドなど)と、そのリソースへのアクセス権を持つ論理ロールを指定します。
または、JavaEE 1.5は注釈をサポートしているため、デプロイメント・ディスクリプタではなくコード注釈を使用します。
固有デプロイメント・ディスクリプタ(web.xmlなど)では、手順1で定義した論理ロールをエンタープライズ・グループにマップします。
詳細は、『Oracle Fusion Middleware Enterprise JavaBeans Developer's Guide for Oracle Containers for Java EE』の「セキュリティ・サービスの使用方法」を参照してください。
プログラム的な認可では、宣言的な方法よりもきめ細かい認可を実現できます。プログラム的な認可では、メソッドisUserInRole(サーブレットおよびJSPの場合)またはメソッドisCallerInRole(EJBの場合)をアプリケーションのコードから呼び出す必要があります。これらはどちらも標準のJava APIに用意されています。
これらのメソッドは、認可の決定に関してロール・メンバーシップにある程度は依存しますが、これらの使用により、ユーザーは、リソース・レベル(EJBのメソッドまたはURL)のアクセス制御に限定されることがないため、よりきめ細かく認可の決定を制御できるようになります。
次の例では、メソッドisUserInRoleをコールするサーブレットを示しています。サーブレットをパッケージ化しているEARファイルには構成ファイルweb.xmlおよびweblogic-application.xmlが含まれており、これらのファイルには次の構成の断片が含まれていることを前提とします。
web.xml
<!-- security roles --> <security-role> <role-name>sr_developer</role-name> </security-role>
weblogic-application.xml
次のスニペットは、ユーザーweblogicとセキュリティ・ロールsr_developer間のマッピングを示しています。
<wls:security-role-assignment> <wls:role-name>sr_developer</wls:role-name> <wls:principal-name>weblogic</wls:principal-name> </wls:security-role-assignment>
isUserInRoleを呼び出すコード例
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
public class PolicyServlet extends HttpServlet {
public PolicyServlet() {
super();
}
public void init(ServletConfig config)
throws ServletException {
super.init(config);
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
final ServletOutputStream out = response.getOutputStream();
response.setContentType("text/html");
out.println("<HTML><BODY bgcolor=\"#FFFFFF\">");
out.println("Time stamp: " + new Date().toString());
out.println( "<br>request.getRemoteUser = " + request.getRemoteUser() + "<br>");
out.println("request.isUserInRole('sr_developer') = " + request.isUserInRole("sr_developer") + "<br>");
out.println("request.getUserPrincipal = " + request.getUserPrincipal() + "<br>");
out.println("</BODY>");
out.println("</HTML>");
}
}
JAAS認可ではパーミッションを使用しますが、ロールの概念も使用できます。認可ポリシーによって、パーミッションがサブジェクト(ロール、グループまたはユーザー)にバインドされ、さらに必要に応じてソース・コードにもバインドされます。ロールの付与は、addPrincipalsToAppRoleのコールで実現します。
パーミッションはSecurityManagerまたはAccessControllerのコールによって評価され、これらのメソッドでリソースをきめ細かく制御できます。
このモデルでは、認可ポリシーで次の情報が指定されます。
アプリケーション・ロールおよびエンタープライズ・グループ。
ユーザー、グループおよびコード・ソースに付与されるパーミッション。ユーザーおよびグループの場合は、これによってアクセスが許可されるユーザーまたはグループのメンバーが決定されます。コード・ソースの場合は、これによって、コードが実行できるアクションが決定されます。
このモデルを使用してプログラミングする場合、機密性の高いコード行の前に、現在のユーザーまたはロールがそのコードにアクセスするための適切なパーミッションを付与されているかどうかを確認するコールを記述します。ユーザーが適切なパーミッションを持っている場合は、コードが実行されます。適切なパーミッションが与えられていない場合、コードは例外をスローします。
JAASの標準パーミッションの詳細は、http://java.sun.com/javase/6/docs/technotes/guides/security/permissions.htmlを参照してください。
特別な設定を必要とせずに使用可能なパーミッション・クラスの詳細は、「リソース・パーミッション」を参照してください。
JAASおよびOPSS認可では、クラスを環境にロードして実行するときに、そのクラスで実行できる操作を制御することが基本になっています。
この項の内容は次のとおりです。
OPSSでは、XMLベースとLDAPベースのどちらのポリシー・ストアにあるリソース・カタログでも指定でき、実行時に使用できます。ただし、ファイルベースのポリシー・ストアにはいくつかの制限事項があります。詳細は、「ファイルベースのポリシー・ストアに対してPS2でサポートされていないメソッド」を参照してください。
リソース・カタログを使用するアプリケーション・ポリシー・モデルの説明は、Oracle Authorization Policy Manager管理者ガイドを参照してください。
この項では、リソース・カタログ・モデルの利点を説明し、XML形式の様々なリソース・カタログ要素の構成例を紹介します。また、これらに関連する機能を説明して、それらの機能にプログラム的にアクセスする方法を示します。この項の内容は次のとおりです。
スキーマ要素の詳細は、付録B「ファイルベースのアイデンティティ・ストアとポリシー・ストアのリファレンス」を参照してください。
リソース・カタログを使用すると、次の利点により11gR1ポリシー・モデルの機能向上が実現します。
判読可能な用語でポリシーおよび保護アーティファクトが記述されます。
アプリケーション・ソース・コードに関係なく、またこれらのコードに関する知識を必要とせずに、ポリシーを定義し、変更できます。
保護アーティファクトを参照および検索できます。
後で認可ポリシーで使用できるビルディング・ブロック(権限またはパーミッションのセット)に保護アーティファクトをグループ化できます。
リソース・カタログは、リソース・タイプ、リソース、アクションおよび権限で構成されます。これらのアーティファクト間の関係を図17-1に示します。
リソース・カタログは、次のスキーマ要素によって(アプリケーションのjazn-data.xmlまたはsystem-jazn-data.xmlで)指定します。
次のコードは、リソース・タイプの構成を示しています。
<resource-types>
<resource-type>
<name>TaskFlowResourceType</name>
<display-name>TaskFlowResourceType_disp</display-name>
<description>Resource Type for Task Flow</description>
<provider-name>resTypeProv</provider-name>
<matcher-class>
oracle.adf.controller.security.TaskFlowPermission</matcher-class>
<actions-delimiter>,</actions-delimiter>
<actions>customize,view</actions>
</resource-type>
</resource-types>
リソース・タイプの指定では次の点が適用されます。
名前は必須で、大文字と小文字は区別されません。
プロバイダ名は省略可能で、大文字と小文字は区別されません。外部ストア(OPSSドメイン・ポリシー・ストア以外のストア)で管理しているリソースがある場合にプロバイダを使用することが普通です。
プロバイダ名を指定する場合、<provider-name>要素に記述したクラスはリソース・ファインダとして使用されます。このタイプのリソースに対する問合せ(ResourceManager検索APIを使用して実行)は、OPSSドメイン・ポリシー・ストアに対して組込みのリソース・ファインダを使用せずに、このマッチャ・クラスに委任されます。
マッチャ・クラス名は必須で、大文字と小文字が区別されます。
説明の文字列は省略可能で、大文字と小文字は区別されません。
表示名は省略可能で、大文字と小文字は区別されません。
アクションの文字列はオプションで、大文字と小文字が区別されます。リソース・タイプのアクションのリストは空でもかまいません。アクション・リストが空の場合、リソース・タイプのインスタンスに対するアクションは外部で指定され、OPSSでは不定になります。
リソース・タイプのエントリはWLSTコマンドで管理できます。詳細は、第7.4.2.11項「createResourceType」、第7.4.2.12項「getResourceType」および第7.4.2.13項「deleteResourceType」を参照してください。
パーミッション・クラスでは、リソースに対して権限受領者が実行できるアクションを制御する手段が提供されます。アプリケーションの設計段階では、アクション、ターゲット照合および暗黙の論理が実行時に想定どおりに機能するようにカスタムのパーミッション・クラスを使用して全面的に制御できます。その場合でも、サーバーのシステム・クラスパスでカスタムのパーミッション・クラスを指定し、必要に応じてそのパーミッション・クラスを使用可能にしてロードできるようにしておく必要があります。ただし、環境のシステム・クラス・パスの変更は困難で、環境によってはそのような変更ができないこともあります。
OPSSには、アプリケーションまたはシステムのリソースを保護するために、どの権限でもパーミッション・クラスとして使用できるoracle.security.jps.ResourcePermissionクラスが用意されています。したがって、アプリケーション開発者がカスタムのパーミッション・クラスを記述する必要はありません。ResourcePermissionは、特別な設定を必要とせずに利用でき、サポートされているあらゆるポリシー・プロバイダに格納されている権限内で容易にパーミッションに使用できるからです。
ResourcePermissionクラスを使用するパーミッションは、リソース・パーミッションと呼ばれ、次のXMLサンプルで示している形式に基づいてリソース・タイプ、リソース名およびオプションのアクション・リストを指定します。
<permission> <class>oracle.security.jps.ResourcePermission</class> <name>resourceType=type,resourceName=name</name> <actions>character-separated-list-of-actions</actions> </permission>
この指定では、タイプ名にエンコードしたリソース・タイプを定義する必要があります。リソース・タイプの情報は実行時には使用されませんが、リソース・パーミッションを正常に移行するにはリソース・タイプを定義しておく必要があります。また、リソース・タイプは、管理者によるリソースのモデル化とリソース使用の管理に役立ちます。リソース・タイプの指定の詳細は、「リソース・タイプ」を参照してください。
次のコードは、リソース・パーミッションの指定と対応する必須のリソース・タイプを示しています。
<permission> <class>oracle.security.jps.ResourcePermission</class> <name>resourceType=epm.calcmgr.permission,resourceName=EPM_Calc_Manager</name> </permission> <resource-types> <resource-type> <name>epm.calcmgr.permission</name> <display-name>CalcManager ResourceType</display-name> <description>Resourcetype for managing CalcManager grants</description> <provider-name></provider-name> <matcher-class>oracle.security.jps.ResourcePermission</matcher-class> <actions-delimiter>,</actions-delimiter> <actions></actions> </resource-type> </resource-types> <permission> <class>oracle.security.jps.ResourcePermission</class> <name>resourceType=oracle.bi.publisher.Reports,resourceName=GLReports</name> <actions>develop;schedule</actions> </permission> <resource-types> <resource-type> <name>oracle.bi.publisher.Reports</name> <display-name>BI Publisher Reports</display-name> <provider-name></provider-name> <matcher-class>oracle.security.jps.ResourcePermission</matcher-class> <actions-delimiter>;</actions-delimiter> <actions>view;develop;schedule</actions> </resource-type> </resource-types>
リソース・パーミッションに関連付けられているリソース・タイプには、空のアクション・リストを指定してもかまいません。次の重要点がリソース・パーミッションに適用されます。
名前は、次の形式に従う必要があります。
resourceType=aType,resourceName=aName
リソース・パーミッションのリソース・タイプを定義する必要があります。このリソース・タイプはResourcePermission.getType()メソッドで返されます。
区切り文字付きのアクション・リストはオプションです。指定する場合は、関連するリソース・タイプで指定されているアクションから選択する必要があります。このリストはResourcePermission.getActions()メソッドで返されます。
このリストの項目の区切り文字には、関連するリソース・タイプの<actions-delimiter>で指定されている文字を使用する必要があります。
パーミッションで使用するリソースの表示名は、ResourcePermission.getResourceName()メソッドで返されます。
リソース・パーミッションでは、ワイルドカードの使用はサポートされていません。
リソース・パーミッションはポリシー管理APIで管理できます。リソース・タイプはWLSTコマンドで管理できます。詳細は、第7.4.2項「WLSTコマンドを使用したポリシーの管理」を参照してください。
次のコード・スニペットは、リソース・パーミッションのインスタンス化およびリソース・パーミッションをプログラム的に確認する方法を示しています。このコード・スニペットは、「リソース・パーミッションの構成」で説明している構成例の1つに基づいています。
ResourcePermission rp =
new ResourcePermission("oracle.bi.publisher.Reports","GLReports","develop");
JpsAuth.checkPermission(rp);
実行時にリソース・パーミッションで次の4つの条件が満たされると、そのパーミッションは適切であると判断されます。
パーミッションがResourcePermisionクラスのインスタンスである。
リソース・タイプ名(最初の引数)がリソース・タイプの名前に一致する(大文字小文字の区別はなし)。
リソース名(2つ目の引数)がリソース・インスタンスの名前に完全に一致する。
アクション・リスト(3つ目の引数)が、リソース・タイプで指定されているアクションのカンマ区切りリストである。
リソースは、リソース・タイプに関連付けられており、この関連付けられているリソース・タイプを指定する必要があります。
次のコードは、リソース(リソース・インスタンス)の構成を示しています。
<resources>
<resource>
<name>resource1</name>
<display-name>Resource1DisplayName</display-name>
<description>Resource1 Description</description>
<type-name-ref>TaskFlowResourceType</type-name-ref>
</resource>
</resources>
この例では、<type-name-ref>要素で参照するリソース・タイプの定義が必要です。リソース・タイプTaskFlowResourceの定義については、「リソース・タイプ」で構成のコードを参照してください。
リソースのエントリでは、様々な文字列の大文字と小文字の区別に関して次の点に留意してください。
名前では、大文字と小文字が区別されます。
説明の文字列では、大文字と小文字は区別されません。
表示名では、大文字と小文字は区別されません。
次のコードは、パーミッション・セット(または権限)の構成を示しています。
<permission-sets>
<permission-set>
<name>permsetName</name>
<member-resources>
<member-resource>
<type-name-ref>TaskFlowResourceType</type-name-ref> <resource-name>resource1</resource-name>
<actions>customize,view</actions>
</member-resource>
</member-resources>
</permission-set>
</permission-sets>
パーミッション・セットに関して、次の点に留意してください。
<member-resource>で指定するアクションは、<resource-name-ref>で参照しているリソース・タイプで指定されているアクションから選択する必要があります。
<member-resources>には、複数の<member-resource>要素を指定できます。
パーミッション・セットには1つ以上のリソースが必要です。
どの権限でも参照していないパーミッション・セットが存在していてもかまいません。つまり、パーミッション・セットをプリンシパルに必ずしも付与する必要はありません。
また、パーミッション・セットのエントリで次の文字列を使用する場合は、大文字小文字の区別のルールに従う必要があります。
名前では、大文字と小文字は区別されません。
説明の文字列では、大文字と小文字は区別されません。
表示名では、大文字と小文字は区別されません。
次のコードは、リソース・カタログを使用したアプリケーション・ポリシーの構成を示しています(参照はコードに含まれていません)。
<jazn-policy>
<grant>
<grantee>
<principals>
<principal>
<class>
oracle.security.jps.service.policystore.ApplicationRole</class>
<name>AppRole</name>
<guid>F5494E409CFB11DEBFEBC11296284F58</guid>
</principal>
</principals>
</grantee>
<!-- entitlement-based permissions -->
<permission-set-refs>
<permission-set-ref>
<name>MyEntitlement</name>
</permission-set-ref>
</permission-set-refs>
</grant>
</jazn-policy>
</application>
</applications>
</policy-store>
<jazn-policy></jazn-policy>
</jazn-data>
リソース・カタログ・アーティファクトをポリシー管理APIで管理できます。具体的には、次のインタフェースがリソース・カタログのアーティファクトに直接関連しています。これらはすべてインタフェースoracle.security.jps.service.policystore.EntityManagerの下位インタフェースです。
GrantManager - このインタフェースに用意されているメソッドでは、検索条件を使用して権限を問い合せ、リソース・カタログ・アーティファクトの様々な組合せに適合する権限のリストを取得して、プリンシパルに対してパーミッションを付与または取り消すことができます。
PermissionSetManager - このインタフェースに用意されているメソッドでは、パーミッション・セット(権限)の作成、変更および問合せを実行できます。
ResourceManager - このインタフェースに用意されているメソッドでは、リソース(リソース・インスタンス)の作成、削除および変更を実行できます。
ResourceTypeManager - このインタフェースに用意されているメソッドでは、リソース・タイプの作成、削除、変更および問合せを実行できます。
これらのインタフェースの詳細は、JavadocドキュメントのOracle Fusion Middleware Oracle Platform Security Services Java APIリファレンスを参照してください。
次のコード・スニペットは、リソース・タイプ、リソース・インスタンス、アクションおよびパーミッション・セットの作成を示しています。
import oracle.security.jps.service.policystore.entitymanager.*;
import oracle.security.jps.service.policystore.search.*;
import oracle.security.jps.service.policystore.info.resource.*;
import oracle.security.jps.service.policystore.info.*;
import oracle.security.jps.service.policystore.*;
import java.util.*;
public class example {
public static void main(String[] args) throws Exception {
ApplicationPolicy ap;
ResourceTypeManager rtm = ap.getEntityManager(ResourceTypeManager.class);
ResourceTypeSearchQuery query = new ResourceTypeSearchQuery();
query.setANDMatch();
query.addQuery(ResourceTypeSearchQuery.SEARCH_PROPERTY.NAME, false, ComparatorType.EQUALITY, "resourceType", BaseSearchQuery.MATCHER.EXACT);
List<ResourceTypeEntry> allResourceTypes = rtm.getResourceTypes(query);
ResourceManager rm = ap.getEntityManager(ResourceManager.class);
ResourceSearchQuery ResourceQuery = new ResourceSearchQuery();
ResourceQuery.setANDMatch();
ResourceQuery.addQuery(ResourceSearchQuery.SEARCH_PROPERTY.NAME, false, ComparatorType.EQUALITY, "R2", BaseSearchQuery.MATCHER.EXACT);
List<ResourceEntry> allResources = rm.getResources("RT2", ResourceQuery);
PermissionSetManager psm = ap.getEntityManager(PermissionSetManager.class);
PermissionSetSearchQuery pssq = new PermissionSetSearchQuery();
pssq.setANDMatch();
pssq.addQuery(PermissionSetSearchQuery.SEARCH_PROPERTY.NAME, false, ComparatorType.EQUALITY, "PS1", BaseSearchQuery.MATCHER.EXACT);
List<PermissionSetEntry> allPermSets = psm.getPermissionSets(pssq);
RoleCategoryManager rcm = ap.getEntityManager(RoleCategoryManager.class);
RoleCategorySearchQuery rcsq = new RoleCategorySearchQuery();
rcsq.setANDMatch();
rcsq.addQuery(RoleCategorySearchQuery.SEARCH_PROPERTY.NAME, false, ComparatorType.EQUALITY, "roleCategoryCartoon", BaseSearchQuery.MATCHER.EXACT);
List<RoleCategoryEntry> allRoleCategories = rcm.getRoleCategories(rcsq);
}
}
次のコード・スニペットは、リソース・カタログ要素を使用した複雑な問合せを示しています。
//ApplicationPolicy ap as in the preceeding example
ResourceTypeManager rtm = ap.getEntityManager(ResourceTypeManager.class);
ResourceTypeSearchQuery query = new ResourceTypeSearchQuery();
query.setANDMatch();
query.addQuery(ResourceTypeSearchQuery.SEARCH_PROPERTY.NAME, false, ComparatorType.EQUALITY, "resourceType", BaseSearchQuery.MATCHER.EXACT);
List<ResourceTypeEntry> enties = rtm.getResourceTypes(query);
ResourceManager rm = ap.getEntityManager(ResourceManager.class);
ResourceSearchQuery ResourceQuery = new ResourceSearchQuery();
ResourceQuery.setANDMatch();
ResourceQuery.addQuery(ResourceSearchQuery.SEARCH_PROPERTY.NAME, false, ComparatorType.EQUALITY, "R2", BaseSearchQuery.MATCHER.EXACT);
ArrayList<BaseSearchQuery> querries = ResourceQuery.getQueries();
List<ResourceEntry> resources = rm.getResources("RT2", ResourceQuery);
PermissionSetManager psm = ap.getEntityManager(PermissionSetManager.class);
PermissionSetSearchQuery pssq = new PermissionSetSearchQuery();
pssq.setANDMatch();
pssq.addQuery(PermissionSetSearchQuery.SEARCH_PROPERTY.NAME, false, ComparatorType.EQUALITY, "PS1", BaseSearchQuery.MATCHER.EXACT);
List<PermissionSetEntry> psets = psm.getPermissionSets(pssq);
RoleCategoryManager rcm = ap.getEntityManager(RoleCategoryManager.class);
RoleCategorySearchQuery rcsq = new RoleCategorySearchQuery();
rcsq.setANDMatch();
rcsq.addQuery(RoleCategorySearchQuery.SEARCH_PROPERTY.NAME, false, ComparatorType.EQUALITY, "roleCategoryCartoon", BaseSearchQuery.MATCHER.EXACT);
ArrayList<BaseSearchQuery> queries = rcsq.getQueries();
List<RoleCategoryEntry> rcs = rcm.getRoleCategories(rcsq);
次のコード・サンプルは、権限を作成する方法を示しています。
GrantManager gm = ap.getEntityManager(GrantManager.class); Set<PrincipalEntry> pe = new HashSet<PrincipalEntry>(); List<AppRoleEntry> are = ap.searchAppRoles(appRoleName); pe.addAll(are); gm.grant(pe, null, permissionSetName);
この項では、プログラム上でポリシーを確認する方法をいくつか示します。この項の内容は次のとおりです。
Oracle Fusion Middlewareは、次の標準クラスでメソッドcheckPermissionの使用をサポートしています。
java.lang.SecurityManager
java.security.AccessController
また、Oracle Fusion Middlewareは、クラスoracle.security.jps.util.JpsAuthのメソッドcheckPermissionの使用もサポートしています。
checkPermissionは、(前述の2つではなく)クラスJpsAuthで使用することをお薦めします。これは、このクラスのほうがデバッグ・サポートとパフォーマンスにおいて優れており、監査もサポートされるためです。
静的メソッドAccessController.checkPermissionは、デフォルトのアクセス制御コンテキスト(スレッド作成時に継承されるコンテキスト)を使用します。その他のコンテキストでパーミッションを確認するには、特定のAccessControlContextインスタンスでインスタンス・メソッドcheckPermissionをコールします。
次の表に示すように、メソッドcheckPermissionはJAASモード(第14章「サーブレット・フィルタとEJBインターセプタの構成」を参照)の値に応じて動作します。
表17-2 JAASモードに応じたcheckPermissionの動作
| JAASモードの設定 | checkPermission |
|---|---|
|
オフまたは未定義 |
有効なセキュリティ・ポリシーに基づくコードベースのセキュリティを実施します。サブジェクトベースのセキュリティに対するプロビジョニングはありません。 |
|
doAs |
|
|
doAsPrivileged |
NULLアクセス制御コンテキストを使用してサブジェクトベースのセキュリティを適用します。 |
|
subjectOnly |
パーミッションの評価時に、プリンシパルにかかわる権限付与のみが考慮されます(コードベースにかかわる権限付与は無視されます)。 |
|
注意: checkPermissionをdoAsブロックの中でコールして、パーミッション・チェックのコールが失敗した場合、失敗した保護ドメインを表示するには、システム・プロパティjava.security.debug=access,failureを設定する必要があります。 |
次の例は、パーミッションをチェックするサーブレットを示しています。サーブレットをパッケージ化しているEARファイルに構成ファイルjazn-data.xmlおよびweb.xmlが含まれていることが前提となります。
jazn-data.xml
アプリケーションのファイルベースのポリシー・ストアは次のとおりです。
<?xml version="1.0" ?>
<jazn-data>
<policy-store>
<applications>
<application>
<name>MyApp</name>
<app-roles>
<app-role>
<name>AppRole</name>
<display-name>AppRole display name</display-name>
<description>AppRole description</description>
<guid>F5494E409CFB11DEBFEBC11296284F58</guid>
<class>oracle.security.jps.service.policystore.ApplicationRole</class>
</app-role>
</app-roles>
<role-categories>
<role-category>
<name>MyAppRoleCategory</name>
<display-name>MyAppRoleCategory display name</display-name>
<description>MyAppRoleCategory description</description>
</role-category>
</role-categories>
<resource-types>
<resource-type>
<name>MyResourceType</name>
<display-name>MyResourceType display name</display-name>
<description>MyResourceType description</description>
<provider-name>MyResourceType provider</provider-name>
<matcher-class>oracle.security.jps.ResourcePermission</matcher-class>
<actions-delimiter>,</actions-delimiter>
<actions>write,read</actions>
</resource-type>
</resource-types>
<resources>
<resource>
<name>MyResource</name>
<display-name>MyResource display name</display-name>
<description>MyResource description</description>
<type-name-ref>MyResourceType</type-name-ref>
</resource>
</resources>
<permission-sets>
<permission-set>
<name>MyEntitlement</name>
<display-name>MyEntitlement display name</display-name>
<description>MyEntitlement description</description>
<member-resources>
<member-resource>
<type-name-ref>MyResourceType</type-name-ref>
<resource-name>MyResource</resource-name>
<actions>write</actions>
</member-resource>
</member-resources>
</permission-set>
</permission-sets>
<jazn-policy>
<grant>
<grantee>
<principals>
<principal>
<class>
oracle.security.jps.service.policystore.ApplicationRole</class>
<name>AppRole</name>
<guid>F5494E409CFB11DEBFEBC11296284F58</guid>
</principal>
</principals>
</grantee>
<!-- entitlement-based permissions -->
<permission-set-refs>
<permission-set-ref>
<name>MyEntitlement</name>
</permission-set-ref>
</permission-set-refs>
</grant>
</jazn-policy>
</application>
</applications>
</policy-store>
<jazn-policy></jazn-policy>
</jazn-data>
web.xml
フィルタJpsFilterは次のように構成されます。
<web-app>
<display-name>PolicyTest: PolicyServlet</display-name>
<filter>
<filter-name>JpsFilter</filter-name>
<filter-class>oracle.security.jps.ee.http.JpsFilter</filter-class>
<init-param>
<param-name>application.name</param-name>
<param-value>PolicyServlet</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>JpsFilter</filter-name>
<servlet-name>PolicyServlet</servlet-name>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>...
コード例
次の例では、Subject.doAsPrivilegedがJpsSubject.doAsPrivilegedによって置換される場合があります。
import javax.security.auth.Subject;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.security.*;
import java.util.Date;
import java.util.PropertyPermission;
import java.io.FilePermission;
public class PolicyServlet extends HttpServlet {
public PolicyServlet() {
super();
}
public void init(ServletConfig config)
throws ServletException {
super.init(config);
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
final ServletOutputStream out = response.getOutputStream();
response.setContentType("text/html");
out.println("<HTML><BODY bgcolor=\"#FFFFFF\">");
out.println("Time stamp: " + new Date().toString());
out.println( "<br>request.getRemoteUser = " + request.getRemoteUser() + "<br>");
out.println("request.isUserInRole('sr_developer') = " + request.isUserInRole("sr_developer") + "<br>");
out.println("request.getUserPrincipal = " + request.getUserPrincipal() + "<br>");
Subject s = null;
s = Subject.getSubject(AccessController.getContext());
out.println("Subject in servlet " + s);
out.println("<br>");
final RuntimePermission rtPerm = new RuntimePermission("getClassLoader");
try {
Subject.doAsPrivileged(s, new PrivilegedAction() {
public Object run() {
try {
AccessController.checkPermission(rtPerm);
out.println("<br>");
out.println("CheckPermission passed for permission: " + rtPerm+ " seeded in application policy");
out.println("<br>");
} catch (IOException e) {
e.printStackTrace();
printException ("IOException", e, out);
} catch (AccessControlException ace) {
ace.printStackTrace();
printException ("Accesscontrol Exception", ace, out);
}
return null;
}
}, null);
} catch (Throwable e) {
e.printStackTrace();
printException("application policy check failed", e, out);
}
out.println("</BODY>");
out.println("</HTML>");
}
void printException(String msg, Throwable e, ServletOutputStream out) {
Throwable t;
try {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw, true);
e.printStackTrace(pw);
out.println("<p>" + msg + "<p>");
out.println("<code>");
out.println(sw.getBuffer().toString());
t = e;
/* Print the root cause */
while ((t = t.getCause()) != null) {
sw = new StringWriter();
pw = new PrintWriter(sw, true);
t.printStackTrace(pw);
out.println("<hr>");
out.println("<p> Caused By ... </p>");
out.println(sw.getBuffer().toString());
}
out.println("</code><p>");
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
Oracle Fusion Middlewareは、標準クラスjavax.security.auth.Subjectで、doAsメソッドとdoAsPrivilegedメソッドをサポートします。
ただし、これらのメソッドは、パフォーマンスが高く、監査機能も備えているため、oracle.security.jps.util.JpsSubjectクラスで使用することをお薦めします。
|
注意: checkPermissionをdoAsブロックの中でコールして、パーミッション・チェックのコールが失敗した場合、失敗した保護ドメインを表示するには、システム・プロパティjava.security.debug=access,failureを設定する必要があります。 |
メソッドcheckBulkAuthorizationでは、サブジェクトが1つ以上のリソース・アクションにアクセスできるかどうかを判断できます。具体的には、渡したリソースの中で、渡したサブジェクトに対してアクセスが許可されているリソース・アクションのセットを返します。
(JavaSEアプリケーションで)このメソッドを呼び出す場合は次の点を確認してください。
システム・プロパティjava.security.policyが、OPSSまたはOracle WebLogic Serverのポリシー・ファイルの場所に設定されている。
アプリケーションでは最初にメソッドsetPolicyがコールされる。
java.security.Policy.setPolicy(new oracle.security.jps.internal.policystore.JavaProvider())
アプリケーションでは、setPolicyをコールした後でcheckBulkAuthorization()がコールされる。
どのアプリケーションでも、checkBulkAuthorizationではコール元から次の情報が得られることが前提となっています。
ユーザーおよびエンタープライズ・ロールのプリンシパルが指定されたサブジェクト
各リソースが属するストライプが含まれるリソースのリスト
リソース・パーミッションを使用した権限付与では、必須のリソース・タイプを指定する必要があります。詳細は、「リソース・パーミッション」を参照してください。
checkBulkAuthorizationでも、アプリケーションを実行しているドメインに構成したポリシー・ストア・ストライプを、そのアプリケーションから認識できることが前提となっています。
checkBulkAuthorizationでは、ポリシー・ストアにリソースが存在している必要はありません。
次の機能に関連するメソッドは、ファイルベースのXMLポリシー・ストアを使用しているリリース11gR1 PS2では使用できません(ポリシー・ストアがLDAPベースの場合は使用できます)。
一括認可
複雑な問合せ
連鎖的な削除
一括認可は、インタフェースoracle.security.jps.service.policystoreの次のメソッドでカプセル化されます。
java.util.Set<ResourceActionsEntry>
checkBulkAuthorization(javax.security.auth.Subject subject,
java.util.Set<ResourceActionsEntry> requestedResources)
throws PolicyStoreException
複雑な問合せは、問合せを実行するすべてのメソッドに関連します。ポリシー・ストアがファイルベースの場合、問合せは単純であることが必要です。ファイルベースのポリシー・ストアを使用している場合に、問合せを実行するメソッドに複雑な問合せを渡すとそのメソッドは例外をスローします。
単純な問合せとは、検索条件が1つのみの問合せであり、複雑な問合せとは、複数の検索条件を持つ問合せです。addQueryをコールするたびに問合せには条件が1つ追加されます。
次のコードは、表示名が文字列MyDisplayNameに一致するすべてのパーミッションを返す単純なクエリーの構造を示しています。
PermissionSetSearchQuery query = new PermissionSetSearchQuery();
query.addQuery(PermissionSetSearchQuery.SEARCH_PROPERTY.DISPLAY_NAME,
false,
ComparatorType.EQUALITY,
"MyDisplayName",
BaseSearchQuery.MATCHER.EXACT);
getPermissionSets(query);
次の例は、指定したリソース・タイプおよび指定したリソース・インスタンス名を持つすべてのパーミッション・セットを返す複雑な問合せの構造を示しています。
PermissionSetSearchQuery query = new PermissionSetSearchQuery();
query.addQuery(PermissionSetSearchQuery.SEARCH_PROPERTY.RESOURCE_TYPE,
false,
ComparatorType.EQUALITY,
"MyResourceType",
BaseSearchQuery.MATCHER.EXACT);
query.addQuery(PermissionSetSearchQuery.SEARCH_PROPERTY.RESOURCE_NAME,
false,
ComparatorType.EQUALITY,
"MyResourceInstanceName",
BaseSearchQuery.MATCHER.EXACT);
query.setANDMatch();
getPermissionSets(query);
連鎖的な削除は、ブール型引数cascadeDeleteを使用するメソッドに関連します。ポリシー・ストアがファイルベースの場合にこの引数に指定できる唯一の値は、FALSEです。インタフェースResourceTypeManagerでのこのようなメソッドの例を次に示します。
void deleteResourceType(EntryReference rtRef, boolean cascadeDelete)
throws PolicyObjectNotFoundException,
PolicyStoreOperationNotAllowedException,
PolicyStoreException
この項では、JavaSEアプリケーションで使用するポリシー・ストアと資格証明ストアを構成する方法を説明します。この項の内容は次のとおりです。
これらのアプリケーション向け認証の構成の詳細は、第15.2項「JavaSEアプリケーション向け認証の開発」を参照してください。
JavaSEアプリケーションで認可が機能するためには、システム・プロパティを適切に設定しておく必要があります。すべてのプロパティのリストは、第F.1項「OPSSシステム・プロパティ」を参照してください。
この項では、LDAPベースのストアをポリシー・ストアおよび資格証明ストアとして使用するように設定していることが前提となっています。Oracle Internet Directoryでのノードの設定の詳細は、第7.1.2項「LDAPベースのポリシー・ストアを使用する場合の前提条件」を参照してください。
JavaSEアプリケーションでは、LDAPベースのポリシー・ストアおよび資格証明ストアを使用できます。これらのサービス固有の内容は、アプリケーション・ファイルjps-config-jse.xmlで構成します。
次のコードは、LDAPベースのポリシー・ストアおよび資格証明ストアのインスタンスの構成を示しています。
<serviceInstance provider="ldap.policystore.provider" name="policystore.ldap"> <property value="OID" name="policystore.type"/> <property value="bootstrap" name="bootstrap.security.principal.key"/> <property value="cn=PS1domainRC3" name="oracle.security.jps.farm.name"/> <property value="cn=myTestNode" name="oracle.security.jps.ldap.root.name"/> <property value="ldap://myComp.com:1234" name="ldap.url"/> </serviceInstance> <serviceInstance provider="ldap.credentialstore.provider" name="credstore.ldap"> <property value="bootstrap" name="bootstrap.security.principal.key"/> <property value="cn=PS1domainRC3" name="oracle.security.jps.farm.name"/> <property value="cn=myTestNode" name="oracle.security.jps.ldap.root.name"/> <property value="ldap://myComp.com:1234" name="ldap.url"/> </serviceInstance>
次のコードは、プログラムからLDAPサーバーにアクセスできるようにするためのブートストラップ資格証明ファイル(cwallet.sso)の構成を示しています。
<serviceInstance location="./bootstrap" provider="credstoressp" name="bootstrap.cred"> <property value="./bootstrap" name="location"/> </serviceInstance>
次のコードは、前述のインスタンスを参照するために必要なjpsContextsの構成を示しています。
<jpsContexts default="TestJSE">
<jpsContext name="TestJSE">
<serviceInstanceRef ref="policystore.ldap"/>
<serviceInstanceRef ref="credstore.ldap"/>
</jpsContext>
<jpsContext name="bootstrap_credstore_context">
<serviceInstanceRef ref="bootstrap.cred"/>
</jpsContext>
</jpsContexts>
次のコードは、上記で構成したLDAPベースのポリシー・ストアへの参照をプログラム的に取得する方法を示しています。ここでは、環境で次のようにシステム・プロパティが設定されていることが前提となっています。
jps.policystore.hybrid.mode: true
oracle.security.jps.config: ファイルjps-config-jse.xmlの場所
String contextName="TestJSE"; ...
public static PolicyStore getPolicyStore(String contextName) {
try-block
JpsContextFactory ctxFact;
ctxFact = JpsContextFactory.getContextFactory();
JpsContext ctx = ctxFact.getContext(contextName);
return ctx.getServiceInstance(PolicyStore.class);
catch-block
...
JavaSEアプリケーションでは、ファイルベースのポリシー・ストアおよび資格証明ストアを使用できます。これらのサービス固有の内容は、アプリケーション・ファイルjps-config-jse.xmlで構成します。
ファイルベースのポリシー・ストアはファイルsystem-jazn-data.xmlで指定し、ファイルベースの資格証明ストアはファイルcwallet.ssoで指定します(このウォレット・ファイルを、同じ名前のブートストラップ・ファイルcwallet.ssoと混同しないようにしてください。このブートストラップ・ファイルには、アプリケーション・セキュリティがLDAPベースの場合にLDAPストアにアクセスするための資格証明が格納されています)。
ウォレットの詳細は、第14.4.3項「ウォレットベースの資格証明ストアの使用」および第8.5.2.5項「modifyBootStrapCredential」を参照してください。
次のコードは、ファイルベースのポリシー・ストアと資格証明ストアおよびそれらを参照するjpsContextの構成を示しています。
<serviceProviders>
<serviceProvider type="CREDENTIAL_STORE" name="credstoressp"
class="oracle.security.jps.internal.credstore.ssp.SspCredentialStoreProvider">
<description>SecretStore-based CSF Provider</description>
</serviceProvider>
<serviceProvider type="POLICY_STORE" name="policystore.xml.provider"
class="oracle.security.jps.internal.policystore.xml.XmlPolicyStoreProvider">
<description>XML-based PolicyStore Provider</description>
</serviceProvider>
</serviceProviders>
<serviceInstances>
<serviceInstance name="credstore" provider="credstoressp" location="./">
<description>File-based Credential Store Service Instance</description>
</serviceInstance>
<serviceInstance name="policystore.xml" provider="policystore.xml.provider" location="./system-jazn-data.xml">
<description>File-based Policy Store Service Instance</description>
</serviceInstance>
</serviceInstances>
<jpsContexts default="TestJSE">
<jpsContext name="TestJSE">
<serviceInstanceRef ref="credstore"/>
<serviceInstanceRef ref="policystore.xml"/>
...
</jpsContext>
...
</jpsContexts>