この章の内容は、次のとおりです。
この項の内容は、次のとおりです。
Oracle Virtual Private Database(VPD)を使用すると、行および列レベルでデータベース・アクセスを制御するセキュリティ・ポリシーを作成できます。基本的には、Oracle Virtual Private Databaseのセキュリティ・ポリシーが適用された表、ビューまたはシノニムに対して発行されるSQL文に、動的なWHERE
句が追加されます。
Oracle Virtual Private Databaseを使用すると、データベース表、ビューまたはシノニムに対するセキュリティを直接詳細なレベルまで規定できます。これらのデータベース・オブジェクトにセキュリティ・ポリシーを直接付加すると、ユーザーがデータにアクセスするたびにポリシーが自動的に適用されるため、セキュリティを回避できません。
ユーザーがOracle Virtual Private Databaseポリシーで保護されている表、ビューまたはシノニムに直接的または間接的にアクセスすると、Oracle DatabaseはユーザーのSQL文を動的に変更します。この変更は、セキュリティ・ポリシーを実装する関数によって戻されたWHERE
条件(述語)に基づいて行われます。Oracle Databaseでは、関数内に記述された条件、または関数が戻す条件を使用して、動的かつユーザーに対して透過的にSQL文が変更されます。Oracle Virtual Private Databaseポリシーは、SELECT
、INSERT
、UPDATE
、INDEX
およびDELETE
文に適用できます。
たとえば、ユーザーが次の問合せを実行するとします。
SELECT * FROM OE.ORDERS;
Oracle Virtual Private Databaseポリシーにより、WHERE
句の文が動的に追加されます。次に例を示します。
SELECT * FROM OE.ORDERS WHERE SALES_REP_ID = 159;
この例では、ユーザーは営業担当者159の受注のみを表示できます。
このユーザーのセッション情報(ユーザーのIDなど)に基づいてユーザーをフィルタ処理する場合は、WHERE
句を作成してアプリケーション・コンテキストを使用できます。次に例を示します。
SELECT * FROM OE.ORDERS WHERE SALES_REP_ID = SYS_CONTEXT('userenv','session_user');
注意: Oracle Virtual Private Databaseでは、DDL( TRUNCATE 文やALTER TABLE 文)のフィルタ処理はサポートされていません。 |
Oracle Virtual Private Databaseポリシーを使用するメリットは、次のとおりです。
すべてのアプリケーションでアクセス制御を実装するのではなく、Oracle Virtual Private Databaseセキュリティ・ポリシーをデータベース表、ビューまたはシノニムに付加すると、次のようなメリットがあります。
セキュリティ。データベース表、ビューまたはシノニムにポリシーを対応付けることで、アプリケーション・セキュリティの重大な問題を解決できます。たとえば、アプリケーションの使用を許可されているユーザーが、そのアプリケーションに対応付けられている権限を利用し、SQL*Plusなどの非定型の問合せツールを使用してデータベースを誤って変更してしまう可能性があります。ファイングレイン・アクセス・コントロールでは、セキュリティ・ポリシーを表、ビューまたはシノニムに直接付加することによって、ユーザーがどのような方法でデータにアクセスしても、同じセキュリティが施行されます。
簡潔性。セキュリティ・ポリシーは、表ベース、ビュー・ベースまたはシノニム・ベースのアプリケーションごとに繰り返し追加するのではなく、表、ビューまたはシノニムに1回のみ追加します。
柔軟性。SELECT
文には1つのセキュリティ・ポリシーを、INSERT
文には別のポリシーを、さらにUPDATE
文およびDELETE
文にはまた別のポリシーを指定できます。たとえば、人事部門の担当者には、その部門内のすべての社員のレコードに対するSELECT
権限を付与し、名字がA
からF
で始まるその部門内の社員の給与のみを更新できるように指定できます。さらに、各表、ビューまたはシノニムに対して複数のポリシーを作成できます。
ポリシー関数を複数回実行すると、パフォーマンスに影響を与える可能性があります。 Oracle DatabaseがOracle Virtual Private Database述語をキャッシュする方法を構成することによって、ポリシー関数のパフォーマンスを制御できます。次のオプションがあります。
各問合せについてポリシーを1回評価します(静的ポリシー)。
ポリシー関数内のアプリケーション・コンテキストが変更された場合のみ、ポリシーを評価します(状況依存ポリシー)。
実行ごとにポリシーを評価します(動的ポリシー)。
これらのポリシー・タイプの構成方法は、「Oracle Virtual Private Databaseポリシー・タイプを使用したパフォーマンスの最適化」を参照してください。
セキュリティを強化するために、Oracle Virtual Private Database ポリシー関数は、定義者権限で宣言されたかのように実行されます。 実行者権限として宣言するとユーザーおよび他のコード保守管理者を混乱させてしまうため、実行者権限では宣言しないでください。
Oracle Virtual Private Databaseポリシーでは、アプリケーション・コンテキストを使用できます。アプリケーション・コンテキストを作成すると、ユーザー情報が安全にキャッシュされます。キャッシュ環境を設定できるのは、指定されたアプリケーション・パッケージのみです。ユーザーまたはパッケージ外部では変更できません。さらに、データがキャッシュされるため、パフォーマンスが向上します。アプリケーション・コンテキストの詳細は、第6章「アプリケーション・コンテキストを使用したユーザー情報の取得」を参照してください。
たとえば、ORDERS_TAB
表へのアクセスを顧客ID番号を基にして行うとします。顧客ID番号が必要になるたびにログインしたユーザーに問い合せるのではなく、アプリケーション・コンテキスト内に顧客ID番号を格納しておくことができます。このようにすると、顧客番号は必要なときにセッションで使用できます。
アプリケーション・コンテキストは、セキュリティ・ポリシーが複数のセキュリティ属性に基づく場合に特に役立ちます。たとえば、WHERE
述語が4つの属性(従業員番号、コスト・センター、職位、支出制限など)に基づくポリシー関数は、この情報を取得するために複数の副問合せを実行する必要があります。このデータがアプリケーション・コンテキストを介して使用可能な場合、パフォーマンスは大きく向上します。
アプリケーション・コンテキストを使用すると、述語により規定される正しいセキュリティ・ポリシーを戻すことができます。たとえば、「顧客は自分の注文のみを参照でき、社員はすべての顧客のすべての注文を参照できる」というルールを規定している受注管理アプリケーションを考えてみます。この場合は、2つの異なるポリシーがあります。position
属性でアプリケーション・コンテキストを定義できます。この属性はポリシー関数内でアクセスでき、その属性の値に基づいて正しい述語を戻します。そのため、職位がclerk
(社員)であるユーザーはすべての注文を取得できるようにし、customer
(顧客)であるユーザーは自分に関連するレコードのみ参照できるようにすることができます。
属性に対して特定の述語を戻すファイングレイン・アクセス・コントロール・ポリシーを設計するには、ポリシーを実装する関数内でアプリケーション・コンテキストにアクセスする必要があります。たとえば、顧客が自分のレコードのみを参照するように制限する必要があるとします。ユーザーは次の問合せを実行します。
SELECT * FROM orders_tab
ファイングレイン・アクセス・コントロールによって、この問合せはWHERE
述語が含まれるように動的に変更されます。
SELECT * FROM orders_tab WHERE custno = SYS_CONTEXT ('order_entry', 'cust_num');
前述の例で、50,000人の顧客が存在し、各顧客が受け取る述語を同じにするとします。すべての顧客は同一のWHERE
述語を共有し、自分の注文のみを参照できます。顧客間で異なるのは、顧客番号のみです。
アプリケーション・コンテキストを使用すると、50,000人の顧客に適用するポリシー関数内で、1つのWHERE
述語を戻すことができます。その結果、1つの共有カーソルが、顧客ごとに異なる形態で実行されます。これは、実行時に顧客番号が評価されるためです。この値は、顧客ごとに異なります。このようなアプリケーション・コンテキストの使用によって、最適なパフォーマンスに加えて行レベルのセキュリティが得られます。
SYS_CONTEXT
関数がバインド変数のように動作するのは、SYS_CONTEXT
引数が定数の場合のみです。
Oracle Virtual Private Databaseを実装するには、動的なWHERE
句を生成する関数、および保護するオブジェクトにその関数を付加するポリシーを作成する必要があります。
動的なWHERE
句(述語)を生成するには、規定する制限を定義した関数(プロシージャではなく)を作成する必要があります。通常は、セキュリティ管理者が自分のスキーマにこの関数を作成します。別の関数のコールを含めたり、ログイン失敗を追跡するためのチェックを追加するなど、複雑な動作が必要な場合は、これらの関数を1つのパッケージ内に作成します。
関数では、次の動作が必要です。
引数としてスキーマ名、入力としてオブジェクト(表、ビューまたはシノニム)名を取る必要があります。これらの情報を保持するように入力パラメータを定義しますが、関数内でスキーマ名とオブジェクト名自体を指定しないでください。DBMS_RLS
パッケージ(「保護するオブジェクトに関数を付加するポリシーの作成」を参照)を使用して作成したポリシーによって、スキーマ名、およびポリシーが適用されるオブジェクトが提供されます。最初にスキーマのパラメータを作成し、その後にオブジェクトのパラメータを作成する必要があります。
生成するWHERE句述語の戻り値を提供する必要があります。WHERE
句の戻り値は、常にVARCHAR2
データ型です。
有効なWHERE句を生成する必要があります。このコードは「例: 単純なOracle Virtual Private Databaseポリシーの作成」に示すように基本的なもので、WHERE
句はログインするすべてのユーザーに共通です。
ただし、ほとんどの場合、各ユーザー、ユーザーの各グループ、または保護するオブジェクトにアクセスする各アプリケーションに異なるWHERE
句を設計する必要があります。たとえば、マネージャがログインする場合は、そのマネージャの権限に固有のWHERE
句を生成できます。これを行うには、ユーザー・セッション情報にアクセスするアプリケーション・コンテキストをWHERE
句の生成コードに組み込みます。アプリケーション・コンテキストを使用するOracle Virtual Private Databaseポリシーの作成方法は、「例: データベース・セッション・ベースのアプリケーション・コンテキストを使用したポリシーの実装」で説明します。
アプリケーション・コンテキストを使用しないOracle Virtual Private Database関数を作成することもできますが、アプリケーション・コンテキストを使用すると、ユーザーのセッション属性(ユーザーIDなど)に基づいてユーザー・アクセスが安全に行われるため、より強固なOracle Virtual Private Databaseポリシーを作成できます。様々なタイプのアプリケーション・コンテキストの詳細は、第6章「アプリケーション・コンテキストを使用したユーザー情報の取得」を参照してください。
さらに、CまたはJavaコールを埋め込み、オペレーティング・システム情報にアクセスしたり、オペレーティング・システム・ファイルや他のソースからWHERE
句を戻すことができます。
関数を作成した後は、その関数を表、ビューまたはシノニムに対応付けるOracle Virtual Private Databaseポリシーを作成する必要があります。ポリシーは、DBMS_RLS
パッケージを使用して作成します。SYS
以外のユーザーがDBMS_RLS
パッケージを使用するには、EXECUTE
権限が付与されている必要があります。このパッケージには、ポリシーを管理してファイングレイン・アクセス・コントロールを設定できるプロシージャが含まれています。たとえば、ポリシーを表に付加するには、DBMS_RLS.ADD_POLICY
プロシージャを使用します。この設定内でファイングレイン・アクセス・コントロールを設定します。たとえば、ユーザーが表またはビューに対してSELECT
またはUPDATE
文を発行するとポリシーが有効になるように設定します。
Oracle Virtual Private Databaseポリシーの作成とは、関数を作成し、その関数を表またはビューに適用することを意味します。
仮想プライベート・データベース・ポリシーの作成方法の例は、「例: Oracle Virtual Private Databaseポリシーの作成」を参照してください。詳細は、「Oracle Virtual Private Databaseポリシーの構成」を参照してください。
Oracle Virtual Private DatabaseのWHERE
句のアクションを定義する関数を作成した後は、VPDアクションを適用するデータベース表にその関数を対応付ける必要があります。これを行うには、Oracle Virtual Private Databaseポリシーを構成します。ポリシーとは、仮想プライベート・データベース関数を管理するメカニズムです。また、ポリシーを使用すると、ファイングレイン・アクセス・コントロールを追加できるため、たとえば、SQL文のタイプを指定したり、特定の表列にポリシーを適用できます。ユーザーがこのデータベース・オブジェクト内のデータにアクセスすると、ポリシーが自動的に有効になります。
ここでは、ポリシーを表、ビューおよびシノニムに付加する一般的な方法について説明します。Oracle Virtual Private Databaseポリシーを管理するには、DBMS_RLS
パッケージを使用します。詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。
表7-1に、DBMS_RLS
パッケージに含まれているプロシージャを示します。
表7-1 DBMS_RLSのプロシージャ
プロシージャ | 説明 |
---|---|
個別ポリシーの処理用 |
|
表、ビューまたはシノニムにポリシーを追加します。 |
|
表、ビューまたはシノニムに事前に追加したポリシーを使用可能または使用禁止にします。 |
|
静的ポリシー以外のポリシーに対応付けられたカーソルを無効にします。 |
|
表、ビューまたはシノニムからポリシーを削除します。 |
|
グループ・ポリシーの処理用 |
|
ポリシー・グループを作成します。 |
|
ポリシー・グループを削除します。 |
|
特定のポリシー・グループにポリシーを追加します。 |
|
グループ内のポリシーを使用可能にします。 |
|
リフレッシュされたポリシーに対応付けられたSQL文を再解析します。 |
|
グループ内のポリシーを使用禁止にします。 |
|
特定のグループに属するポリシーを削除します。 |
|
アプリケーション・コンテキストの処理用 |
|
アクティブなアプリケーションのコンテキストを追加します。 |
|
アプリケーションのコンテキストを削除します。 |
関連項目:
|
ポリシーを表、ビューまたはシノニムに付加するには、DBMS_RLS.ADD_POLICY
プロシージャを使用します。 ポリシーを追加する表、ビューまたはシノニム、およびポリシーの名前を指定する必要があります。また、ポリシーが制御する文のタイプ(SELECT
、INSERT
、UPDATE
、DELETE
、CREATE INDEX
またはALTER INDEX
)など、その他の情報も指定できます。
例7-1に、DBMS_RLS.ADD_POLICY
を使用して、secure_update
というOracle Virtual Private DatabaseポリシーをHR.EMPLOYEES
表に付加する方法を示します。ポリシーに付加される関数はcheck_updates
です。
例7-1 表への単純なOracle Virtual Private Databaseポリシーの付加
BEGIN DBMS_RLS.ADD_POLICY( object_schema => 'hr', object_name => 'employees', policy_name => 'secure_update', policy_function => 'check_updates', ...
関数がパッケージ内に作成されている場合は、パッケージ名を指定します。次に例を示します。
policy_function => 'pkg.check_updates', ...
注意: 表へのポリシーの定義は可能ですが、表に定義されたポリシーから表を選択することはできません。 |
Oracle Virtual Private Databaseポリシーは、SELECT
、INSERT
、UPDATE
、INDEX
およびDELETE
文に規定できます。文のタイプを指定しない場合、Oracle DatabaseではデフォルトでSELECT
、INSERT
、UPDATE
およびDELETE
が指定されますが、INDEX
は指定されません。DBMS_RLS.ADD_POLICY
プロシージャのstatement_types
パラメータを使用して、これらの文の組合せを入力します。リストは一重引用符で囲みます。
例7-2に、ポリシーに対してSELECT
文とINDEX
文を指定する方法を示します。
例7-2 DBMS_RLS.ADD_POLICYを使用したSQL文の指定
BEGIN
DBMS_RLS.ADD_POLICY(
object_schema => 'hr',
object_name => 'employees',
policy_name => 'secure_update',
policy_function => 'check_updates',
statement_types => 'SELECT,INDEX');
END;
重要: 索引をメンテナンスする権限を持つユーザーは、表に対する完全なアクセス権がない場合でも、 SELECT など通常の問合せですべての行データを参照できます。たとえば、ユーザーは、関数の引数として列値を持つユーザー定義関数が含まれたファンクション索引を作成できます。索引の作成時に、Oracle Databaseはすべての行の列値をユーザー関数に渡します。これによって、索引を作成するユーザーは行データを使用できるようになります。statement_types パラメータにINDEX を指定することによって、索引メンテナンス操作に対してOracle Virtual Private Databaseポリシーを規定できます。 |
セキュリティに関連する列が問合せで参照される際に行レベルのセキュリティを規定するポリシーを作成できます。
列レベルのポリシーによって、セキュリティに関連する列が問合せで参照される際の行レベルのセキュリティを規定できます。列レベルのOracle Virtual Private Databaseポリシーは、表やビューに適用できますが、シノニムには適用できません。
ポリシーを列に適用するには、DBMS_RLS.ADD_POLICY
プロシージャのsec_relevant_cols
パラメータを使用して、セキュリティ関連の列を指定します。このパラメータによって、問合せで列が明示的または暗黙的に参照されるたびに、セキュリティ・ポリシーが適用されます。
たとえば、人事部門以外のユーザーは、通常、各自の社会保障番号を参照することのみが許可されます。販売担当者が次の問合せを開始するとします。
SELECT fname, lname, ssn FROM emp;
セキュリティ・ポリシーを実装する関数は述語ssn='my_ssn'
を戻します。Oracle Databaseは次のように問合せをリライトして実行します。
SELECT fname, lname, ssn FROM emp WHERE ssn = 'my_ssn';
例7-3は、営業部門(部門番号30)のユーザーは他部門の従業員の給与を参照できないというOracle Virtual Private Databaseポリシーを示します。このポリシーに関連する列は、sal
およびcomm
です。最初にOracle Virtual Private Databaseポリシー関数を作成し、次にDBMS_RLS
PL/SQLパッケージを使用して追加します。
例7-3 列レベルのOracle Virtual Private Databaseポリシーの作成
CREATE OR REPLACE FUNCTION hide_sal_comm ( v_schema IN VARCHAR2, v_objname IN VARCHAR2) RETURN VARCHAR2 AS con VARCHAR2 (200); BEGIN con := 'deptno=30'; RETURN (con); END hide_sal_comm;
次に、DBMS_RLS.ADD_POLICY
プロシージャを使用して、ポリシーを構成します。
BEGIN
DBMS_RLS.ADD_POLICY (
object_schema => 'scott',
object_name => 'emp',
policy_name => 'hide_sal_policy',
policy_function => 'hide_sal_comm',
sec_relevant_cols => 'sal,comm');
END;
列レベルのOracle Virtual Private Databaseに関するデフォルトの動作では、機密情報が含まれた列を参照する問合せから戻される行の数を制限します。例7-3に示すように、セキュリティ関連の列は、DBMS_RLS.ADD_POLICY
プロシージャのsec_relevant_cols
パラメータを使用して指定します。
たとえば、emp
表に対するSELECT
権限を持つ営業部門のユーザーを考えてみます。この表は、例7-3で作成した列レベルのOracle Virtual Private Databaseポリシーで保護されています。ユーザー(例: ユーザーSCOTT
)は次の問合せを実行します。
SELECT ENAME, d.dname, JOB, SAL, COMM FROM emp e, dept d WHERE d.deptno = e.deptno;
データベースは次の行を戻します。
ENAME DNAME JOB SAL COMM ---------- -------------- --------- ---------- ---------- ALLEN SALES SALESMAN 1600 300 WARD SALES SALESMAN 1250 500 MARTIN SALES SALESMAN 1250 1400 BLAKE SALES MANAGER 2850 TURNER SALES SALESMAN 1500 0 JAMES SALES CLERK 950 6 rows selected.
表示されるのは、行のすべての列に対してユーザーがアクセス権を持っている行のみです。
問合せで機密性の高い列を参照する場合、列レベルのOracle Virtual Private Databaseのデフォルト動作では、戻される行の数が制限されます。列のマスク動作を利用すると、機密性の高い列を参照している場合にもすべての行が表示されます。ただし、機密性の高い列はNULL
値で表示されます。列のマスク動作を有効にするには、DBMS_RLS.ADD_POLICY
プロシージャのsec_relevant_cols_opt
パラメータを設定します。
たとえば、前述の例に記載されている販売担当者の問合せ結果を考えてみます。列のマスクを使用すると、販売担当者自身の詳細と社会保障番号が格納されている行のみが表示されるのではなく、emp
表からすべての行が表示されますが、ssn
列の値はNULL
になります。この動作は、行のサブセットのみを戻す他のあらゆるタイプのOracle Virtual Private Databaseポリシーとは基本的に異なることに注意してください。
列レベルのOracle Virtual Private Databaseに関するデフォルトのアクションとは対照的に、列のマスク動作ではすべての行が表示されますが、機密情報が含まれた列の値はNULL
として戻されます。ポリシーに列のマスク動作を含めるには、DBMS_RLS.ADD_POLICY
プロシージャのsec_relevant_cols_opt
パラメータをdbms_rls.ALL_ROWS
に設定します。
例7-4に、列レベルのOracle Virtual Private Databaseに関する列のマスク動作を示します。例7-3と同じVPDポリシーを使用しますが、sec_relevant_cols_opt
はdbms_rls.ALL_ROWS
として指定されています。
例7-4 Oracle Virtual Private Databaseポリシーへの列のマスクの追加
BEGIN DBMS_RLS.ADD_POLICY( object_schema => 'scott', object_name => 'emp', policy_name => 'hide_sal_policy', policy_function => 'hide_sal_comm', sec_relevant_cols =>' sal,comm', sec_relevant_cols_opt => dbms_rls.ALL_ROWS); END;
emp
表に対するSELECT
権限を持つ営業部門のユーザー(たとえば、SCOTT
)が、次の問合せを実行するとします。
SELECT ENAME, d.dname, job, sal, comm FROM emp e, dept d WHERE d.deptno = e.deptno;
データベースは、この問合せで指定されたすべての行を戻しますが、Oracle Virtual Private Databaseポリシーによって一部の値はマスクされています。
ENAME DNAME JOB SAL COMM ---------- -------------- --------- ---------- ---------- CLARK ACCOUNTING MANAGER KING ACCOUNTING PRESIDENT MILLER ACCOUNTING CLERK JONES RESEARCH MANAGER FORD RESEARCH ANALYST ADAMS RESEARCH CLERK SMITH RESEARCH CLERK SCOTT RESEARCH ANALYST WARD SALES SALESMAN 1250 500 TURNER SALES SALESMAN 1500 0 ALLEN SALES SALESMAN 1600 300 JAMES SALES CLERK 950 BLAKE SALES MANAGER 2850 MARTIN SALES SALESMAN 1250 1400 14 rows selected.
列のマスク動作により、営業部門のユーザーの問合せで要求された列がすべて戻されますが、営業部門以外の従業員に関してはsal
列とcomm
列がNULL
になっています。
列のマスクが適用されるのは、SELECT
文に対してのみです。
通常のOracle Virtual Private Database述語とは異なり、ポリシー関数によって生成される列マスク条件は、単純なブール式であることが必要です。
計算を実行するアプリケーションや、NULL
値が戻されることが想定されていないアプリケーションの場合は、標準の列レベルのOracle Virtual Private Databaseを使用して、列のマスク動作オプションsec_relevant_cols_opt
ではなくsec_relevant_cols
を指定します。
UPDATE AS SELECT
とともに使用される列のマスク動作によって更新されるのは、ユーザーが表示を許可されている列のみです。
問合せによっては、列のマスク動作により一部の行が表示されない場合があります。次に例を示します。
SELECT * FROM emp WHERE sal = 10;
列のマスク動作オプションが設定されているため、salary
列にNULL
値が戻される場合は、この問合せを実行しても行が戻されない場合があります。
複数のセキュリティ・ポリシーをグループ化して、そのグループをアプリケーションに適用できます。
この項の内容は、次のとおりです。
ポリシー・グループは、1つのアプリケーションに属する一連のセキュリティ・ポリシーです。アプリケーション・コンテキスト(駆動コンテキストまたはポリシー・コンテキスト)を指定して、有効なポリシー・グループを指定できます。ユーザーが表、ビューまたはシノニムの列にアクセスすると、Oracle Databaseは駆動コンテキストを検索し、有効なポリシー・グループを判断します。Oracle Databaseは、そのポリシー・グループに属するすべての関連ポリシーを規定します。
ポリシー・グループは、複数のセキュリティ・ポリシーを持つ複数のアプリケーションが同一の表、ビューまたはシノニムを共有する場合に便利です。ポリシー・グループによって、表、ビューまたはシノニムがアクセスされたときに有効にするポリシーを識別できます。
たとえば、ホスト環境で、A社が、B社およびC社に対してBENEFIT
表をホスティングするとします。この表は、2つの異なるセキュリティ・ポリシーを持つ、Human Resources(人事管理)およびFinance(財務管理)という2つアプリケーションによってアクセスされます。Human Resourcesアプリケーションは社内の序列に基づいてユーザーを認可し、Financeアプリケーションは部門に基づいてユーザーを認可します。これらの2つのポリシーをBENEFIT
表に統合するには、2つの企業が共同でポリシーを開発する必要がありますが、それは現実的ではありません。ベース・オブジェクトに一連の特定のポリシーを規定するアプリケーション・コンテキストを定義することにより、各アプリケーションがセキュリティ・ポリシーの集合を個別に実装できます。
これを行うには、セキュリティ・ポリシーをグループ化します。アプリケーション・コンテキストを参照することにより、実行時に有効にするポリシーのグループをOracle Databaseが判断します。サーバーは、そのポリシー・グループに属するすべてのポリシーを規定します。
表、ビューまたはシノニムにポリシーを追加するには、DBMS_RLS.ADD_GROUPED_POLICY
プロシージャを使用して、そのポリシーが属するグループを指定します。有効にするポリシーを指定するには、DBMS_RLS.ADD_POLICY_CONTEXT
プロシージャを使用して駆動コンテキストを追加できます。駆動コンテキストが不明なポリシー・グループを戻した場合は、エラーが戻されます。
駆動コンテキストが定義されていない場合は、すべてのポリシーが実行されます。同様に、駆動コンテキストがNULL
である場合は、すべてのポリシー・グループのポリシーが規定されます。データにアクセスするアプリケーションは、セキュリティ設定モジュール(アプリケーション・コンテキストを設定するモジュール)を回避できないため、該当するすべてのポリシーが適用されます。
同一の表、ビューまたはシノニムに複数の駆動コンテキストを適用して、それぞれを個別に処理できます。これによって、複数のアクティブなポリシーを設定して規定できます。
たとえば、福利厚生アプリケーションと財務アプリケーションをホスティングするホスト企業があり、これらのアプリケーションが、いくつかのデータベース・オブジェクトを共有している場合を考えてみます。この2つのアプリケーションは、SYS_DEFAULT
ポリシー・グループのSUBSCRIBER
ポリシーを使用して、ホスティング用にストライプ化されます。データ・アクセスは、最初にサブスクライバIDごとにパーティション化され、次に、ユーザーが福利厚生アプリケーションまたは財務アプリケーションのどちらにアクセスしているか(駆動コンテキストによって決定される)によってパーティション化されます。ホスティング・サービスを使用するA社が、自社のデータ・アクセスにのみ関連したカスタム・ポリシーを適用するとします。この場合は、駆動コンテキスト(COMPANY A SPECIAL
など)を追加して、特別な追加のポリシー・グループの適用先をA社のデータ・アクセスのみに限定できます。このポリシーはA社のみに関連しているため、SUBSCRIBER
ポリシーの下では適用できません。基本的なホスティング・ポリシーは、他のポリシーから分離した方がより効率的です。
セキュリティ・ポリシーのグループ内で、1つのセキュリティ・ポリシーをデフォルト・セキュリティ・ポリシーに指定できます。これは、アプリケーションごとにセキュリティ・ポリシーを分割して、セキュリティ・ポリシーを常に有効にする場合に便利です。デフォルト・セキュリティ・ポリシーを使用すると、開発者はすべての条件下で基礎となるセキュリティを規定できます。一方、アプリケーションごとにセキュリティ・ポリシーを分割(セキュリティ・グループを使用)すると、デフォルト・セキュリティ・ポリシーにアプリケーション固有のセキュリティ・レイヤーを追加できます。デフォルト・セキュリティ・ポリシーを実装するには、SYS_DEFAULT
ポリシー・グループにポリシーを追加してください。
このグループ内に定義されている、特定の表、ビューまたはシノニムに対するポリシーは、駆動コンテキストが指定するポリシー・グループとともに実行されます。前述のとおり、駆動コンテキストは、有効なポリシー・グループを指定するアプリケーション・コンテキストです。SYS_DEFAULT
ポリシー・グループには、ポリシーが含まれる場合と含まれない場合があります。SYS_DEFAULT
ポリシー・グループは削除できません。このポリシー・グループを削除すると、Oracle Databaseでエラーが発生します。
SYS_DEFAULT
ポリシー・グループに、複数のオブジェクトに対応付けられているポリシーを追加する場合、各オブジェクトには個別にSYS_DEFAULT
ポリシー・グループが対応付けられます。たとえば、scott
スキーマのemp
表に1つのSYS_DEFAULT
ポリシー・グループがある場合、scott
スキーマのdept
表には別のSYS_DEFAULT
ポリシー・グループが対応付けられます。これは、次のようにツリー構造に編成されます。
SYS_DEFAULT - policy1 (scott/emp) - policy3 (scott/emp) SYS_DEFAULT - policy2 (scott/dept)
同一の名前を持つ複数のポリシー・グループを作成できます。特定のポリシー・グループを選択すると、対応付けられているスキーマとオブジェクト名が、画面右側のプロパティ・シートに表示されます。
同一の表、ビューまたはシノニムに対して複数のポリシーを設定できます。たとえば、受注用の基本アプリケーションがあり、社内の各部門にはそれぞれ独自のデータ・アクセス規則があるとします。基本アプリケーションのポリシー関数を作成しなおさなくても、部門固有のポリシー関数を表に追加できます。
表に適用されるすべてのポリシーは、AND
構文で規定されます。そのため、CUSTOMERS
表に3つのポリシーを適用している場合、各ポリシーが表に適用されます。データにアクセスするアプリケーションに応じて異なるポリシーが適用されるように、ポリシー・グループおよびアプリケーション・コンテキストを使用して、ファイングレイン・アクセス・コントロールの規定を分割できます。これによって、開発グループ間でポリシーを調整する必要がなくなり、アプリケーションの開発が容易になります。また、常に適用する(たとえば、ホスト環境でサブスクライバによりデータ分割を規定する)デフォルト・ポリシー・グループを保持することもできます。
駆動コンテキストを実装するパッケージは、データベースへの接続に使用されるアプリケーションを正しく検証する必要があります。Oracle Databaseは、コール・スタックをチェックして、駆動コンテキストを実装するパッケージによるコンテキスト属性の設定を確認しますが、パッケージ内では不適切な検証が発生する可能性があります。
たとえば、データベース・ユーザーまたはエンタープライズ・ユーザーがデータベースに認識されているアプリケーションの場合、ユーザーには、駆動コンテキストを設定するパッケージに対するEXECUTE
権限が必要です。次のことを認識しているユーザーを考えてみます。
BENEFITS
アプリケーションの方がHR
アプリケーションよりもアクセスが自由であること。
(正しいポリシー・グループを駆動コンテキスト内に設定する)setctx
プロシージャでは、実際に接続しているアプリケーションを判断するための検証が実行されないこと。つまり、このプロシージャでは、(3層システムに対する)着信接続のIPアドレス、またはユーザー・セッションのproxy_user
属性がチェックされないこと。
ユーザーは、アクセスがより自由なBENEFITS
ポリシー・グループにコンテキストを設定する引数を駆動コンテキスト・パッケージに渡してから、かわりにHR
アプリケーションにアクセスできます。setctx
ではアプリケーションに対してそれ以上の検証を行わないため、このユーザーは限定的なHRセキュリティ・ポリシーをバイパスしてしまいます。
一方、Oracle Virtual Private Databaseによるプロキシ認証を実装すると、ユーザーのかわりにデータベースに接続する中間層(およびアプリケーション)の識別情報を確認できます。これによって、データ・アクセスを仲介するアプリケーションごとに正しいポリシーが適用されます。
たとえば、開発者は、プロキシ認証機能を使用して、データベースに接続しているアプリケーション(中間層)がHRAPPSERVER
であることを確認できます。このように、駆動コンテキストを実装するパッケージでは、ユーザー・セッションのproxy_user
がHRAPPSERVER
かどうかを検証できます。proxy_user
がHRAPPSERVER
の場合は、HR
ポリシー・グループを使用するように駆動コンテキストを設定できます。proxy_user
がHRAPPSERVER
でない場合は、アクセスを拒否できます。
このような場合に、次の問合せが実行されるとします。
SELECT * FROM apps.benefit;
Oracle Databaseは、デフォルト・ポリシー・グループ(SYS_DEFAULT
)およびアクティブなネームスペースHR
のポリシーを選択します。この問合せは、内部で次のようにリライトされます。
SELECT * FROM apps.benefit WHERE company = SYS_CONTEXT('ID','MY_COMPANY') and SYS_CONTEXT('ID','TITLE') = 'MANAGER';
ポリシーに対してポリシー・タイプを指定すると、ポリシーの各実行のパフォーマンスを最適化できます。ポリシー・タイプを使用して、Oracle DatabaseがOracle Virtual Private Databaseポリシーの述語をキャッシュする方法を制御します。ポリシー関数を実行すると、システム・リソースを大量に消費する場合があるため、ポリシーに対してポリシー・タイプを設定することを検討してください。ポリシー関数の実行回数を最小限に抑えることで、データベースのパフォーマンスを最適化できます。
選択できるポリシー・タイプは、DYNAMIC
、STATIC
、SHARED_STATIC
、CONTEXT_SENSITIVE
およびSHARED_CONTEXT_SENSITIVE
の5種類です。これらのポリシー・タイプによって、ポリシーの述語を変更する頻度を正確に指定できます。ポリシー・タイプを指定するには、DBMS_RLS.ADD POLICY
プロシージャのpolicy_type
パラメータを設定します。
この項の内容は、次のとおりです。
DYNAMIC
ポリシー・タイプを指定すると、ユーザーが仮想プライベート・データベースで保護されたデータベース・オブジェクトにアクセスするたびに、ポリシー関数が実行されます。DBMS_RLS.ADD_POLICY
プロシージャにポリシー・タイプを指定しない場合、ポリシーはデフォルトで動的になります。ポリシーを動的に構成するには、DBMS_RLS.ADD_POLICY
プロシージャのpolicy_type
パラメータをDYNAMIC
に設定します。
動的ポリシー・タイプでは、静的ポリシーや状況依存ポリシー・タイプの場合と異なり、データベースのパフォーマンスは最適化されません。ただし、ポリシーを静的または状況依存に設定する前に、その都度実行されるDYNAMIC
ポリシー・タイプでテストすることをお薦めします。最初にポリシー関数をDYNAMIC
ポリシーでテストすると、何もキャッシュされていないため、ポリシー関数が各問合せに与える影響を調べることができます。これにより、パフォーマンスを最適化するために静的ポリシーまたは状況依存ポリシーを使用可能にする前に、関数が正常に機能することを確認できます。
文の実行開始時間と終了時間を測定するには、DBMS_UTILITY.GET_TIME
プロシージャを使用します。次に例を示します。
SQL> SELECT DBMS_UTILITY.GET_TIME FROM DUAL; GET_TIME ---------- 2312721 SQL> SELECT COUNT(*) FROM HR.EMPLOYEES; COUNT(*) ---------- 107 SQL> SELECT DBMS_UTILITY.GET_TIME FROM DUAL; GET_TIME ---------- 2314319
例7-5に、DYNAMIC
ポリシー・タイプの作成方法を示します。
静的ポリシー・タイプを指定すると、インスタンス内のすべてのユーザーに対して同じ述語が規定されます。Oracle Databaseでは静的ポリシーの述語がSGAに格納されるため、ポリシー関数は問合せごとに再実行されません。その結果、パフォーマンスが向上します。
静的ポリシーを使用可能にするには、そのポリシーを複数のオブジェクト間で共有するかどうかに応じて、DBMS_RLS.ADD_POLICY
プロシージャのpolicy_type
パラメータをSTATIC
またはSHARED_STATIC
のいずれかに設定します。
例7-6に、STATIC
ポリシー・タイプの作成方法を示します。
例7-6 DBMS_RLS.ADD_POLICYを使用したSTATICポリシーの作成
BEGIN
DBMS_RLS.ADD_POLICY(
object_schema => 'hr',
object_name => 'employees',
policy_name => 'secure_update',
policy_function => 'hide_fin',
policy_type => dbms_rls.STATIC);
END;
述語が同じでも、同じカーソルを実行するたびに異なる行セットが生成される場合があります。これは、述語によるデータのフィルタ処理がSYS_CONTEXT
やSYSDATE
などの属性によって異なるためです。
たとえば、ポリシーをSTATIC
またはSHARED_STATIC
ポリシー・タイプとして使用可能にする場合を想定します。この場合は、ポリシーで保護されたデータベース・オブジェクトに対して実行されるすべての問合せに次の述語が追加されます。
WHERE dept = SYS_CONTEXT ('hr_app','deptno')
述語は、問合せごとに変わりませんが、SYS_CONTEXT
のセッション属性に基づいて問合せに適用されます。前述の例の述語では、ポリシーで保護されたデータベース・オブジェクトを問い合せているユーザーの部門番号がSYS_CONTEXT
のdeptno
属性と一致する行のみを戻します。
注意: 共有の静的ポリシーを使用する場合は、ポリシーの述語に、列名など特定のデータベース・オブジェクト固有の属性が含まれていないことを確認してください。 |
たとえば、使用する財務データを含むHR
スキーマの2番目の表に例7-6のポリシーを適用する場合、両方の表でSHARED_STATIC
設定を使用します。
例7-7に、同じポリシーを共有する2つの表に対してSHARED_STATIC
ポリシー・タイプを設定する方法を示します。
例7-7 DBMS_RLS.ADD_POLICYを使用したSHARED_STATICポリシーの作成
-- Create a policy for the first table, employees: BEGIN DBMS_RLS.ADD_POLICY( object_schema => 'hr', object_name => 'employees', policy_name => 'secure_update', policy_function => 'hide_fin', policy_type => dbms_rls.SHARED_STATIC); END; -- Now create a policy for the second table, fin_data: BEGIN DBMS_RLS.ADD_POLICY( object_schema => 'hr', object_name => 'fin_data', policy_name => 'secure_update', policy_function => 'hide_fin', policy_type => dbms_rls.SHARED_STATIC); END;
静的ポリシーは、すべての問合せに同じ述語が必要で、高いパフォーマンスが不可欠なホスト環境などに最適です。このような環境では、ポリシー関数がすべての問合せに同じ述語を追加すると、ポリシー関数を再実行するたびに不要なオーバーヘッドがシステムに加わります。たとえば、競争相手である複数の顧客企業に関する市場調査データが含まれたデータ・ウェアハウスを考えてみます。このウェアハウスでは、各企業が自社の市場調査データのみを参照できるポリシーを規定する必要があり、このポリシーは次の述語で表現されます。
WHERE subscriber_id = SYS_CONTEXT('customer', 'cust_num')
アプリケーション・コンテキストに対してSYS_CONTEXT
を使用すると、データベースでは、戻される行を動的に変更できます。関数を再実行する必要はなく、述語はSGAにキャッシュされるため、システム・リソースを節約でき、パフォーマンスが向上します。
静的ポリシーとは対照的に、状況依存ポリシーは必ずしも述語をキャッシュしません。状況依存ポリシーの場合、データベースでは、述語は文の解析後に変更されると想定しています。ただし、ローカル・アプリケーション・コンテキストに変更がない場合、Oracle Databaseはユーザー・セッション内でポリシー関数を再実行しません。コンテキストに変更があった場合、データベースはポリシー関数を再実行して、最初の解析以降の述語に対する変更を取得します。
状況依存ポリシーを使用可能にするには、DBMS_RLS.ADD_POLICY
プロシージャのpolicy_type
パラメータをCONTEXT_SENSITIVE
またはSHARED_CONTEXT_SENSITIVE
に設定します
例7-8に、CONTEXT_SENSITIVE
ポリシー・タイプの作成方法を示します。
例7-8 DBMS_RLS.ADD_POLICYを使用したCONTEXT_SENSITIVEポリシーの作成
BEGIN
DBMS_RLS.ADD_POLICY(
object_schema => 'hr',
object_name => 'employees',
policy_name => 'secure_update',
policy_function => 'hide_fin',
policy_type => dbms_rls.CONTEXT_SENSITIVE);
END;
状況依存ポリシーは、異なる述語を、問合せを実行するユーザーに応じて適用する必要がある場合に便利です。たとえば、マネージャには述語WHERE group
がmanagers
に設定され、従業員には述語WHERE empno
がemp_id
に設定される場合を考えてみます。
共有の状況依存ポリシーは、複数のデータベース・オブジェクト間で共有できることを除いて、通常の状況依存ポリシーと同様に機能します。このポリシー・タイプの場合、すべてのオブジェクトはUGAからポリシー関数を共有できます。述語は、ローカル・セッションのコンテキストに変更があるまで、UGAにキャッシュされます。
注意: 共有の状況依存ポリシーを使用する場合は、ポリシーの述語に、列名など特定のデータベース・オブジェクト固有の属性が含まれていないことを確認してください。 |
例7-9に、複数の表で1つのポリシーを共有する、2つの共有の状況依存ポリシーを作成する方法を示します。
例7-9 DBMS_RLS.ADD_POLICYを使用したSHARED_CONTEXT_SENSITIVEポリシーの作成
-- Create a policy for the first table, employees: BEGIN DBMS_RLS.ADD_POLICY( object_schema => 'hr', object_name => 'employees', policy_name => 'secure_update', policy_function => 'hide_fin', policy_type => dbms_rls.SHARED_CONTEXT_SENSITIVE); END; -- Now create a policy for the second table, fin_data: BEGIN DBMS_RLS.ADD_POLICY( object_schema => 'hr', object_name => 'fin_data', policy_name => 'secure_update', policy_function => 'hide_fin', policy_type => dbms_rls.SHARED_CONTEXT_SENSITIVE); END;
状況依存ポリシーは、ユーザー・セッションごとに述語を変える必要はないが、ポリシーが異なるユーザーまたはグループに複数の異なる述語を規定する必要がある場合に便利です。たとえば、単一のポリシーを持つsales_history
表を考えてみます。このポリシーでは、アナリストは自分の製品のみを参照でき、地域担当者は自分の地域のみを参照できます。この場合、データベースは、ユーザーのタイプが変わるたびにポリシー関数を再実行する必要があります。サーバーによるポリシー関数の再実行なしに、ユーザーがログインして保護されたオブジェクトに対していくつかのDML文を発行できる場合は、パフォーマンスが向上します。
表7-2に、使用可能なポリシー・タイプの要約を示します。
表7-2 DBMS_RLS.ADD_POLICYのポリシー・タイプ
ポリシー・タイプ | ポリシー関数の実行 | 使用例 | 複数オブジェクト間での共有 |
---|---|---|---|
|
ポリシーで保護されたデータベース・オブジェクトがアクセスされるたびに、ポリシー関数を再実行します。 |
日中の特定時間は、ユーザーによるデータベース・オブジェクトへのアクセスを拒否する時間依存のポリシーなど、ポリシーの述語を問合せごとに生成する必要があるアプリケーション。 |
なし |
|
1回実行され、述語はSGAにキャッシュされます。脚注1 |
ビューの置換。 |
なし |
|
|
同じ述語を複数のデータベース・オブジェクトに適用する必要があるデータ・ウェアハウスなどのホスト環境。 |
あり |
|
|
ポリシーによって異なるユーザーまたはグループに複数の述語が規定される、3層セッション・プーリング・アプリケーション。 |
なし |
|
データベース・セッションで最初にオブジェクトが参照されたとき。 述語はプライベート・セッション・メモリーであるUGAにキャッシュされるため、ポリシー関数を複数のオブジェクト間で共有できます。 |
|
あり |
脚注1 述語が同じでも、同じカーソルを実行するたびに異なる行セットが生成される場合があります。これは、述語によるデータのフィルタ処理がSYS_CONTEXT
やSYSDATE
などの属性によって異なるためです。
この項の内容は、次のとおりです。
営業担当者159が作成したOE.ORDERS
表内のすべての受注へのアクセスを制限する、単純なOracle Virtual Private Databaseポリシーを作成する必要があるとします。このポリシーは、基本的に次の文で表現されます。
SELECT * FROM OE.ORDERS;
このポリシーを次のように変換します。
SELECT * FROM OE.ORDERS WHERE SALES_REP_ID = 159;
手順は、次のとおりです。
SYS
としてSQL*Plusにログインし、AS SYSDBA
権限を使用して接続します。
sqlplus "SYS/AS SYSDBA"
Enter password: password
DBA_USERS
データ・ディクショナリ・ビューに対して、次のSELECT
文を実行します。
SELECT USERNAME, ACCOUNT_STATUS FROM DBA_USERS WHERE USERNAME = 'OE';
DBA_USERS
ビューに、ユーザーOE
がロックされて期限切れになっていると表示された場合は、次の文を入力して、OE
アカウントのロックを解除し、新しいパスワードを作成します。
ALTER USER OE ACCOUNT UNLOCK IDENTIFIED BY password;
password
を安全なパスワードに置き換えます。セキュリティを向上させるため、以前のリリースのOracle Databaseで使用されたパスワードを再利用しないでください。詳細は、「パスワードの最低要件」を参照してください。
次の関数を作成します。この関数は、OE.ORDERS
表に対するSELECT
文にWHERE SALES_REP_ID = 159
句を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 |
CREATE OR REPLACE FUNCTION auth_orders( schema_var IN VARCHAR2, table_var IN VARCHAR2 ) RETURN VARCHAR2 IS return_val VARCHAR2 (400); BEGIN return_val := 'SALES_REP_ID = 159'; RETURN return_val; END auth_orders; / |
この例の説明は、次のとおりです。
2–3行目: スキーマ名OE
と表名ORDERS
を格納するために指定する入力パラメータを作成します。最初に、スキーマ用のパラメータを定義し、次に、オブジェクト(この例では表)用のパラメータを定義します。パラメータは常にこの順序で作成します。作成する仮想プライベート・データベース・ポリシーでは、OE.ORDERS
表を指定するためにこれらのパラメータが必要です。
5行目: WHERE
述語句で使用する文字列を戻します。戻り値は常にVARCHAR2
データ型になります。
6–10行目: WHERE SALES_REP_ID = 159
述語の作成を含みます。
次に、DBMS_RLS
パッケージのADD_POLICY
プロシージャを使用して、次のポリシーを作成します。
1 2 3 4 5 6 7 8 9 10 11 |
BEGIN DBMS_RLS.ADD_POLICY ( object_schema => 'oe', object_name => 'orders', policy_name => 'orders_policy', function_schema => 'sys', policy_function => 'auth_orders', statement_types => 'select, insert, update, delete' ); END; / |
この例の説明は、次のとおりです。
3行目: 保護するスキーマ(この例ではOE
)を指定します。
4行目: 保護するスキーマ内のオブジェクト(この例ではORDERS
表)を指定します。
5行目: このポリシーの名前をorders_policy
と指定します。
6行目: auth_orders
関数が作成されたスキーマを指定します。この例では、auth_orders
はSYS
スキーマに作成されています。ただし、通常は、セキュリティ管理者のスキーマに作成する必要があります。
7行目: ポリシーを規定する関数を指定します。この例では、「手順2: ポリシー関数の作成」で作成したauth_orders
関数を指定します。
8行目: ポリシーを適用する操作を指定します。この例では、ポリシーは、ユーザーが実行可能なすべてのSELECT
文、INSERT
文、UPDATE
文およびDELETE
文に適用されます。
Oracle Virtual Private Databaseポリシーを作成した直後に、ポリシーは有効になります。ユーザー(スキーマの所有者を含む)が次にOE.ORDERS
に対してSELECT
文を実行すると、営業担当者159の受注のみにアクセスできます。
ユーザーOE
でログインします。
CONNECT oe
Enter password: password
Connected.
次のSELECT
文を入力します。
SELECT COUNT(*) FROM ORDERS;
次の出力が表示されます。
COUNT(*) --------- 7
ポリシーはユーザーOE
に対して有効です。ここに示すように、受注表の105行の内、7行のみが戻されます。
ただし、管理権限を持つユーザーは、表のすべての行にアクセスできます。
ユーザーSYS
で再度ログインします。
CONNECT sys/as sysdba
Enter password: password
Connected.
次のSELECT
文を入力します。
SELECT COUNT(*) FROM OE.ORDERS;
次の出力が表示されます。
COUNT(*) --------- 105
ユーザーSYS
で、次のように関数とポリシーを削除します。
DROP FUNCTION auth_orders; EXEC DBMS_RLS.DROP_POLICY('OE','ORDERS','ORDERS_POLICY');
OE
アカウントをロックして期限切れにする必要がある場合は、次の文を入力します。
ALTER USER OE ACCOUNT LOCK PASSWORD EXPIRE;
この例では、データベース・セッション・ベースのアプリケーション・コンテキストを使用して、顧客が自分の注文のみを参照できるというポリシーを実装する方法を示しています。 次のようにセキュリティのレイヤーを作成します。
ユーザーがログインするとき、データベース・セッション・ベースのアプリケーション・コンテキストによって顧客かどうかがチェックされます。 顧客でないユーザーでもログインできますが、このユーザーはこの例で作成する注文表にアクセスできません。
ユーザーが顧客の場合はログインできます。 顧客がログインした後、Oracle Virtual Private Databaseポリシーによって、このユーザーは自分の注文のみを参照できるように制限されます。
さらに、Oracle Virtual Private Databaseポリシーによって、ユーザーは自分の注文の表示のみが許可されます。 ユーザーは、注文の追加、変更または削除はできません。
手順は、次のとおりです。
SQL*Plusを起動して、管理権限を持つユーザーとしてログインします。
sqlplus "SYS/AS SYSDBA"
Enter password: password
Connected.
Oracle Virtual Private Databaseポリシーを管理する、次の管理ユーザーを作成します。
次のSQL文では、このユーザーを作成してから、この例を終了するのに必要な権限をユーザーに付与します。
GRANT CREATE SESSION, CREATE ANY CONTEXT, CREATE PROCEDURE, CREATE TRIGGER, ADMINISTER DATABASE TRIGGER TO sysadmin_vpd IDENTIFIED BY password;
GRANT EXECUTE ON DBMS_SESSION TO sysadmin_vpd;
GRANT EXECUTE ON DBMS_RLS TO sysadmin_vpd;
password
を安全なパスワードに置き換えます。詳細は、「パスワードの最低要件」を参照してください。
次のユーザー・アカウントを作成します。
GRANT CREATE SESSION TO tbrooke IDENTIFIED BY password; GRANT CREATE SESSION TO owoods IDENTIFIED BY password;
password
を安全なパスワードに置き換えます。詳細は、「パスワードの最低要件」を参照してください。
この例で使用するサンプル・ユーザーSCOTT
のステータスをチェックします。
SELECT USERNAME, ACCOUNT_STATUS FROM DBA_USERS WHERE USERNAME = 'SCOTT';
DBA_USERS
ビューに、ユーザーSCOTT
がロックされて期限切れになっていると表示された場合は、次の文を入力して、SCOTT
アカウントのロックを解除し、新しいパスワードを作成します。
ALTER USER SCOTT ACCOUNT UNLOCK IDENTIFIED BY password;
password
を安全なパスワードに置き換えます。セキュリティを向上させるため、以前のリリースのOracle Databaseで使用されたパスワードを再利用しないでください。詳細は、「パスワードの最低要件」を参照してください。
ユーザーSCOTT
で接続し、customers
表を作成して値を入力します。
CONNECT scott
Enter password: password
Connected.
CREATE TABLE customers (
cust_no NUMBER(4),
cust_email VARCHAR2(20),
cust_name VARCHAR2(20));
INSERT INTO customers VALUES (1234, 'TBROOKE', 'Thadeus Brooke');
INSERT INTO customers VALUES (5678, 'OWOODS', 'Oberon Woods');
ユーザーの電子メール・アドレスを入力する際には、大文字で入力します。後でアプリケーション・コンテキストのPL/SQLパッケージを作成するときに、SYS_CONTEXT
ファンクションのSESSION_USER
パラメータではユーザー名が大文字であると想定されます。大文字でないと、そのユーザー用のアプリケーション・コンテキストを設定できません。
ユーザーsysadmin_vpd
には、ユーザーSCOTT
と同様にcustomers表のSELECT
権限が必要になるため、この権限をsysadmin_vpdに付与します。
GRANT SELECT ON customers TO sysadmin_vpd;
orders_tab
表を作成して値を入力します。
CREATE TABLE orders_tab ( cust_no NUMBER(4), order_no NUMBER(4)); INSERT INTO orders_tab VALUES (1234, 9876); INSERT INTO orders_tab VALUES (5678, 5432); INSERT INTO orders_tab VALUES (5678, 4592);
ユーザーtbrooke
とowoods
はorders_tab
表を問い合せる必要があるため、これらのユーザーにSELECT
権限を付与します。
GRANT SELECT ON orders_tab TO tbrooke; GRANT SELECT ON orders_tab TO owoods;
orders_tab
受注表には、2名のサンプル顧客tbrooke
とowoods
の購買レコードがあります。この段階では、これらの顧客がこの表を参照すると、すべての受注を参照できます。
ユーザーsysadmin_vpd
で接続します。
CONNECT sysadmin_vpd
Enter password: password
Connected.
次の文を入力します。
CREATE OR REPLACE CONTEXT orders_ctx USING orders_ctx_pkg;
この文は、orders_ctx
アプリケーション・コンテキストを作成します。ユーザーsysadmin_vpd
がこのコンテキストを作成してsysadmin_vpd
スキーマに対応付けた場合でも、SYS
スキーマがこのアプリケーション・コンテキストを所有することに注意してください。
ユーザーsysadmin_vpd
で、次のPL/SQLパッケージを作成します。このパッケージによって、顧客tbrooke
およびowoods
がアカウントにログインしたときに、データベース・セッション・ベースのアプリケーション・コンテキストが設定されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
CREATE OR REPLACE PACKAGE orders_ctx_pkg IS PROCEDURE set_custnum; END; / CREATE OR REPLACE PACKAGE BODY orders_ctx_pkg IS PROCEDURE set_custnum AS custnum NUMBER; BEGIN SELECT cust_no INTO custnum FROM scott.customers WHERE cust_email = SYS_CONTEXT('USERENV', 'SESSION_USER'); DBMS_SESSION.SET_CONTEXT('orders_ctx', 'cust_no', custnum); EXCEPTION WHEN NO_DATA_FOUND THEN NULL; END set_custnum; END; / |
この例の説明は、次のとおりです。
8行目: 顧客IDを保持するcustnum
変数を作成します。
10行目: SELECT
文を実行し、scott.customers
表のcust_no
列データに格納されている顧客IDをcustnum
変数にコピーします。
11行目: WHERE
句を使用して、ログインしたユーザーのユーザー名と一致するすべての顧客IDを検索します。
12行目: cust_no
属性を作成し、この属性をcustnum
変数に格納された値に設定して、orders_ctx
アプリケーション・コンテキスト値を設定します。
13–14行目: WHEN NO_DATA_FOUND
システム例外を追加して、10–11行目のSELECT
文によって発生した可能性のあるno data found
エラーを捕捉します。
要約すると、sysadmin_vpd.set_cust_num
プロシージャは、セッション・ユーザーの顧客IDを選択してcustnum
変数に格納することによって、ユーザーが登録済顧客かどうかを識別します。 ユーザーが登録済顧客の場合、Oracle Databaseによってこのユーザーにアプリケーション・コンテキスト値が設定されます。 「手順5: ユーザー・アクセスを自分の注文に制限するPL/SQLポリシー関数の作成」に示すように、ポリシー関数では、コンテキスト値を使用して、ユーザーがorders_tab
表内のデータに対して持つアクセスを制御します。
次回ユーザーがログインすると、ログイン・トリガーによって、「手順3: アプリケーション・コンテキストを設定するPL/SQLパッケージの作成」で作成したPL/SQLパッケージのプロシージャが実行されるため、アプリケーション・コンテキストを設定できます。
ユーザーsysadmin_vpd
で、次のトリガーを作成します。
CREATE TRIGGER set_custno_ctx_trig AFTER LOGON ON DATABASE BEGIN sysadmin_vpd.orders_ctx_pkg.set_custnum; END; /
この段階で、tbrooke
またはowoods
でログインすると、ログイン・トリガーによってsysadmin_vpd.orders_ctx_pkg.set_custnum
プロシージャの起動時にユーザー用のアプリケーション・コンテキストが設定されます。これは次のようにテストできます。
CONNECT tbrooke
Enter password: password
SELECT SYS_CONTEXT('orders_ctx', 'cust_no') custnum FROM DUAL;
次の出力が表示されます。
EMP_ID ------------------------------------------------------------------- 1234
次の手順では、ログインしたユーザーがSELECT * FROM scott.orders_tab
問合せを実行するとそのユーザーの注文のみが表示されるように、PL/SQLファンクションを作成します。
ユーザーsysadmin_vpd
で、次の関数を作成します。
CREATE OR REPLACE FUNCTION get_user_orders( schema_p IN VARCHAR2, table_p IN VARCHAR2) RETURN VARCHAR2 AS orders_pred VARCHAR2 (400); BEGIN orders_pred := 'cust_no = SYS_CONTEXT(''orders_ctx'', ''cust_no'')'; RETURN orders_pred; END; /
この関数は、「ログインしたユーザーに属する注文を表示」するWHERE
述語を作成して戻します。このWHERE
述語は、ユーザーがscott.orders_tab
表に対して実行する問合せに追加されます。 次に、この関数をorders_tab
表に適用するOracle Virtual Private Databaseポリシーを作成する必要があります。
ユーザーsysadmin_vpd
で、次のポリシーを作成します。
BEGIN DBMS_RLS.ADD_POLICY ( object_schema => 'scott', object_name => 'orders_tab', policy_name => 'orders_policy', function_schema => 'sysadmin_vpd', policy_function => 'get_user_orders', statement_types => 'select'); END; /
この文は、orders_policy
というポリシーを作成して、SCOTT
スキーマのorders_tab
表(顧客が注文を問い合せる表)に適用します。get_user_orders
関数がこのポリシーを実装します。この関数はsysadmin_vpd
スキーマに格納されます。さらに、このポリシーにより、ユーザーはSELECT
文のみの発行に制限されます。
ユーザーtbrooke
でログインします。
CONNECT tbrooke
Enter password: password
Connected.
ユーザーtbrooke
は、アプリケーション・コンテキストに定義した要件を通過できるため、ログインできます。
ユーザーtbrooke
で、購買レコードにアクセスします。
SELECT * FROM scott.orders_tab;
次の出力が表示されます。
CUST_NO ORDER_NO ---------- ---------- 1234 9876
ユーザーtbrooke
は、2番目のテストを通過します。このユーザーは、scott.orders_tab
表にある自分の注文のみにアクセスできます。
ユーザーowoods
でログインし、購買レコードにアクセスします。
CONNECT tbrooke
Enter password: passwords
SELECT * FROM scott.orders_tab
次の出力が表示されます。
CUST_NO ORDER_NO ---------- ---------- 5678 5432 5678 4592
ユーザーtbrooke
とユーザーowoods
はログインでき、自分の注文のリストを参照できます。
次のことに注意してください。
ユーザーの職位に基づいて複数の述語を作成できます。たとえば、営業担当者は自分の担当顧客のレコードのみを参照でき、受注入力担当はすべての顧客注文を参照できます。get_user_orders
関数は、ユーザーの職位のコンテキスト値に基づいて異なる述語を戻すように拡張できます。
ファイングレイン・アクセス・コントロール・パッケージ内でアプリケーション・コンテキストを使用することによって、実際には解析済の文の中にバインド変数が指定されます。次に例を示します。
SELECT * FROM scott.orders_tab WHERE cust_no = SYS_CONTEXT('order_entry', 'cust_num');
この文は完全に解析および最適化されますが、order_entry
コンテキストに対するユーザーのcust_num
属性値の評価は、実行時に行われます。これは、最適化された文には、その文を発行するユーザーごとに異なる形態で実行されるという利点があることを意味します。
コンテキスト属性は、データベース表(複数も可)のデータ、またはLightweight Directory Access Protocol(LDAP)を使用するディレクトリ・サーバーのデータに基づいて設定できます。
動的に生成された述語の中でアプリケーション・コンテキストを使用するこの例と、述語の中で副問合せを使用する「Oracle Virtual Private Databaseポリシーの概要」を比較してください。
ユーザーOE
で接続し、orders_tab
およびcustomers
表を削除します。
CONNNECT SCOTT Enter password: password Connected. DROP TABLE orders_tab; DROP TABLE customers;
ユーザーSYS
としてAS SYSDBA
で接続します。
CONNECT sys/as sysdba
Enter password: password
Connected.
次の文を実行して、この例で使用したコンポーネントを削除します。
DROP CONTEXT orders_ctx; DROP USER sysadmin_vpd CASCADE; DROP USER tbrooke; DROP USER owoods;
アプリケーションで使用する一連のポリシーをグループ化する方法については、「ポリシー・グループの使用」を参照してください。 非データベース・ユーザーがアプリケーションにログインすると、Oracle Databaseでは、適切なポリシー・グループ内で定義されたポリシーに基づいてユーザーにアクセス権が付与されます。
列レベルのアクセス制御の場合、各列または非表示の列セットが1つのポリシーで制御されます。この例では、2つの列セットを非表示にする必要があります。 そのため、非表示にする列セットごとに1つずつ、2つのポリシーを作成します。ユーザーごとに必要なポリシーは1つのみのため、駆動アプリケーション・コンテキストによってポリシーが分割されます。
手順は、次のとおりです。
ユーザーSYS
としてSYSDBA
権限でログインします。
sqlplus SYS/AS SYSDBA
Enter password: password
Connected.
次のユーザーを作成します。
GRANT CREATE SESSION TO app_user IDENTIFIED BY password; GRANT CREATE SESSION, CREATE PROCEDURE, CREATE ANY CONTEXT TO sysadmin_pg IDENTIFIED BY password;
password
を安全なパスワードに置き換えます。詳細は、「パスワードの最低要件」を参照してください。
ユーザーsysadmin_pg
に次の権限を追加付与します。
GRANT EXECUTE ON DBMS_RLS TO sysadmin_pg;
ユーザーOE
でログインします。
CONNECT OE
Enter password: password
Connected.
OE
アカウントがロックされて期限切れになっている場合、SYSDBA
権限を持つユーザーSYS
として再接続してから、次の文を入力してアカウントのロックを解除し、新しいパスワードを指定します。
ALTER USER OE ACCOUNT UNLOCK IDENTIFIED BY password;
password
を安全なパスワードに置き換えます。セキュリティを向上させるため、以前のリリースのOracle Databaseで使用されたパスワードを再利用しないでください。詳細は、「パスワードの最低要件」を参照してください。
product_code_names
表を作成します。
CREATE TABLE product_code_names( group_a varchar2(32), year_a varchar2(32), group_b varchar2(32), year_b varchar2(32));
product_code_names
表に値をいくつか挿入します。
INSERT INTO product_code_names values('Harpo','2008','Groucho','2004'); INSERT INTO product_code_names values('Margaret Dumont','2008','Zeppo','2008'); INSERT INTO product_code_names values('Chico','2006','Margaret Dumont','2003'); COMMIT;
product_code_names
表のSELECT
権限をapp_user
ユーザーに付与します。
GRANT SELECT ON product_code_names TO app_user;
次に、2人の非データベース・ユーザーprovider_a
およびprovider_b
にそれぞれポリシー・グループを作成する必要があります。
ユーザーsysadmin_pg
で接続します。
CONNECT sysadmin_pg
Enter password: password
Connected.
ユーザーprovider_a
により使用されるprovider_a_group
ポリシー・グループを作成します。
BEGIN DBMS_RLS.CREATE_POLICY_GROUP( OBJECT_SCHEMA => 'oe', OBJECT_NAME => 'product_code_names', POLICY_GROUP => 'provider_a_group'); END; /
ユーザーprovider_b
により使用されるprovider_b_group
ポリシー・グループを作成します。
BEGIN DBMS_RLS.CREATE_POLICY_GROUP( OBJECT_SCHEMA => 'oe', OBJECT_NAME => 'product_code_names', POLICY_GROUP => 'provider_b_group'); END; /
「手順2: 2つのポリシー・グループの作成」で作成した各ポリシー・グループには、ユーザーprovider_a
およびprovider_b
のデータ・アクセスをアプリケーションで制御する方法を定義した関数が必要です。
ユーザーprovider_a
がアクセスするデータを制限するvpd_function_provider_a
関数を作成します。
CREATE OR REPLACE FUNCTION
vpd_function_provider_a
(schema in varchar2, tab in varchar2) return varchar2 as
predicate varchar2(8) default NULL;
BEGIN
IF LOWER(SYS_CONTEXT('USERENV','CLIENT_IDENTIFIER')) = 'provider_a'
THEN predicate := '1=2';
ELSE NULL;
END IF;
RETURN predicate;
END;
/
この関数では、ログインするユーザーが確かにユーザーprovider_a
であるかどうかがチェックされます。間違いない場合、provider_a
が表示できるのは、product_code_names
表の列group_a
およびyear_a
内のデータのみとなります。列group_b
およびyear_b
内のデータは、provider_a
に表示されません。つまり、predicate := '1=2'
を設定すると関連列が非表示になります。「手順4: PL/SQLファンクションのポリシー・グループへの追加」では、これらの列をSEC_RELEVANT_COLS
パラメータに指定します。
この関数タイプのコンポーネントの詳細は、「動的なWHERE句を生成する関数の作成」を参照してください。
ユーザーprovider_a
がアクセスするデータを制限するvpd_function_provider_b
関数を作成します。
CREATE OR REPLACE FUNCTION
vpd_function_provider_b
(schema in varchar2, tab in varchar2) return varchar2 as
predicate varchar2(8) default NULL;
BEGIN
IF LOWER(SYS_CONTEXT('USERENV','CLIENT_IDENTIFIER')) = 'provider_b'
THEN predicate := '1=2';
ELSE NULL;
END IF;
RETURN predicate;
END;
/
vpd_function_provider_a
関数と同様に、この関数では、ログインするユーザーが確かにユーザーprovider_b
であるかどうかがチェックされます。間違いない場合、provider_b
が表示できるのは、列group_b
およびyear_b
内のデータのみであり、group_a
およびyear_a
内のデータはprovider_b
には表示されません。vpd_function_provider_a
関数と同様に、predicate := '1=2'
に指定すると、「手順4: PL/SQLファンクションのポリシー・グループへの追加」でSEC_RELEVANT_COLS
パラメータに指定する関連列が非表示になります。
必要な関数を作成したら、適切なポリシー・グループに関数を関連付ける必要があります。
vpd_function_provider_a
関数をprovider_a_group
ポリシー・グループに追加します。
BEGIN DBMS_RLS.ADD_GROUPED_POLICY( OBJECT_SCHEMA => 'oe', OBJECT_NAME => 'product_code_names', POLICY_GROUP => 'provider_a_group', POLICY_NAME => 'filter_provider_a', FUNCTION_SCHEMA => 'sysadmin_pg', POLICY_FUNCTION => 'vpd_function_provider_a', STATEMENT_TYPES => 'select', POLICY_TYPE => DBMS_RLS.CONTEXT_SENSITIVE, SEC_RELEVANT_COLS => 'group_b,year_b', SEC_RELEVANT_COLS_OPT => DBMS_RLS.ALL_ROWS); END; /
SEC_RELEVANT_COLS
パラメータで指定したgroup_b
およびyear_b
列は、ユーザーprovider_a
に対して非表示になります。
vpd_function_provider_b
関数をprovider_b_group
ポリシー・グループに追加します。
BEGIN DBMS_RLS.ADD_GROUPED_POLICY( OBJECT_SCHEMA => 'oe', OBJECT_NAME => 'product_code_names', POLICY_GROUP => 'provider_b_group', POLICY_NAME => 'filter_provider_b', FUNCTION_SCHEMA => 'sysadmin_pg', POLICY_FUNCTION => 'vpd_function_provider_b', STATEMENT_TYPES => 'select', POLICY_TYPE => DBMS_RLS.CONTEXT_SENSITIVE, SEC_RELEVANT_COLS => 'group_a,year_a', SEC_RELEVANT_COLS_OPT => DBMS_RLS.ALL_ROWS); END; /
SEC_RELEVANT_COLS
パラメータで指定したgroup_a
およびyear_a
列は、ユーザーprovider_b
に対して非表示になります。
アプリケーション・コンテキストにより、ログインする非データベース・ユーザーが使用する必要があるポリシーが決定されます。
ユーザーsysadmin_pg
で、次の駆動アプリケーション・コンテキストを作成します。
CREATE OR REPLACE CONTEXT provider_ctx USING provider_package;
アプリケーション・コンテキストに対してPL/SQL provider_package
パッケージを作成します。
CREATE OR REPLACE PACKAGE provider_package IS PROCEDURE set_provider_context (policy_group varchar2 default NULL); END; / CREATE OR REPLACE PACKAGE BODY provider_package AS PROCEDURE set_provider_context (policy_group varchar2 default NULL) IS BEGIN CASE LOWER(SYS_CONTEXT('USERENV', 'CLIENT_IDENTIFIER')) WHEN 'provider_a' THEN DBMS_SESSION.SET_CONTEXT('provider_ctx','policy_group','PROVIDER_A_GROUP'); WHEN 'provider_b' THEN DBMS_SESSION.SET_CONTEXT('provider_ctx','policy_group','PROVIDER_B_GROUP'); END CASE; END set_provider_context; END; /
provider_ctx
アプリケーション・コンテキストをproduct_code_names
表に関連付け、名前を指定します。
BEGIN DBMS_RLS.ADD_POLICY_CONTEXT( object_schema =>'oe', object_name =>'product_code_names', namespace =>'provider_ctx', attribute =>'policy_group'); END; /
apps_user
アカウントにprovider_package
パッケージに対するEXECUTE
権限を付与します。
GRANT EXECUTE ON provider_package TO apps_user;
これで、2つのポリシー・グループをテストできます。
ユーザーapps_user
として接続した後、次の文を入力して、後で作成する出力の書式が適切に設定されるようにします。
CONNECT apps_user
Enter password: password
Connected.
col group_a format a16
col group_b format a16;
col year_a format a16;
col year_b format a16;
セッション識別子をprovider_a
に設定します。
EXEC DBMS_SESSION.SET_IDENTIFIER('provider_a');
ここで、アプリケーションが識別子を設定します。 識別子をprovider_a
に設定すると、apps_user
ユーザーは、provider_a_group
ポリシー・グループ内の製品に使用可能な製品のみが表示されるユーザーとして設定されます。
provider_package
を実行し、コンテキストに基づいてポリシー・グループを設定します。
EXEC sysadmin_pg.provider_package.set_provider_context;
この時点で、アプリケーション・コンテキストが設定されたことを、次のように確認できます。
SELECT SYS_CONTEXT('USERENV', 'CLIENT_IDENTIFIER') AS END_USER FROM DUAL;
次の出力が表示されます。
END_USER ----------------- provider_a
次のSELECT
文を入力します。
SELECT * FROM oe.product_code_names;
次の出力が表示されます。
GROUP_A YEAR_A GROUP_B YEAR_B ---------------- ---------------- ---------------- ---------------- Harpo 2008 Margaret Dumont 2008 Chico 2006
クライアント識別子をprovider_b
に設定し、次の文を入力します。
EXEC DBMS_SESSION.SET_IDENTIFIER('provider_b'); EXEC sysadmin_pg.provider_package.set_provider_context; SELECT * FROM oe.product_code_names;
次の出力が表示されます。
GROUP_A YEAR_A GROUP_B YEAR_B ---------------- ---------------- ---------------- ---------------- Groucho 2004 Zeppo 2008 Margaret Dumont 2003
ユーザーOE
で接続し、product_code_names
表を削除します。
CONNECT OE
Enter password: password
Connected.
DROP TABLE product_code_names;
ユーザーSYS
で接続し、この例で使用したアプリケーション・コンテキストとユーザーを削除します。
CONNECT SYS/AS SYSDBA
Enter password: password
Connected.
DROP CONTEXT provider_ctx;
DROP USER sysadmin_pg cascade;
DROP USER app_user
この項の内容は、次のとおりです。
Oracle Virtual Private Databaseセキュリティ・ポリシーは、アプリケーション内ではなく、データベース内で適用されます。したがって、ユーザーが異なるアプリケーションを使用してデータにアクセスしようとしても、Oracle Virtual Private Databaseセキュリティ・ポリシーを回避できません。データベースにセキュリティ・ポリシーを作成するもう1つの利点は、複数のアプリケーションで各セキュリティ・ポリシーを保持するのではなく、1箇所でセキュリティ・ポリシーを保持できることです。このため、Oracle Virtual Private Databaseは、アプリケーション・ベースのセキュリティよりも強力なセキュリティを提供し、所有権のコストもより低くなります。
データにアクセスしているアプリケーションに応じて、異なるセキュリティ・ポリシーを規定する必要がある場合があります。Order Entry(受注管理)およびInventory(在庫管理)の2つのアプリケーションが、両方ともorders
表にアクセスする場合を考えてみます。Inventoryアプリケーションで、製品の種類に基づいてアクセスを制限するポリシーを使用するとします。同時に、Order Entryアプリケーションでも、顧客番号に基づいてアクセスを制限するポリシーを使用するとします。
この場合、アプリケーションによるファイングレイン・アクセスの使用を分割する必要があります。分割しないと、2つのポリシーが自動的に連結され、目的とする結果が得られません。複数のポリシー・グループ、および特定のトランザクションに対して有効なポリシー・グループを判断する駆動アプリケーションのコンテキストを指定できます。また、データ・アクセスに対して必ず適用するデフォルト・ポリシーも指定できます。たとえば、ホスティングされたアプリケーションでは、データ・アクセスはサブスクライバIDによって制限されます。使用するグループの決定にアプリケーション・コンテキストを使用するポリシー・グループの作成方法の例は、「例: Oracle Virtual Private Databaseポリシー・グループの実装」を参照してください。
デフォルトでは、各ポリシーに対して最新の述語が使用されるように、ファイングレイン・アクセス・コントロール対応のオブジェクトに対する問合せでポリシー関数が実行されます。たとえば、問合せを午前8時から午後5時の間に限定する時間ベースのポリシー関数の場合は、正午にカーソルの実行を解析すると、その時点でこのポリシー関数が実行され、問合せに対してポリシーが再度参照されます。
自動再解析は、ポリシーを追加するときにDBMS_RLS.ADD_POLICY
設定のSTATIC_POLICY
をTRUE
に設定した場合は実行されません。この設定の場合、ポリシー関数は同じ述語を戻します。
デフォルトでは、データベースでの操作には、使用可能な最新のコミット済データが使用されます。フラッシュバック問合せ機能を使用すると、過去の特定時点におけるデータベースに対して問合せを実行できます。フラッシュバック問合せを使用するアプリケーションを作成するには、SQL問合せのAS OF
句を使用して、時間またはシステム変更番号(SCN)を指定し、指定した時間のコミット済データに対して問合せを実行します。DBMS_FLASHBACK
PL/SQLパッケージを使用することもできますが、コードの量が増えます。この方法では、同じ時点を参照する複数の操作を実行できます。
ただし、Oracle Virtual Private Databaseポリシーで保護されているデータベース・オブジェクトに対してフラッシュバック問合せを使用すると、現行のポリシーが過去のデータに適用されます。現行のOracle Virtual Private Databaseポリシーをフラッシュバック問合せのデータに適用すると、最新のビジネス・ポリシーが反映されるため、安全性が高まります。
この項の内容は、次のとおりです。
Oracle Virtual Private Databaseポリシーを使用して、Oracle Label Securityユーザー認可に基づいて列または行レベルのアクセス制御を提供できます。 一般に、次の手順を実行する必要があります。
Oracle Label Securityのポリシーを作成したら、保護する必要がある表にこのポリシーを適用しないでください。(作成した仮想プライベート・データベース・ポリシーによって自動的に処理されます。)SA_SYSDBA.CREATE_POLICY
プロシージャで、default_options
パラメータをNO_CONTROL
に設定します。
Oracle Label Securityのラベル・コンポーネントを作成し、通常どおりユーザーを認可します。
Oracle Virtual Private Databaseポリシーを作成する際には、次の操作を行います。
ポリシーについて作成するPL/SQLファンクションでは、Oracle Label SecurityのDOMINATES
ファンクションを使用して、ユーザーの認可を手順2で作成したラベルと比較します。(支配ファンクションの詳細は、『Oracle Label Security管理者ガイド』を参照してください。)DOMINATES
ファンクションにより、ユーザーの認可が比較で使用されたラベルと等しい、またはラベルより機密性が高いかどうかが判別されます。ユーザー認可が通過した場合、ユーザーは列に対するアクセス権を付与されます。通過しない場合、ユーザーはアクセスを拒否されます。
仮想プライベート・データベース・ポリシー定義で、保護する必要がある表にこのファンクションを適用します。DBMS_RLS.ADD_POLICY
プロシージャで、機密性の高い列(sec_relevant_cols
パラメータ)および列のマスク(sec_relevant_cols_opt
パラメータ)機能を使用して、Oracle Label Securityユーザー認可に基づいて列を表示または非表示にします。
この方法を示した例については、次のOracle Technology Networkのサイトにアクセスしてください。
http://www.oracle.com/technology/deploy/security/database-security/label-security/ols_cs1.html
Oracle Virtual Private DatabaseおよびOracle Label Securityを使用する場合は、次の例外に注意してください。
When データのエクスポート時、Oracle Virtual Private DatabaseおよびOracle Label Securityのポリシーはダイレクト・パス・エクスポート操作では規定されません。ダイレクト・パス・エクスポート操作では、Oracle Databaseはディスクからバッファ・キャッシュにデータを読み込み、行をエクスポート・クライアントに直接転送します。ダイレクト・パス・エクスポート操作の詳細は、『Oracle Databaseユーティリティ』を参照してください。
Oracle Virtual Private DatabaseおよびOracle Label Securityのポリシーは、SYSスキーマのオブジェクトに適用できません。SYS
ユーザーおよびデータベースにDBA権限でアクセスするユーザー(CONNECT/AS SYSDBA
など)の場合、それらのユーザーのアクションにOracle Virtual Private DatabaseまたはOracle Label Securityのポリシーは適用されません。したがって、データベース・ユーザーSYS
は、データベースからデータを抽出するために使用するエクスポート・モード、アプリケーションまたはユーティリティに関係なく、常にOracle Virtual Private DatabaseまたはOracle Label Securityの規定対象から除外されます。
ただし、SYSDBA
のアクションは、インストール時に監査を有効にし、監査証跡をオペレーティング・システムの保護位置に格納するように指定することによって監査できます。詳細は、「SYS管理ユーザーの監査」を参照してください。SYS
ユーザーはOracle Database Vaultを使用して詳細に監視できます。
EXEMPT ACCESS POLICY権限を直接的またはデータベース・ロールを介して付与されているデータベース・ユーザーは、Oracle Virtual Private Databaseの規定対象から除外されます。システム権限EXEMPT ACCESS POLICY
を持つユーザーは、すべてのSELECT
またはDML操作(INSERT
、UPDATE
およびDELETE
)において、ファイングレイン・アクセス・コントロール・ポリシーの対象から除外されます。これによって、インストールや、SYS
以外のスキーマを介したデータベースのインポートとエクスポートなどの管理アクティビティが使いやすくなります。
ただし、ポリシーを規定する次のオプションは、EXEMPT ACCESS POLICY
が付与されている場合も規定されます。
INSERT_CONTROL
、UPDATE_CONTROL
、DELETE_CONTROL
、WRITE_CONTROL
、LABEL_UPDATE
およびLABEL_DEFAULT
Oracle Label SecurityのポリシーにALL_CONTROL
オプションを指定した場合は、READ_CONTROL
およびCHECK_CONTROL
以外のすべてが規定の対象として適用されます。
EXEMPT ACCESS POLICY
は、ファイングレイン・アクセス・コントロールを無効にするため、この権限は、ファイングレイン・アクセス・コントロールの規定を回避する正当な理由を持つユーザーに対してのみ付与する必要があります。この権限はWITH ADMIN OPTION
を使用して付与しないでください。これを使用すると、ユーザーが他のユーザーにEXEMPT ACCESS POLICY
権限を譲渡して、ファイングレイン・アクセス・コントロールを回避する権限が伝播する可能性があります。
注意:
|
Oracle Virtual Private Databaseは、次のタイプのユーザー・モデルで使用できます。
アプリケーション・ユーザーがデータベース・ユーザーでもある場合。 Oracle Databaseでは、ユーザーがデータベース・ユーザーか、データベースに認識されないアプリケーション・ユーザーかに関係なく、アプリケーションはユーザーごとにファイングレイン・アクセス・コントロールを規定できます。アプリケーション・ユーザーがデータベース・ユーザーでもある場合、Oracle Virtual Private Databaseは次のように規定されます。ユーザーがデータベースに接続すると、アプリケーションは各セッションに対するアプリケーション・コンテキストを設定します(様々な種類のユーザー・セッション・データを取得するための多くのパラメータを提供する、デフォルトのUSERENV
アプリケーション・コンテキスト・ネームスペースを使用できます)。各セッションは異なるユーザー名で開始されるため、各ユーザーに対して異なるファイングレイン・アクセス・コントロール条件を規定できます。
OCIまたはThick JDBCを使用したプロキシ認証。 プロキシ認証を使用すると、ユーザーごとに異なるファイングレイン・アクセス・コントロールができます。これは、各セッション(OCIまたはThick JDBC)が独自のアプリケーション・コンテキストを持つ個別のデータベース・セッションであるためです。
エンタープライズ・ユーザー・セキュリティに統合されているプロキシ認証。 エンタープライズ・ユーザー・セキュリティを使用してプロキシ認証を統合している場合は、Oracle Internet Directoryからユーザー・ロールおよび他の属性を取得してOracle Virtual Private Databaseポリシーを規定できます(また、グローバルに初期化されたアプリケーション・コンテキストもディレクトリから取得できます)。
ユーザーがOne Big Application Userとして接続する場合。 すべてのユーザーのかわりにシングル・ユーザーとしてデータベースに接続するアプリケーションでは、ユーザーごとのファイングレイン・アクセス・コントロールを規定できます。この単一セッションのユーザーは、One Big Application Userと呼ばれます。 ただし、アプリケーション開発者は、そのセッションのコンテキスト内で、個別のアプリケーション・ユーザー(たとえば、REALUSER
)を表すグローバル・アプリケーション・コンテキスト属性を作成できます。すべてのデータベース・セッションおよびすべての監査レコードはOne Big Application Userに対して作成されますが、各セッションはエンド・ユーザーに応じて異なる属性を保持できます。このモデルは、ユーザーの数が限定されていて、セッションが再利用されないアプリケーションに最適です。このモデルの場合、各セッションは同一のデータベース・ユーザーとして作成されるため、ロールやデータベース監査の範囲が限定されます。グローバル・アプリケーション・コンテキストの詳細は、「グローバル・アプリケーション・コンテキストの使用」を参照してください。
Webベースのアプリケーション。 Webベースのアプリケーションには、通常は何百人ものユーザーがいます。多数のユーザー要求に対するデータの取得をサポートするためにデータベースへの接続が持続的に行われる場合でも、このような接続は特定のWebベース・ユーザーに固有のものではありません。通常、Webベースのアプリケーションはスケーラビリティを提供するために、ユーザーごとに異なるセッションを保持するのではなく、接続を設定して再利用します。たとえば、WebユーザーJaneおよびAjitが中間層アプリケーションに接続すると、このアプリケーションは、2人のユーザーのかわりに、使用するデータベース・セッションを1つ確立します。通常、JaneもAjitもデータベースには認識されません。アプリケーションが接続するユーザー名を切り替えるため、どの時点でも、セッションを使用しているのはJaneまたはAjitのいずれかです。
Oracle Virtual Private Databaseを使用すると、複数のグローバル・アプリケーション・コンテキストにアクセスする複数の接続が可能になり、接続プーリングが促進されます。この機能によって、個別ユーザー・セッションごとに別々のアプリケーション・コンテキストを確立する必要がなくなります。
表7-3に、Oracle Virtual Private Databaseをユーザー・モデルに適用する方法の要約を示します。
表7-3 様々なユーザー・モデルでのOracle Virtual Private Database
ユーザー・モデル | 個別のデータベース接続 | ユーザーごとの個別アプリケーション・コンテキスト | 単一データベース接続 | アプリケーションによるユーザー名の切替え |
---|---|---|---|---|
アプリケーション・ユーザーがデータベース・ユーザーでもある場合 |
あり |
あり |
なし |
なし |
OCIまたはThick JDBCを使用したプロキシ認証 |
あり |
あり |
なし |
なし |
エンタープライズ・ユーザー・セキュリティに統合されているプロキシ認証脚注1 |
なし |
なし |
あり |
あり |
One Big Application User |
なし |
なし脚注2 |
なし |
あり2 |
Webベースのアプリケーション |
なし |
なし |
あり |
あり |
脚注1 ユーザー・ロールとその他の属性(グローバルに初期化されたアプリケーション・コンテキストも含む)は、Oracle Internet Directoryから取得してOracle Virtual Private Databaseを規定できます。
脚注2 アプリケーション開発者は、個別アプリケーション・ユーザー(たとえば、REALUSER
)を表すグローバル・アプリケーション・コンテキスト属性を作成できます。その後、この属性を使用して、各セッション属性を制御したり、監査することができます。
表7-4に、Oracle Virtual Private Databaseポリシーに関する情報の検索に使用できるデータ・ディクショナリ・ビューをリストします。これらのビューの詳細は、『Oracle Databaseリファレンス』を参照してください。
表7-4 VPDポリシーに関する情報を表示するデータ・ディクショナリ・ビュー
ビュー | 説明 |
---|---|
|
現行ユーザーがアクセス可能なオブジェクトに対するすべてのOracle Virtual Private Databaseセキュリティ・ポリシーが表示されます。 |
|
現行ユーザーがアクセス可能なシノニム、表およびビューに定義されている駆動コンテキストが表示されます。駆動コンテキストは、Oracle Virtual Private Databaseポリシーで使用されるアプリケーション・コンテキストです。 |
|
現行ユーザーがアクセス可能なシノニム、表およびビューに定義されているOracle Virtual Private Databaseポリシー・グループが表示されます。 |
|
現行ユーザーがアクセス可能な表とビューに対するセキュリティ・ポリシーのセキュリティ関連列が表示されます。 |
|
データベース内のすべてのOracle Virtual Private Databaseセキュリティ・ポリシーが表示されます。 |
|
データベース内のすべてのポリシー・グループが表示されます。 |
|
データベース内のすべての駆動コンテキストが表示されます。このビューの列は、 |
|
データベース内のすべてのセキュリティ・ポリシーのセキュリティ関連列が表示されます。 |
|
現行ユーザーが所有するオブジェクトに対応付けられたすべてのOracle Virtual Private Databaseセキュリティ・ポリシーが表示されます。このビューには |
|
現行ユーザーが所有するシノニム、表およびビューに定義されている駆動コンテキストが表示されます。このビューの列は、 |
|
現行ユーザーが所有している表とビューに対するセキュリティ・ポリシーのセキュリティ関連列が表示されます。このビューの列は、 |
|
現行ユーザーが所有するシノニム、表およびビューに定義されているポリシー・グループが表示されます。このビューには |
|
現在、ライブラリ・キャッシュにキャッシュされているカーソルに対応付けられた、すべてのファイングレイン・セキュリティ・ポリシーと述語が表示されます。このビューは、SQL文に適用されたポリシーを検索するのに便利です。 |