Oracle Virtual Private Databaseでは、ユーザーが入力するSQL文に追加される動的WHERE句に基づいて、データへのアクセスを制限します。
WHERE句を動的に追加することができます。 Oracle Virtual Private Database(VPD)では、ユーザーが実行する任意のSQL文にWHERE句を動的に追加することができます。
WHERE句により、ユーザーのIDに基づいて、ユーザーがアクセスを許可されているデータがフィルタ処理されます。
この機能では、データベースに問い合せるすべてのSQL文に対してWHERE句を強制するポリシーを作成し、データへのアクセスを行または列レベルで制限します。WHERE句では、セキュリティ・ポリシーを通過したIDを持つ、すなわち、保護する対象のデータへのアクセス権を持つユーザーのみが許可されます。VPDポリシーはデータベースの表またはビュー・レベルで作成および管理しますが、これはデータベースにアクセスするアプリケーションを変更しないことを意味します。
マルチテナント環境では、各仮想プライベート・データベース・ポリシーは現在のプラガブル・データベース(PDB)にのみ適用されます。
Oracle仮想プライベート・データベースのポリシーには次のコンポーネントがあり、通常はセキュリティ管理者のスキーマに作成されます。
仮想プライベート・データベースの表に影響するSQL文に動的WHERE句を追加するPL/SQLファンクション。たとえば、PL/SQLファンクションにより、次のSELECT文が変換されます。
SELECT * FROM ORDERS;
次のようになります。
SELECT * FROM ORDERS WHERE SALES_REP_ID = 159;
この例では、ユーザーは営業担当者159の受注のみを表示できます。このWHERE句の生成に使用されるPL/SQLファンクションは次のようになります。
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; /
この例では、次のようになります。
schema_varおよびtable_var: スキーマ名(OE)および表名(ORDERS)を格納するパラメータを作成します。(表に使用する2つ目のパラメータtable_varは、ビューとシノニムにも使用できます。)最初にスキーマのパラメータを作成し、次に表、ビュー、またはシノニム・オブジェクトのパラメータを作成します。ファンクション自体がOEスキーマまたはそのORDERS表を指定するのではないことに注意してください。ユーザーが作成する仮想プライベート・データベースのポリシーがこれらのパラメータを使用して、OE.ORDERS表を指定します。
RETURN VARCHAR2: WHERE述語句に使用される文字列を返します。
IS ... RETURN return_val: WHERE SALES_REP_ID = 159述語の作成が含まれます。
WHERE句は、ユーザーのセッション情報(ユーザーIDなど)に基づいてユーザー情報をフィルタ処理するよう構成できます。これを行うには、アプリケーション・コンテキストを作成します。アプリケーション・コンテキストを使用して、データベースとデータベース以外の両方のユーザーを認証できます。アプリケーション・コンテキストは、名前と値のペアです。次に例を示します。
SELECT * FROM oe.orders
WHERE sales_rep_id = SYS_CONTEXT('userenv','session_user');
この例では、WHERE句でSYS_CONTEXT PL/SQLファンクションを使用して、userenvコンテキストによって示されるユーザーのセッションID(session_user)を取得しています。アプリケーション・コンテキストの詳細は、Oracle Databaseセキュリティ・ガイドを参照してください。
パッケージにポリシーを追加する方法。DBMS_RLS.ADD_POLICYファンクションを使用して、パッケージにポリシーを追加します。DBMS_RLS PL/SQLパッケージを使用するには、そのPL/SQLパッケージに対するEXECUTE権限を付与される必要があります。ユーザーSYSがDBMS_RLSパッケージを所有しています。
データベース・レベルで行レベルのセキュリティを強制する方法は、アプリケーション・プログラム・レベルでセキュリティを強制した場合に比べて多くのメリットがあります。データを保護する場所であるデータベース自体にセキュリティ・ポリシーを実装できるため、様々な方法でアクセスされた場合でも攻撃を受ける可能性が低くなります。このセキュリティ層によって保護されるデータに対してユーザー(または侵入者)がどれだけアクセスを試みても、セキュリティは存在し、強制されます。データベースに接続するすべてのアプリケーションでポリシーを維持する必要はなく、1箇所(データベース)のみでポリシーを維持できるため、メンテナンス費も低く抑えられます。固有のDML操作に対してポリシーを作成できるため、非常に柔軟性の高いポリシーを適用できます。
関連項目:
Oracle Virtual Private Databaseの詳細は、『Oracle Databaseセキュリティ・ガイド』を参照してください
このチュートリアルでは、個々のデータ・アクセスがロールに基づく2人のユーザーを作成します。
OE.ORDERS表へのアクセスが必要な従業員のアカウントの作成です。 sec_adminセキュリティ管理者アカウントにより、セキュリティ管理者が実行できるタスクを実行できます。sec_adminアカウント・ユーザーには、DBMS_RLSパッケージを使用するための権限が必要です。f_policy_ordersポリシーは、ORDERS表に問合せを行うユーザーのフィルタリングに使用される、ポリシーを定義するPL/SQLファンクションです。 accesscontrol_orders)を作成し、それをORDERS表にアタッチします。 ORDERS表からのデータの選択を試すことでポリシーをテストできます。 ユーザーのデータ・アクセスを制限するには、Oracle Virtual Private Database (VPD)ポリシーを作成して必要な制限を定義する必要があります。
このチュートリアルでは、Order Entryデータベース(OE)のORDERS表を使用します。
この表には、次の情報が含まれます。
Name Null? Type ---------------- -------- --------------------------------- ORDER_ID NOTNULL NUMBER(12) ORDER_DATE NOTNULL TIMESTAMP(6) WITH LOCAL TIME ZONE ORDER_MODE VARCHAR2(8) CUSTOMER_ID NOTNULL NUMBER(6) ORDER_STATUS NUMBER(2) ORDER_TOTAL NUMBER(8,2) SALES_REP_ID NUMBER(6) PROMOTION_ID NUMBER(6)
作成する仮想プライベート・データベース・ポリシーは、PL/SQLファンクションに関連付けられます。VPDポリシーはPL/SQLファンクションまたはプロシージャによって制御されるため、アクセスを制限するポリシーを様々な方法で設計できます。このチュートリアルでは、直属の上司が誰であるかに基づいて従業員のアクセスを制限するファンクションを作成します。このファンクションでは、顧客のIDに基づいて顧客のアクセスが制限されます。
データベース管理者やアプリケーション・アカウントとは別のデータベース・アカウントにVPDポリシーを格納する場合があります。このチュートリアルでは、「チュートリアル: セキュア・アプリケーション・ロールの作成」で作成したsec_adminアカウントを使用して、VPDポリシーを作成します。アプリケーション表とVPDポリシーを分けることで、セキュリティを高めます。
行データの機密性に基づいてアクセスを制限する必要がある場合、Oracle Label Security (OLS)を使用します。OLSを使用すると、様々なレベルのセキュリティでデータを分類できます。この場合、行内のデータにアクセスできるユーザーをレベルごとに設定できます。この方法では、データのアクセス制御は、ユーザーの権限ではなくデータ自体に焦点が当てられます。詳細は、「Oracle Label Securityによる行レベルのセキュリティの強制」を参照してください。
最初の手順は、OE.ORDERS表へのアクセスが必要な従業員のアカウントの作成です。
従業員ユーザー・アカウントを作成するには、次のようにします。
Enterprise Managerで、ターゲット・データベースのデータベース・ホームページに、SYSDBA管理権限を持つユーザーSYSとしてアクセスします。
詳細は、Oracle Database 2日でデータベース管理者を参照してください。
「管理」メニューから、「セキュリティ」を選択し、「ユーザー」を選択します。
ユーザー・ページで、「作成」をクリックします。
ユーザーの作成ページで、次の情報を入力します。
名前: LDORAN(Louise Doranのユーザー・アカウントを作成するため)
プロファイル: DEFAULT
認証: Password
「パスワードの入力」および「パスワードの確認」: パスワードの作成要件に示されている要件を満たすパスワードを入力します。
デフォルト表領域: USERS
一時表領域: TEMP
ステータス: Unlocked
「オブジェクト権限」タブを選択します。
「オブジェクト・タイプの選択」リストから「表」を選択し、次に「追加」をクリックします。
表オブジェクト権限の追加ページで、表オブジェクトの選択フィールドに次のテキストを入力します。
OE.ORDERS
このテキストにはスペースを含めないでください。
「使用可能な権限」リストで「SELECT」を選択し、「移動」をクリックして「選択した権限」リストに移動します。「OK」をクリックします。
OE.ORDERSのSELECT権限がリストされた状態で「ユーザーの作成」ページが表示されます。
「OK」をクリックします。
ユーザー・ページが表示され、ユーザーldoranが「ユーザー名」列にリスト表示されます。
ユーザーLDORANの選択ボタンを選択してから、「アクション」リストで「類似作成」を選択します。次に「実行」をクリックします。
ユーザーの作成ページで、次の情報を入力します。
名前: LPOPP(財務管理者のLuis Poppのユーザー・アカウントを作成するため)
「パスワードの入力」および「パスワードの確認」: パスワードの作成要件に示されている要件を満たすパスワードを入力します。
「OK」をクリックします。
両方の従業員アカウントが作成され、それらのアカウントには同じ権限が付与されています。ユーザーLPOPPの権限を確認すると、ユーザーLDORANの権限と同じであることがわかります。この段階で、OE.ORDERS表に対してSELECT文を実行すると、どちらのユーザーでも表のすべてのデータを参照できます。
sec_adminセキュリティ管理者アカウントにより、セキュリティ管理者が実行できるタスクを実行できます。
チュートリアル: セキュア・アプリケーション・ロールの作成で、そのチュートリアルのsec_adminを作成しました。このチュートリアルでも、このアカウントを使用できます。
このアカウントをまだ作成していない場合は、手順2: セキュリティ管理者アカウントを作成するの手順に従ってsec_adminを作成してください。
sec_adminアカウント・ユーザーには、DBMS_RLSパッケージを使用するための権限が必要です。
このパッケージはSYSが所有しているため、このパッケージ権限をsec_adminに付与するには、SYSとしてログオンする必要があります。また、sec_adminユーザーには、OEスキーマのCUSTOMERS表およびHRスキーマのEMPLOYEES表に対するSELECT権限も必要です。
sec_adminにDBMS_RLSパッケージを使用する権限を付与するには、次のようにします。
Enterprise Managerで、データベース・ホームページにアクセスし、SYSDBAロールを持つユーザーSYSとしてアクセスしていることを確認します。
詳細は、Oracle Database 2日でデータベース管理者を参照してください。
「スキーマ」メニューから、「ユーザー」を選択します。
ユーザー・ページでSEC_ADMINユーザーを選択し、ユーザーの表示ページで「編集」をクリックします。
ユーザーの編集ページで「オブジェクト権限」をクリックします。
「オブジェクト・タイプの選択」リストから「パッケージ」を選択し、次に「追加」をクリックします。
パッケージ・オブジェクト権限の追加ページのパッケージ・オブジェクトの選択で、sec_adminにDBMS_RLSパッケージのアクセス権を付与するためにSYS.DBMS_RLSと入力します。
「使用可能な権限」で「EXECUTE」を選択し、「移動」をクリックして「選択した権限」リストに移動します。
「OK」をクリックします。
ユーザーの編集ページの「オブジェクト・タイプの選択」リストから「表」を選択し、「追加」をクリックします。
表オブジェクト権限の追加ページの表オブジェクトの選択フィールドで、sec_adminにHR.EMPLOYEES表のアクセス権を付与するためにHR.EMPLOYEESと入力します。
「使用可能な権限」で「SELECT」を選択し、「移動」をクリックして「選択した権限」リストに移動します。
「OK」をクリックします。
ユーザーの編集ページが表示されます。これはユーザーsec_adminにHR.EMPLOYEES表およびDBMS_RLS PL/SQLパッケージへのオブジェクト権限があることを示しています。どちらのオブジェクトに対しても付与オプションを選択していないことを確認します。
「適用」をクリックします。
すべての変更内容(ここでは、2つのオブジェクト権限の追加)が、sec_adminユーザー・アカウントに適用されます。
f_policy_ordersポリシーは、ORDERS表に問合せを行うユーザーのフィルタリングに使用される、ポリシーを定義するPL/SQLファンクションです。
ユーザーをフィルタリングするために、ポリシー・ファンクションでは、データベースにログイン中のユーザーに関するセッション情報を取得するSYS_CONTEXT PL/SQLファンクションが使用されます。
アプリケーション・コンテキストとパッケージを作成するには、次のようにします。
「ログアウト」を選択し、データベース・インスタンスからログアウトします。
「確認」ダイアログ・ボックスで「(データベース・インスタンス)のログアウト」を選択し、「ログアウト後にログイン・ページを表示します。」チェック・ボックスを選択します。「ログアウト」をクリックします。
NORMALロールを使用するユーザーsec_adminとしてログインします。
「スキーマ」メニューから、「プログラム」、「ファンクション」を選択します。
データベース・ログイン・ページで、NORMALロールが選択されているユーザーsec_adminとしてログインします。
「スキーマ」メニューから、「プログラム」、「ファンクション」を選択します。
ファンクション・ページで、「オブジェクト・タイプ」メニューが「ファンクション」に設定されていることを確認し、「作成」をクリックします。
ファンクションの作成ページで、次の情報を入力します。
名前: F_POLICY_ORDERS
スキーマ: SEC_ADMIN
ソース: 表示された空のファンクション・コードを削除してから、次のコードを入力し(ただしコード左側の行番号は入力しない)、ログオンしたユーザーが営業担当者かどうかをチェックするファンクションを作成します。
f_policy_ordersファンクションはSYS_CONTEXT PL/SQLファンクションを使用してユーザーに関するセッション情報を取得します。次に、この情報を、sec_adminがSELECT権限を持つHR.EMPLOYEES表のそのユーザーのジョブIDと比較します。 (schema in varchar2,
tab in varchar2)
return varchar2
as
v_job_id varchar2(20);
v_user varchar2(100);
predicate varchar2(400);
begin
v_job_id := null;
v_user := null;
predicate := '1=2';
v_user := lower(sys_context('userenv','session_user'));
select lower(job_id) into v_job_id from hr.employees
where lower(email) = v_user;
if v_job_id='sa_rep' then
predicate := '1=1';
else
null;
end if;
return predicate;
exception
when no_data_found then
null;
end;
次のように指定します。
(schema in varchar2, tab in varchar2): 保護する必要があるスキーマ(schema)および表(tab)のパラメータを定義します。このファンクションはOE.ORDERS表を指定しません。「手順5: ACCESSCONTROL_ORDERS仮想プライベート・データベース・ポリシーを作成する」で作成したACCESSCONTROL_ORDERSポリシーによりこれらのパラメータが使用され、OEスキーマとORDERS表が指定されます。最初にschemaパラメータを作成し、その後にtabパラメータを作成してください。
return varchar2: WHERE述語句に使用される文字列を返します。この戻り値のデータ型としてはVARCHAR2が常に使用されます。
as ... predicate: ジョブID、ログオンしたユーザーのユーザー名、および述語の値を格納する変数を定義します。
begin ... return predicate: v_job_idおよびv_userの設定のためのBEGIN句で開始する、WHERE述語の作成が含まれます。
v_job_id varchar2(20)およびv_user varchar2(100): v_job_id変数とv_user変数をnullに、およびpredicate変数を1=2 (つまり、false値)に設定します。この段階では、これらの変数がselect lower(job_id) into v_job_idで開始するテストに通るまで、WHERE述語を生成できません。
v_user := lower(sys_context...: SYS_CONTEXTファンクションを使用してユーザーのセッション情報を取得し、v_user変数に書き込みます。
select lower(job_id) into v_job_id...end if: ユーザーのジョブIDを比較して、ログオンしたユーザーが営業担当者かどうかを確認します。ログオンしたユーザーのジョブIDがsa_rep(営業担当者)である場合は、predicate変数が1=1に設定されます。つまりユーザーは営業担当者であることになり、テストに通ります。
return predicate: WHERE role_of_user_logging_on IS "sa_rep"となるWHERE述語を返します。このWHERE述語は、ユーザーLDORANとLPOPPがOE.ORDERS表に対して発行するSELECT文に追加されます。
exception ... null: 適切な権限のないユーザーがログオンした場合のためにEXCEPTION句を提供します。
「OK」をクリックします。
次に、仮想プライベート・データベース・ポリシー(accesscontrol_orders)を作成し、それをORDERS表にアタッチします。
このポリシーには、パフォーマンスを向上させるためにCONTEXT_SENSITIVEパラメータを追加します。これによりOracle Databaseは、アプリケーション・コンテキストの内容が変わった場合にのみ、f_policy_ordersファンクションを実行するようになります(このケースでは、新しいユーザーがログオンした場合)。Oracle Databaseは、ユーザーがORDERS表でSQL SELECT文を実行したときのみポリシーをアクティブにします。このポリシーはINSERT、UPDATEおよびDELETE文を許可しないので、ユーザーはこれらの操作を実行できません。
ACCESSCONTROL_ORDERS仮想プライベート・データベース・ポリシーを作成するには、次のようにします。
「セキュリティ」メニューから、「仮想プライベート・データベース・ポリシー」を選択します。
仮想プライベート・データベース・ポリシー・ページで、「作成」をクリックします。
ポリシーの作成ページの「一般」で、次の情報を入力します。
ポリシー名: ACCESSCONTROL_ORDERS
オブジェクト名: OE.ORDERS
ポリシー・タイプ: 「CONTEXT_SENSITIVE」を選択します。
このタイプは、最後にカーソルを使用して以降のコンテキストの変更を検出した場合、文実行時にポリシー・ファンクションを再評価します。複数のクライアントが1つのデータベース・セッションを共有するセッション・プーリングの場合、クライアント切替え時に中間層でコンテキストをリセットする必要があります。Oracle Databaseは、このポリシー・タイプのファンクションにより戻された値をキャッシュしません。常に文の解析時にポリシー・ファンクションを実行します。CONTEXT_SENSITIVEポリシー・タイプは1つのオブジェクトのみに適用されます。
ポリシー・タイプを有効にするには、「有効」ボックスを選択します。
「ポリシー・ファンクション」で次の入力を行います。
ポリシー・ファンクション: ポリシーの述語を生成するファンクション名(この場合はSEC_ADMIN.F_POLICY_ORDERS)を入力します。
長い述語: このボックスは選択しないでください。
通常は、32KBまでの長さの述語を返すためにこのボックスを選択します。このボックスを選択しないと、Oracle Databaseは述語を4000バイトに制限します。
「強制」でSELECTオプションを選択しますが、その他にすでに選択されているオプションがあれば選択解除します。
「セキュリティ関連列」のオプションは、いずれも選択しないでください。
「OK」をクリックします。
「仮想プライベート・データベース・ポリシー」ページのポリシーのリストにACCESSCONTROL_ORDERSポリシーが表示されます。
Enterprise Managerからログアウトしないでください。
この段階で、それぞれのユーザーとしてログオンし、ORDERS表からのデータの選択を試すことでポリシーをテストできます。
ACCESSCONTROL_ORDERSポリシーをテストするには、次のようにします。
SQL*Plusを起動します。
コマンド・プロンプトで、次のコマンドを入力してSQL*Plusを起動し、販売担当者Louise Doran(ユーザー名はldoran)としてログインします。
sqlplus ldoran
Enter password: password
SQL*Plusが起動し、デフォルトのデータベースに接続してから、プロンプトが表示されます。
SQL*Plusの開始の詳細は、Oracle Database 2日でデータベース管理者を参照してください。
次のSELECT文を入力します。
SELECT COUNT(*) FROM OE.ORDERS;
Louiseに関する次のような結果が表示されます。表示のとおり、LouiseはOE.ORDERS表のすべての注文にアクセスできます。
COUNT(*)
--------
105
財務管理者のLuis Poppとして接続します。
CONNECT lpopp
Enter password: password
次のSELECT文を入力します。
SELECT COUNT(*) FROM OE.ORDERS;
Popp氏は営業担当者ではないため、OE.ORDERS表のデータにアクセスできず、次のような結果が表示されます。Popp氏にはアクセス権がないので、Oracle Databaseから0行へのアクセスのみが許可されます。
COUNT(*)
--------
0
SQL*Plusを終了します。
EXIT
コンポーネントが不要になった場合、このチュートリアルで作成したコンポーネントを削除できます。
sec_adminによって作成されたデータ構造を削除するには、Enterprise Managerを使用できます。sec_adminのDBMS_RLSパッケージに対するEXECUTE権限を取り消すには、Enterprise Managerを使用できます。ユーザーsec_adminによって作成されたデータ構造を削除するには、Enterprise Managerを使用できます。
sec_adminで作成したデータ構造を削除するには、次のようにします。
Enterprise Managerで、sec_adminユーザーとしてログインしていることを確認します。
「セキュリティ」メニューから、「仮想プライベート・データベース・ポリシー」を選択します。
仮想プライベート・データベース・ポリシー・ページの「検索」で、「実行」をクリックします。
スキーマ名: OE
オブジェクト名: ORDERS
ポリシー名: %
作成したポリシーのACCESSCONTROL_ORDERSが表示されます。
「ACCESSCONTROL_ORDERS」を選択し、「削除」をクリックします。
「確認」ページで「はい」をクリックします。
「スキーマ」メニューから、「プログラム」、「ファンクション」を選択します。
F_POLICY_ORDERSファンクションが表示されていない場合は、「検索」フィールドを使用して検索します。
F_POLICY_ORDERSファンクションの選択ボタンを選択し、「削除」をクリックします。
「確認」ウィンドウで「OK」をクリックします。
ユーザー・アカウントを削除するには、Enterprise Managerを使用できます。
ユーザー・アカウントを削除するには、次のようにします。
Enterprise Managerで「ログアウト」を選択し、データベース・インスタンスからログアウトします。
NORMALロールが選択されているユーザーSYSTEMとしてログインします。
データベース・ホームページの「スキーマ」メニューから、「ユーザー」を選択します。
ユーザー・ページで次の各ユーザーを選択し、「削除」をクリックしてそれらを削除します。
LDORAN
LPOPP
sec_adminは削除しないでください。このマニュアルの以降のチュートリアルで、このアカウントが必要になります。
ユーザーsec_adminのDBMS_RLSパッケージに対するEXECUTE権限を取り消すには、Enterprise Managerを使用できます。
ユーザーsec_adminのDBMS_RLSパッケージに対するEXECUTE権限を取り消すには、次のようにします。
Enterprise Managerで「ログアウト」を選択し、データベース・インスタンスからログアウトします。
SYSDBAロールが選択されているSYS管理ユーザーとしてログインします。
「スキーマ」メニューから、「ユーザー」を選択します。
ユーザー・ページでユーザー「SEC_ADMIN」を選択し、「編集」をクリックします。
「オブジェクト権限」タブを選択します。
オブジェクト権限のリストから、HR.EMPLOYEES表に対するSELECT権限の項目を選択します。
「削除」をクリックします。
オブジェクト権限のリストから、DBMS_RLSパッケージに対するEXECUTE権限の項目を選択します。
「削除」をクリックします。
「適用」をクリックします。
Enterprise Managerを終了します。