Oracle® Fusion Middleware Oracle Entitlements Server開発者ガイド 11g リリース2 (11.1.2.1) B71698-03 |
|
前 |
次 |
Oracle Entitlements Serverランタイム環境に拡張クラスをロードすることで、基本機能を拡張できます。拡張機能はJavaアーカイブ(JAR)ファイルとしてバンドルされています。この章では、作成可能な拡張機能に関する次の項について説明します。
ポリシー情報ポイント(PIP)は、属性値のソースとして機能するシステムエンティティです。ポリシーの実行時評価の間に、Oracle Entitlements Serverは、属性リトリーバ・プラグインを利用して1つ以上のPIP情報ストアから属性値を取得します。これらの属性リトリーバにより、属性の値がアクセスの決定に影響するデータ・ドリブン方式でポリシーを使用できます。たとえば、銀行口座からの送金へのアクセスが現在口座にある金額に基づく場合、属性リトリーバ・コンポーネントを使用して現在の残高を取得できます。このインフラストラクチャは高い拡張性があり、ユーザーは独自のPIPプラグインを開発して、ファイル、USBドライバ、インターネットなど、多くの場所から情報を取得できます。
注意: PIPの詳細な説明は、『Oracle Fusion Middleware Oracle Entitlements Server管理者ガイド』を参照してください。 |
詳細は、次の各項を参照してください。
Oracle Entitlements Serverは事前定義済属性リトリーバを使用して、Lightweight Directory Access Protocol (LDAP)データ・ストアおよびリレーショナル・データベース管理システム(RDBMS)に接続します。別のタイプのPIPデータ・ストアから属性値を取得するためにカスタム属性リトリーバを開発することができます。カスタム属性リトリーバは、1つまたは多数の属性に値を返せます。
属性リトリーバの構成情報は、jps-config.xml
構成ファイルで定義されます。このファイル内の属性リトリーバの構成は、事前定義済とカスタムによって異なります。
事前定義済属性リトリーバの場合:
データ・ストアへの接続に必要な情報と資格証明情報を構成します。
属性名、使用する属性リトリーバの名前、値を取得する検索問合せ(たとえば、PIPがリレーショナル・データベースの場合はSQL問合せ、ディレクトリの場合はLDAP問合せ)、および属性値のキャッシング情報など、属性値を個別に構成します。
事前定義済属性リトリーバの詳細は、『Oracle Fusion Middleware Oracle Entitlements Server管理者ガイド』を参照してください。
カスタム属性リトリーバの場合は、属性リトリーバを実装するクラスの名前に関する情報を構成します。
属性リトリーバは、単一の値または複数の値の属性を返すことができます。
注意:
|
1.3.3項「条件の追加」の説明のとおり、ポリシーの条件は属性または関数を使用して作成します。条件に動的な属性値を使用する場合、属性をcom.bea.security.AppContext
インタフェースで渡したり、事前定義済またはカスタム属性リトリーバで取得することができます。次の手順では、カスタム属性リトリーバの作成手順を説明します。
com.bea.security.providers.authorization.asi.AttributeRetrieverV2
インタフェースを使用してカスタム属性リトリーバを実装します。
詳細は、7.1.3項「カスタム属性リトリーバの実装」を参照してください。
JARファイルを作成します。
次のJARファイルを該当するクラスパスに追加します。
Javaセキュリティ・モジュールへ接続する場合は、JARファイルをアプリケーションのクラスパスに追加します。
RMI、WebサービスまたはWebLogic Serverセキュリティ・モジュールに接続する場合、他のセキュリティ・モジュールのJARファイルがあるシステムのクラスパスにJARファイルを追加します。
JARが物理的に格納されている場所は問題にはなりません。
カスタム属性リトリーバを使用するようにセキュリティ・モジュールを構成します。
構成では、カスタム属性リトリーバの完全修飾の場所を指定してください。詳細は、『Oracle Fusion Middleware Oracle Entitlements Server管理者ガイド』を参照してください。
カスタム属性リトリーバにはAttributeRetrieverV2
インタフェースを実装する必要があります。表7-1はこの目的で使用可能なメソッドを説明しています。
表7-1 AttributeRetrieverV2インタフェースのメソッド
メソッド | 説明 |
---|---|
|
特定の属性の値が要求されるたびに、このメソッドをコールします。指定された属性の値が返され、次のパラメータが取得されます。
|
|
このメソッドは、多くの場合、属性リトリーバのロード時に1回コールします。このメソッドは、属性リトリーバが値を戻すことができる属性名のリストを返します。 |
最も単純な使用方法の場合、属性リトリーバは値の取得に追加情報を必要としません。たとえば、日中の時刻を取得する場合、getAttributeValue()
はシステム関数をコールし、情報を返します。他の使用例では、属性リトリーバが属性値を返す前に、追加の情報を必要とする場合があります。たとえば、属性リトリーバはユーザーの場所を取得するためにユーザーの識別子を必要とします。このため、属性リトリーバには、他の属性の値を取得するためにRequestHandle
インタフェースが提供されています。この例で、属性リトリーバはRequestHandle
インタフェースを使用して組込みのSYS_USER
属性の値を取得します。この値は現在のユーザーのアイデンティティに解決されます。
注意: システム属性の名前は、 |
次の各項では、属性取得オプションの詳細を説明します。
AttributeRetrieverV2
の実装では、getAttributeValue()
メソッドを使用して名前付き属性の値を返すことができます。このメソッドは、入力に属性の名前を取り、その属性の値を返します。例7-1では、getAttributeValue()
の使用方法を示します。
例7-1 getAttributeValue()メソッドの実装
package oracle.security.oes.test; import java.util.Map; import javax.security.auth.Subject; import weblogic.security.service.ContextHandler; import weblogic.security.spi.Resource; import com.bea.security.providers.authorization.asi.AttributeRetrieverV2; import com.bea.security.providers.authorization.asi.ARME.evaluator.RequestHandle; public class SimpleAttributeRetriever implements AttributeRetrieverV2 { public Object getAttributeValue(String name, RequestHandle requestHandle, Subject subject, Map roles, Resource resource, ContextHandler contextHandler) { if (name == null) return null; return "static_value"; } public String[] getHandledAttributeNames() { return new String[] {"static_attr"}; } }
MyAttributeRetrieverV2
は、AttributeRetrieverV2
の実装です。getHandledAttributeNames()
メソッドは、この実装で処理される属性の名前を返します。少なくとも1つの属性を返します。空の値やNULL値は、リトリーバが任意の属性でコールされることを意味します。getAttributeValue()
パラメータの値は次のように定義されています。
nameは取得する属性の名前です。
requestHandleは、(必要時に)他の属性の値を取得可能なインタフェースの実装です。また、異なる属性リトリーバ間やカスタム関数間でのコンテキスト(任意のオブジェクト)の共有を可能にします。使用されていない場合も関数に渡されます。
subjectは、リクエストに関連付けられたプリンシパルを定義します。
rolesは、関連付けられたプリンシパルのロール・メンバーシップを定義します。オブジェクトは、キーがロール名で、値がロール・オブジェクトのマップです。
resourceは、リクエストに関連付けられた保護されたリソースです。
contextHandlerは、リクエストに関連付けられたコンテキストを定義します。コンテキストが存在しない場合は、NULLになる場合があります。
状況によっては、属性リトリーバが必要な属性値を取得する前に、参考情報として属性の取得が必要になる場合があります。たとえば、属性リトリーバがユーザーの場所を取得するために、ユーザーの属性を必要とする場合があります。RequestHandle
インタフェースのgetAttribute()
メソッドを呼び出すことにより、属性リトリーバは識別子を取得でき、ユーザーのすべての情報にアクセスできます。getAttribute()
メソッドは、AttributeElement
オブジェクトの名前と値のペアとして属性名と値を返します。
RequestHandle
は、必要時に他の属性の値を取得可能なインタフェースです。また、属性リトリーバやカスタム関数の異なる呼び出し間でコンテキスト(任意のオブジェクト)の共有を可能にします。
注意:
|
例7-2では、getAttribute()
の使用方法を示します。
例7-2 getAttribute()メソッドの使用方法
public Object getAttributeValue (String name, RequestHandle requestHandle, Subject subject, Map roles, Resource resource, ContextHandler contextHandler) { ... ... // retrieve sys_user built-in attribute String user = null; try { AttributeElement element = requestHandle.getAttribute("sys_user", true); if (element != null) { user = (String)element.getValueAs(String.class); } } catch (Exception e) { // ignore it } ... ... }
getAttribute()
パラメータの値は次のように定義されています。
sys_userは取得する属性の名前です。
trueは、属性タイプのチェック機能を有効にします。タイプのチェックを無効にするために、この値をfalseにできます。
この項では、カスタム属性リトリーバを認識するためにOracle Entitlements Serverを構成する手順を説明します。com.bea.security.providers.authorization.asi.AttributeRetrieverV2
の実装後(7.1.3項「カスタム属性リトリーバの実装」で説明)、Javaコードをコンパイルし、コンパイルしたクラスをセキュリティ・モジュール・インスタンスのクラスパスに追加し、jps-config.xml
構成ファイルに次の変更を加えます。
例7-3に示すようにPIPサービス・プロバイダを<serviceProviders>
セクションに宣言します。
例7-4に示すようにPIPサービス・インスタンスを<serviceInstances>
セクションに宣言します。
例7-4 jps-config.xmlのserviceProvidersセクション
<serviceInstances> <serviceInstance name="pip.service.MyAttributeRetriever" provider="pip.service.provider"> <property name="type" value="CUSTOM_PIP"/> <property name="application" value="testPIPBasedOnCustomPIP"/> <property name="description" value="MyAttributeRetriever"/> <property name="classnames" value="pips.MyDummyAttributeRetriever"/> </serviceInstance> </serviceInstances>
次の表の定義に従ってプロパティを指定します。
名前 | 値 |
---|---|
Type |
値はCUSTOM_PIPにする必要があります。 |
Application |
PIPインスタンスが適用されるアプリケーションです。 |
Classnames |
カスタムPIPの完全修飾クラス名です。 |
例7-5に示すようにPIPサービス・インスタンスを<jpsContext>
セクションに宣言します。
関数は、ポリシーの条件で高度な処理を実行するために使用できます。関数は、いくつかのパラメータを取り、サポートされている任意のデータ型を戻すことができます。Oracle Entitlements Serverでは、いくつかの事前定義済関数が提供されており、さらに独自の関数を宣言できます。
カスタム関数は、クラス内にメソッドとして実装でき、メソッドには1つまたは複数のカスタム関数を含めることができます。メソッド名には、ポリシー内で参照している対応する名前と一致していれば、任意の名前を選択できます。カスタム関数は、定数や他の属性(動的属性を含む)または他の関数名で構成された引数を渡すことができます。すべての評価関数が共通のネームスペースを共有するため、2つの関数が同じ名前を持つことはできません。詳細は、次の各項を参照してください。
次の手順は、ポリシー内にカスタム関数を実装するときに行う詳細手順を示しています。
例7-6は、カスタム関数の作成方法を示しています。
例7-6 カスタム関数のサンプル・コード
package com.bea.security.examples; import java.util.Map; import java.util.Properties; import javax.security.auth.Subject; import weblogic.security.service.ContextHandler; import weblogic.security.spi.Resource; import com.bea.security.providers.authorization.asi.ARME.evaluator.RequestHandle; import com.wles.util.AttributeElement; public class MyEvaluationFunction { /**named evaluation function. Additional authorization request data is made available to allow for more complex attribute evaluation. This method will be registered to ARME, and be invoked while the policy contains a custom evaluation function with name "string_longer_then". @param requestHandle the attributes container associated with the request, through which the function can get required attribute value. @param args an array of function arguments. Each element is either <code>null</code>, or a String @param subject the subject associated with the request @param roles the role membership of the subject key: role name. value: role object <code>null</code> if function is called during role mapping @param resource the resource associated with the request @param contextHandler the context associated with the request, may be <code>null</code> if non-existant @return <code>true</code> or <code>false</code> as the result of the function @throws MissingAttributeException for can not get required attribute value. */ public boolean string_longer_then(RequestHandle requestHandle, Object[] args, Subject subject, Map roles, Resource resource, ContextHandler contextHandler) { // Check if we got a correct number of the input paramters if(args.length < 2 || args.length > 3 || args[0] == null || args[1] == null) { // Incorrect number of arguments. // Such policy is invalid and can not be evaluated throw new RuntimeException ("Incorrect number of arguments in a function"); } // Arguments for an evalaution function are attribute names. // Unfortunately, if a string literal or a numeric value is used // it is passed in as value. The only way to distinguish // values from names is to try to look up the attribute. // Evaluation function should not set any values. // Get the integer value of the first argument. // This example does not do any type error checking // - but your code should. int intCompLength = 0; try { AttributeElement strLength = requestHandle.getAttribute((String)args[0], true); if(strLength != null) { if(strLength.isList()) { // string_longer_then: first argument not a single value return false; } intCompLength = Integer.parseInt((String)strLength.getValueAs(String.class)); } else { // numerical constant will be passed in as is. try { intCompLength = Integer.parseInt((String)args[0]); } catch(NumberFormatException ne) { //value format is error, and no attribute in requestHandle. throw new RuntimeException("miss attribute: " + args[0]); } } } catch(Exception e) { //caught exception while get attribute throw new RuntimeException( "failed while get attribute: " + (String)args[0] + ". Exception: " + e.getMessage()); } // Get the string value String input = null; try { AttributeElement strContent = requestHandle.getAttribute((String)args[1], true); if(strContent != null) { if(strContent.isList()) { // string_longer_then: second argument is not a single value return false; } input = (String)strContent.getValueAs(String.class); } else { input = (String)args[1]; } } catch(Exception e) { //caught exception while get attribute throw new RuntimeException( "failed while get attribute: " + (String)args[0] + ". Exception: " + e.getMessage()); } // return false, if the conditin is not satisfied if(input.length() <= intCompLength) { return false; } // Condition was satisfied. Create and attach the return attribute /* The method appendReturnData(String name, Object data) on RequestHandle object does a copy of data. Return value will only be appended if the rule that called this function actually fired. (other elements in the condition may prevent that) */ requestHandle.appendReturnData("cropped_string", input); return true; } }
例7-7は、DataType引数を返すカスタム関数の作成方法を示しています。
例7-7 DataType引数を返すカスタム関数のサンプル・コード
import oracle.security.jps.service.policystore.info.DataType; import oracle.security.jps.service.policystore.info.OpssString; /** Another example of evaluation function. Additional authorization request data is made available to allow for more complex attribute evaluation. This method will be registered to ARME, and be invoked while the policy contains a custom evaluation function with name "string_longer_then". @param requestHandle the attributes container associated with the request, through which the function can get required attribute value. @param args an array of function arguments. Each element is either <code>null</code>, or a String @param subject the subject associated with the request @param roles the role membership of the subject key: role name. value: role object <code>null</code> if function is called during role mapping @param resource the resource associated with the request @param contextHandler the context associated with the request, may be <code>null</code> if non-existant @return <code>DataType</code> as the result of the function where DataType is any of the out-of-the-box supported data typs such as OpssDate/ OpssTime/ OpssString etc. @throws MissingAttributeException for can not get required attribute value. */ public DataType string_to_upper_case(RequestHandle requestHandle, Object[] args, Subject subject, Map roles, Resource resource, ContextHandler contextHandler) throws MissingAttributeException { // Check if we got a correct number of the input paramters if((args.length != 1) || (args[0] == null)) { // Incorrect number of arguments. // Such policy is invalid and can not be evaluated throw new RuntimeException ("Incorrect number of arguments in a function"); } // Arguments for an evalaution function are attribute names. // Unfortunately, if a string literal or a numeric value is used // it is passed in as value. The only way to distinguish // values from names is to try to look up the attribute. // Evaluation function should not set any values. // Get the integer value of the first argument. // This example does not do any type error checking // - but your code should. int intCompLength = 0; try { AttributeElement str = requestHandle.getAttribute((String)args[0], true); String input = null; if(str != null) { if(str.isList()) { // string_to_upper_case: first argument not a single value return false; } input = (String)str.getValueAs(String.class); } else { // string constant will be passed in as is. input = (String)args[0]; } } catch(Exception e) { //caught exception while get attribute throw new RuntimeException( "failed while get attribute: " + (String)args[0] + ". Exception: " + e.getMessage()); } String output = input.toUpperCase(); return new OpssString(output); }
詳細は、2.4.3.2項「カスタム関数の定義の作成」および2.4.5項「条件の定義」を参照してください。
引数メタデータのインタフェースは、カスタムOracle Entitlements Server関数が予期する引数についての情報を問い合せるために使用します。(これには、引数の数と、それらの名前および型などがあります。)オプションで、これらの引数問合せに対してInspectableFunction
インタフェースを実装できます。このインタフェースを基にカスタム関数を追加すると、管理コンソールはgetArgMetadata
メソッドをコールして、引数を表すメタデータを返し、カスタム関数が予期するメタデータを検証します。
関数で予期される最初の引数(引数0)ごとに、getArgMetadata
は引数を表すメタデータを返す必要があります。管理コンソールで予期される引数ごとのメタデータが収集されると、カスタムOracle Entitlements Server関数を使用するプロセスを自動化するために、インタフェース・メソッドのgetArgValue
およびisValidArgValue
が使用されます。
例7-8に、getArgMetadata(String functionName)
メソッドのサンプル・コードを示します。
例7-9に、getArgValues (String functionName, int argNumber, ArrayList<oracle.security.jps.service.policystore.info.DataType> prevArgValues)
メソッドのサンプル・コードを示します。
例7-10に、isValidArgValue (String functionName, int argNumber, oracle.security.jps.service.policystore.info.DataType argValue, ArrayList<oracle.security.jps.service.policystore.info.DataType> prevArgValues)
メソッドのサンプル・コードを示します。
例7-8 getArgMetadata()メソッドのサンプル・コード
public ArrayList<ArgMetadata> getArgMetadata (String functionName) { if (functionName.compareToIgnoreCase(Constants.GET_STRING_IDC_FUNC_NAME) == 0 || functionName.compareToIgnoreCase(Constants.GET_INTEGER_IDC_FUNC_NAME) == 0 || functionName.compareToIgnoreCase(Constants.GET_BOOLEAN_IDC_FUNC_NAME) == 0) { ArrayList<ArgMetadata> metadata = new ArrayList<ArgMetadata>(); metadata.add (new ArgMetadata (Constants.GET_IDC_FUNC_ARGS.CLAIM_NAME.ordinal(), "Attribute", OpssString.class, true, false, true)); return metadata; } else { throw new RuntimeException ("Invalid function name " + functionName); } }
例7-9 getArgValues()メソッドのサンプル・コード
public ArrayList<oracle.security.jps.service.policystore.info.DataType> getArgValues (String functionName, int argNumber, ArrayList<oracle.security.jps.service.policystore.info.DataType> prevArgValues) throws RuntimeException { ArrayList<oracle.security.jps.service.policystore.info.DataType> values = new ArrayList<oracle.security.jps.service.policystore.info.DataType>(); if (functionName.compareToIgnoreCase(Constants.GET_STRING_IDC_FUNC_NAME) == 0 || functionName.compareToIgnoreCase(Constants.GET_INTEGER_IDC_FUNC_NAME) == 0 || functionName.compareToIgnoreCase(Constants.GET_BOOLEAN_IDC_FUNC_NAME) == 0) { if (argNumber == Constants.GET_IDC_FUNC_ARGS.CLAIM_NAME.ordinal()) { // return claims in the dictionary Iterator<ClaimSchema> it = dictCtx.getDictionary().getClaimsForAllNamespaces(); while (it.hasNext()) { if ((functionName.compareToIgnoreCase(Constants.GET_STRING_IDC_FUNC_NAME) == 0 && it.next().getType() == String.class) || (functionName.compareToIgnoreCase(Constants.GET_INTEGER_IDC_FUNC_NAME) == 0 && it.next().getType() == Integer.class) || (functionName.compareToIgnoreCase(Constants.GET_BOOLEAN_IDC_FUNC_NAME) == 0 && it.next().getType() == Boolean.class)) { nameList.add (it.next().getUniqueName()); } } Collections.sort(nameList); for (String name : nameList) values.add (new OpssString (name)); } else { throw new RuntimeException ("Invalid argument number " + argNumber); } } else { throw new RuntimeException ("Invalid function name " + functionName); } return values; }
例7-10 isValidArgValue()メソッドのサンプル・コード
public boolean isValidArgValue (String functionName, int argNumber, oracle.security.jps.service.policystore.info.DataType argValue, ArrayList<oracle.security.jps.service.policystore.info.DataType> prevArgValues) throws RuntimeException { if (functionName.compareToIgnoreCase(Constants.GET_STRING_IDC_FUNC_NAME) == 0 || functionName.compareToIgnoreCase(Constants.GET_INTEGER_IDC_FUNC_NAME) == 0 || functionName.compareToIgnoreCase(Constants.GET_BOOLEAN_IDC_FUNC_NAME) == 0) { if (argNumber == Constants.GET_IDC_FUNC_ARGS.CLAIM_NAME.ordinal()) { // is it a valid claim? try { ClaimSchema schema = dictCtx.getDictionary().getClaimSchema(argValue.toString()); return ((functionName.compareToIgnoreCase(Constants.GET_STRING_IDC_FUNC_NAME) == 0 && schema.getType() == String.class) || (functionName.compareToIgnoreCase(Constants.GET_INTEGER_IDC_FUNC_NAME) == 0 && schema.getType() == Integer.class) || (functionName.compareToIgnoreCase(Constants.GET_BOOLEAN_IDC_FUNC_NAME) == 0 && schema.getType() == Boolean.class)); } catch (UnknownClaimException e) { return false; } } else { throw new RuntimeException ("Invalid argument number " + argNumber); } } else { throw new RuntimeException ("Invalid function name " + functionName); } }