USER MANUALS

カスタムビューポリシーの開発

カスタムビューポリシーは、アノテーション付きの Java クラスです。このアノテーションは、このクラスをカスタムビューポリシーとしてマークするとともに、このクエリの実行前にクエリをインターセプトするためにサーバーが実行する必要があるメソッドを示すものです。

カスタムポリシーが実行されるたびに、サーバーはそのクラスの新しいインスタンスを作成します。しかし、この Java クラスの属性が「静的」であると、ポリシーを何度実行しても属性の値は変わりません。

カスタムビューポリシーを開発するには、プロジェクトのクラスパスに <DENODO_HOME>/lib/contrib/denodo-commons-custom.jar を追加します。

Virtual DataPort API の Javadoc は、この API のクラスとアノテーションについてのドキュメントを提供します。

<DENODO_HOME>/samples/vdp/customPolicies/ ディレクトリには、サンプルのカスタムビューポリシーがあります。

このカスタムビューポリシーは、ユーザーまたはロールが同じビューやストアドプロシージャに対して同時に実行できるクエリの数を制限します。このカスタムビューポリシーには「Limit」という入力パラメータが 1 つあります。このパラメータにより、そのユーザーまたはロールが同時に実行できるクエリの最大数を設定します。

このディレクトリの README ファイルでは、このサンプルをコンパイルして Virtual DataPort にインポートする方法について説明しています。

カスタムビューポリシーを作成して Virtual DataPort にインポートした後は、Denodo ナレッジベースの記事「 How to debug Denodo custom extensions with Eclipse 」を読んでデバッグ方法について確認してください。


カスタムビューポリシーを開発するには、次のような Java クラスを作成します。

import com.denodo.common.custom.annotations.*;
import com.denodo.common.custom.policy.*;

@CustomElement(name = "my_new_custom_policy", type = CustomElementType.VDPCUSTOMPOLICY)
public class MyDenodoCustomPolicy {

    @CustomContext
    CustomRestrictionPolicyContext context;

    @CustomExecutor
    public CustomRestrictionPolicyValue execute(
        @CustomParam(name = "parameter1", mandatory = false) String inputParameter {

       /*
        * This custom view policy accepts all the queries that involve
        * the view over which this policy was assigned.
        */
        return new CustomRestrictionPolicyValue(CustomRestrictionPolicyType.ACCEPT);
   }
}

@CustomElementname 属性は、このカスタムビューポリシーの名前です。

context 属性により、クエリのコンテキストについて以下の情報を取得できます。

  • Virtual DataPort が受け取ったクエリ: getQuery()

  • クエリに含まれるフィールド。つまり、 SELECTWHEREGROUP BY 、および HAVING の句に含まれるフィールドのリスト: getFieldsInQuery()

  • クエリを実行するユーザーアカウント: getCurrentUserName()

  • クエリを実行するユーザーアカウントの有効なロールのリスト: getCurrentUserRoles() 。つまり、そのユーザーに直接付与されているロールと、ユーザー自身のロールではなく、ユーザーのロールに付与されているロール。

  • クエリを実行するコネクションのユーザーエージェント: getCurrentUserAgent()

  • クエリが実行されるデータベース: getCurrentDatabaseName() 。これはビューが属するデータベースと異なる場合があります。たとえば、データベース「db1」に接続しているときに、 SELECT * FROM db2.customer を実行した場合、このメソッドは「db1」を返します。

  • このカスタムビューポリシーが割り当てられているユーザーまたはロール: getPolicyCredentialsName() および getPolicyCredentialsType() 。後者のメソッドは、そのポリシーがユーザーとロールのどちらに割り当てられているかを返します。

  • このカスタムビューポリシーが割り当てられているビューまたはストアドプロシージャ: getElementType() および getElementName()

  • このカスタムビューポリシーが割り当てられているエレメントのデータベース: getElementDatabase()

  • エレメント getElementTags() にタグが割り当てられたコレクション。

  • getFieldsTags() エレメントからフィールドにタグが割り当てられたマップ。

  • クエリのプロパティ。プロパティの値を取得するには getProperty(...) を呼び出し、値を変更するには setProperty(...) を呼び出します。使用可能なプロパティは、 CustomRestrictionPolicyContext クラスで定義されている定数 (I18N_PROPERTYSWAP_PROPERTY など) です。

  • 追加の認証情報 (認証メカニズム getAdditionalAuthenticationInformation() から提供された場合)。

  • JMX を介してデータを取得するためにこのカスタムビューポリシーで使用できる、Virtual DataPort サーバーへの JMX コネクション: getJmxConnection() 。Denodo の JMX インターフェイスは、サーバーの現在のステータスに関する情報を提供します。この情報を使用して、Denodo サーバーの負荷や同時クエリ数などに基づいてポリシーの動作を変更できます。

  • メッセージをログに記録するには、 log(...) メソッドを呼び出します。このメソッドを使用して記録されたメッセージは、ログカテゴリ com.denodo.vdb.catalog.view.CustomRestrictionPolicyContextImpl にリダイレクトされます。

  • ログカテゴリが有効になっているかどうかの確認: isLogLevelEnabled(...)

  • オプションの完全なリストについては、 CustomRestrictionPolicyContext クラスの Javadoc を参照してください。

注釈

カスタムビューポリシーのメカニズムでは、 execute メソッドの呼び出しの直前に context 属性が初期化されます。クラスのコンストラクターからこの属性にアクセスしようとすると、この属性は null になります。

カスタムビューポリシーにパラメータを追加するには、 execute メソッドにパラメータを追加して、 @CustomParam(name = "<parameter_name>", mandatory = false) というアノテーションを付けます。このアノテーションには以下の 2 つのパラメータがあります。

  • name: この値は、Administration Tool でこのカスタムビューポリシーに関する情報をユーザーに表示するときに使用されます。

  • mandatory: このパラメータが必須かどうかを示すブール値。

後でこのポリシーをビュー上でユーザーまたはロールに割り当てる場合は、ポリシーの入力パラメータの値を指定する必要があります。

この Java クラスには、 @CustomExecutor のアノテーションが付いたメソッドが 1 つだけ 必要です (この例では、 execute メソッド)。実行エンジンは、クエリの実行時にカスタムビューポリシーを読み込むと、このアノテーションによってマークされたメソッドを実行します。このメソッドは CustomRestrictionPolicyValue オブジェクトを返す必要があります。

  • クエリを「そのまま」承認するには、以下を返します。

    return new CustomRestrictionPolicyValue(CustomRestrictionPolicyType.ACCEPT);
    
  • クエリを拒否するには、以下を返します。

    return new CustomRestrictionPolicyValue(CustomRestrictionPolicyType.REJECT);
    
  • クエリに条件を追加するには、以下を返します。

    String condition = "title <> 'Chief Executive Officer'";
    return new CustomRestrictionPolicyValue(
                   CustomRestrictionPolicyType.ACCEPT_WITH_FILTER
                   , CustomRestrictionPolicyFilterType.REJECT_ROW
                   , condition
                   , null);
    

    この例では、実行エンジンは、ユーザーが実行するクエリに、条件「title <> 'Chief Executive Officer'」を追加します。

  • フィールドのリストに含まれる 1 つ以上のフィールドがクエリに含まれている場合にクエリに条件を追加するには、以下を返します。フィールドが SELECTWHEREGROUP BYHAVING の句の少なくとも 1 つで使用されている場合、そのフィールドはクエリで使用されているとみなされます。

    String condition = "title <> 'Chief Executive Officer'";
    Set<String> sensitiveFields = new HashSet<>(Arrays.asList("salary", "bonus"));
    return new CustomRestrictionPolicyValue(CustomRestrictionPolicyType.ACCEPT_WITH_FILTER,
                   CustomRestrictionPolicyFilterType.REJECT_ROW_IF_ANY_SENSITIVE_FIELDS_USED
                   , condition
                   , sensitiveFields);
    

    この例では、「salary」フィールドと「bonus」フィールドの 両方またはどちらか がクエリで使用されている場合、条件「title <> 'Chief Executive Officer'」がクエリに追加されます。これらのフィールドのどちらもクエリで使用されていない場合、この条件はクエリに追加 されません

  • フィールドのリストに含まれるすべてのフィールドがクエリに含まれている場合にクエリに条件を追加するには、以下を返します。フィールドが SELECTWHEREGROUP BYHAVING の句の少なくとも 1 つで使用されている場合、そのフィールドはクエリで使用されているとみなされます。

    String condition = "title <> 'Chief Executive Officer'";
    Set<String> sensitiveFields = new HashSet<>(Arrays.asList("salary", "bonus"));
    return new CustomRestrictionPolicyValue(CustomRestrictionPolicyType.ACCEPT_WITH_FILTER,
                    CustomRestrictionPolicyFilterType.REJECT_ROW_IF_ALL_SENSITIVE_FIELDS_USED, condition,
                    sensitiveFields);
    

    この例では、「salary」フィールドと「bonus」フィールドの両方がクエリで使用されている場合、条件「title <> 'Chief Executive Officer'」がクエリに追加されます。これらのフィールドが両方とも使用されているのでなければ、この条件はクエリに追加 されません

    この例では、定数 REJECT_ROW_IF_ALL_SENSITIVE_FIELDS_USED を使用し、前の例では定数 REJECT_ROW_IF_ANY_SENSITIVE_FIELDS_USED を使用している点に注意してください。

  • フィールドのリストに含まれる 1 つ以上のフィールドがクエリで使用されている場合に、特定の条件を満たして いない 行で、リストに含まれるフィールドの値をマスクするには、以下を返します。

    String condition = "title <> 'Chief Executive Officer'";
    Set<String> sensitiveFields = new HashSet<>(Arrays.asList("salary", "bonus"));
    return new CustomRestrictionPolicyValue(CustomRestrictionPolicyType.ACCEPT_WITH_FILTER,
                    CustomRestrictionPolicyFilterType.MASK_SENSITIVE_FIELDS_IF_ANY_USED, condition,
                    sensitiveFields);
    

    フィールドをマスクするには、その値を null に設定します。

    この例では、「salary」フィールドと「bonus」フィールドの 両方またはどちらか がクエリで使用されている場合、条件を満たして いない 行で、「sensitiveFields」リストに含まれるフィールド (「salary」と「bonus」) が NULL に設定されます。この例では、「title」フィールドの値が「Chief Executive Officer」になっている (つまり、条件を満たしていない) 行で、「salary」フィールドと「bonus」フィールドの値が NULL に設定されます。

    これらのフィールドのいずれもクエリで使用されていなければ、どのフィールドもマスクされません。

  • フィールドのリストに含まれるすべてのフィールドがクエリで使用されている場合に、条件を満たして いない 行で、リストに含まれるフィールドの値をマスクするには、以下を返します。

    String condition = "title <> 'Chief Executive Officer'";
    Set<String> sensitiveFields = new HashSet<>(Arrays.asList("salary", "bonus"));
    return new CustomRestrictionPolicyValue(CustomRestrictionPolicyType.ACCEPT_WITH_FILTER,
                    CustomRestrictionPolicyFilterType.MASK_SENSITIVE_FIELDS_IF_ALL_USED, condition,
                    sensitiveFields);
    

    フィールドをマスクするには、その値を null に設定します。

    この例では、「salary」フィールドと「bonus」フィールドの 両方 がクエリで使用されている場合、条件を満たして いない 行で、「sensitiveFields」リストに含まれるフィールド (「salary」と「bonus」) が NULL に設定されます。この例では、「title」フィールドの値が「Chief Executive Officer」になっている (つまり、条件を満たしていない) 行で、「salary」フィールドと「bonus」フィールドの値が NULL に設定されます。

    これらのフィールドのすべてがクエリで使用されているのでなければ、条件はクエリに追加 されず 、どのフィールドもマスクされません。

  • クエリの結果のすべての行で一部のフィールドの値をマスクする (つまり、 MASK_SENSITIVE_FIELDS_IF_ALL_USED または MASK_SENSITIVE_FIELDS_IF_ANY_USED オプションを指定する) には、常に false に評価される条件 (1 is null など) を使用します。

    String condition = "1 is null";
    Set<String> sensitiveFields = new HashSet<>(Arrays.asList("salary", "bonus"));
    return new CustomRestrictionPolicyValue(CustomRestrictionPolicyType.ACCEPT_WITH_FILTER,
                    CustomRestrictionPolicyFilterType.MASK_SENSITIVE_FIELDS_IF_ANY_USED, condition,
                    sensitiveFields);
    

    この例では、「salary」フィールドと「bonus」フィールドの 両方またはどちらか がクエリで使用されている場合、すべての行で「salary」フィールドと「bonus」フィールドの値が NULL に設定されます。

  • 前の例の値を別のマスキングでマスクするには、デフォルトのマスキング式とフィールドごとのマスキング構成があるマップを受け取るコンストラクターを使用します。たとえば、マスク「salary」にはデフォルトの動作が指定されていて、「bonus」には値 0 が指定されているとします。

    String condition = "1 is null";
    Map<String, CustomMaskingExpression> sensitiveFields = new LinkedHashMap<>();
    sensitiveFields.put("salary", CustomMaskingExpression.DEFAULT);
    sensitiveFields.put("bonus", CustomMaskingExpression.SET_0);
    return new CustomRestrictionPolicyValue(CustomRestrictionPolicyType.ACCEPT_WITH_FILTER,
                    CustomRestrictionPolicyFilterType.MASK_SENSITIVE_FIELDS_IF_ANY_USED, condition,
                    CustomMaskingExpression.REDACT, sensitiveFields);
    

    この例では、「salary」フィールドと「bonus」フィールドの 両方またはどちらか がクエリで使用されている場合、すべての行で、「salary」フィールドには列タイプに応じた REDACT 式の結果が設定され、「bonus」フィールドは 0 に設定されます。

  • オフセット/フェッチ句がある場合でも、ビューから取得する行数を強制的に制限するには、目的の QUERY_LIMIT を設定し、ブール FORCE_STRICT_QUERY_LIMIT を true に設定します。

    this.context.setProperty("QUERY_LIMIT","50");
    this.context.setProperty("FORCE_STRICT_QUERY_LIMIT", String.valueOf(true));
    

    この例では、 QUERY_LIMIT を 50 に設定し、 FORCE_STRICT_QUERY_LIMIT を true に設定しています。つまり、クエリは最初の 50 個の値を超えたら、それ以上の値を返しません。たとえば、オフセット 10 でクエリを作成し、60 をフェッチした場合、結果に表示されるのは 40 行だけです。


カスタムビューポリシーの入力パラメータのいずれかが日時値の場合は、カスタム関数での「 日時型および時間間隔型の処理 」を参照してください。カスタムビューポリシーの入力パラメータの管理規則は、カスタム関数の場合と同じです。

Add feedback