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を終了します。