4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Oracle Databaseのアクセス制御 - VPDの仕組みとDeep Data Securityとの違い -

4
Last updated at Posted at 2026-09-04

ここしばらくは26aiでリリースされた新しいアクセス制御 Deep Data Securityの機能についての解説や使い方を紹介してきました。一方で、従来からOracle Databaseに行・列レベルのアクセス制御の機能としてVPD (Virtual Private Database)があるのですが、それとの違い・使い分けについて少し考えてみたいと思います。

まずVPDの機能についてですが、こちらのスライドをご覧ください。
VPDは、Oracle Database 8iの頃からある伝統的な機能で、データベース・ユーザーのセッション情報を基にしてWHERE句を透過的に付加するというものです。セッション情報にはユーザ名やIPアドレス、利用プログラムなどの情報が格納されていますが、それをSYS_CONTEXT関数で取り出し、VPDのポリシーとして利用します。

スクリーンショット 2026-09-04 101313.png

実際には下記のようにPL/SQLでVPDポリシーを表に対して作成する必要があります。20年以上前に設計された機能なので、設定方法は正直洗練されていませんが、グローバルでは軍事や公共機関などの最重要データベースのアクセス制御で使われている実績多数の信頼性の高い機能です。

スクリーンショット 2026-09-03 224831.png

VPDは、データベースユーザーを対象とします。Deep Data Securityは、エンドユーザーが対象なのでここが大きな違いです。とはいえ、VPDでアプリケーションユーザーの情報を使ったアクセス制御をしたいというのは昔からある要件なので、その場合は、Client Identifierまたはアプリケーション・コンテキストを使います。
下記のように、アプリケーションコード内で明示的にDBセッションの中にアプリケーション情報を格納するというものです。WebLogicや一部のアプリケーションでは既にWebUIで連携実装できるものもありますが、基本的にはコードを改修して、アプリの情報をDBセッションに伝播し、それを基にVPDのポリシーに利用します。
Deep Data Securityでは、エンドユーザー・セキュリティ・コンテキストなどでこの情報の伝播を自動的に行い、データ権限のポリシー設定で簡単に実装できるようになっています。

スクリーンショット 2026-09-04 005348.png

では、実際にこのVPDの機能を試す手順を紹介します。VPDは、Enterprise Editionの機能なので、お手元にある19cや26aiのOracle Databaseで簡単に試していただくことが可能です。

VPDの実行手順

①DBユーザーごとに自分の行だけを表示

表とユーザーの作成

CREATE TABLE orders_by_db_user (
  order_id     NUMBER PRIMARY KEY,
  db_username  VARCHAR2(128),
  customer     VARCHAR2(30),
  order_amount NUMBER
);

INSERT INTO orders_by_db_user VALUES (1001, 'TOKYO_USER', 'TOKYO_STORE', 120000);
INSERT INTO orders_by_db_user VALUES (1002, 'OSAKA_USER', 'OSAKA_STORE', 85000);
INSERT INTO orders_by_db_user VALUES (1003, 'NAGOYA_USER', 'NAGOYA_STORE', 64000);
COMMIT;

CREATE USER tokyo_user IDENTIFIED BY password;
CREATE USER osaka_user IDENTIFIED BY password;

GRANT CREATE SESSION TO tokyo_user;
GRANT CREATE SESSION TO osaka_user;

GRANT SELECT ON orders_by_db_user TO tokyo_user;
GRANT SELECT ON orders_by_db_user TO osaka_user;

VPDポリシーの作成

CREATE OR REPLACE FUNCTION orders_user_pred (
  p_schema IN VARCHAR2,
  p_object IN VARCHAR2
)
RETURN VARCHAR2
AUTHID DEFINER
AS
BEGIN
  RETURN q'[
    db_username = SYS_CONTEXT('USERENV', 'SESSION_USER')
  ]';
END;
/

BEGIN
  DBMS_RLS.ADD_POLICY(
    object_schema   => 'ADMIN',
    object_name     => 'ORDERS_BY_DB_USER',
    policy_name     => 'ORDERS_USER_POLICY',
    function_schema => 'ADMIN',
    policy_function => 'ORDERS_USER_PRED',
    statement_types => 'SELECT',
    policy_type     => DBMS_RLS.DYNAMIC
  );
END;
/

TokyoとOsakaのユーザーで動作確認

--Tokyoユーザーで実行
sql tokyo_user/password@サービス名

SQL> SELECT SYS_CONTEXT('USERENV', 'SESSION_USER') AS db_user FROM dual;

DB_USER
_____________
TOKYO_USER

SQL> SELECT order_id, customer, order_amount FROM admin.orders_by_db_user ORDER BY order_id;

   ORDER_ID CUSTOMER          ORDER_AMOUNT
___________ ______________ _______________
       1001 TOKYO_STORE             120000


--Osakaユーザーで実行
sql osaka_user/password@サービス名
SQL> SELECT SYS_CONTEXT('USERENV', 'SESSION_USER') AS db_user FROM dual;

DB_USER
_____________
OSAKA_USER

SQL> SELECT order_id, customer, order_amount FROM admin.orders_by_db_user ORDER BY order_id;

   ORDER_ID CUSTOMER          ORDER_AMOUNT
___________ ______________ _______________
       1002 OSAKA_STORE              85000
       

②接続元IPとクライアント・プログラムでアクセス制御

表とユーザーの作成

CREATE TABLE orders_by_network (
  order_id     NUMBER PRIMARY KEY,
  customer     VARCHAR2(30),
  order_amount NUMBER
);

INSERT INTO orders_by_network VALUES (2001, 'TOKYO_STORE', 120000);
INSERT INTO orders_by_network VALUES (2002, 'OSAKA_STORE', 85000);
INSERT INTO orders_by_network VALUES (2003, 'NAGOYA_STORE', 64000);
COMMIT;

CREATE USER vpd_test IDENTIFIED BY password;
GRANT CREATE SESSION TO vpd_test;
GRANT SELECT ON orders_by_network TO vpd_test;

--実行クライアントのIPアドレスとプログラム名を控える
SELECT
  SYS_CONTEXT('USERENV', 'IP_ADDRESS')          AS ip_address,
  SYS_CONTEXT('USERENV', 'CLIENT_PROGRAM_NAME') AS client_program
FROM dual;

IP_ADDRESS      CLIENT_PROGRAM
_______________ _________________
116.82.xx.xx    SQLcl

VPDポリシーの作成

CREATE OR REPLACE FUNCTION orders_net_pred (
  p_schema IN VARCHAR2,
  p_object IN VARCHAR2
)
RETURN VARCHAR2
AUTHID DEFINER
AS
BEGIN
  RETURN q'[
    SYS_CONTEXT('USERENV', 'IP_ADDRESS') = '116.82.xx.xx'
    AND SYS_CONTEXT('USERENV', 'CLIENT_PROGRAM_NAME') = 'SQLcl'
  ]';
END;
/

BEGIN
  DBMS_RLS.ADD_POLICY(
    object_schema   => 'ADMIN',
    object_name     => 'ORDERS_BY_NETWORK',
    policy_name     => 'ORDERS_NET_POLICY',
    function_schema => 'ADMIN',
    policy_function => 'ORDERS_NET_PRED',
    statement_types => 'SELECT',
    policy_type     => DBMS_RLS.DYNAMIC
  );
END;
/

vpd_testユーザーで動作確認

sql  vpd_test/password@サービス名

SQL> SELECT
  2    SYS_CONTEXT('USERENV', 'IP_ADDRESS')          AS ip_address,
  3    SYS_CONTEXT('USERENV', 'CLIENT_PROGRAM_NAME') AS client_program
  4* FROM dual;

IP_ADDRESS      CLIENT_PROGRAM
_______________ _________________
116.82.xx.xx    SQLcl  

-- ポリシーに指定したIPアドレスとプログラム名の組み合わせであればアクセスできる
SQL> SELECT * FROM .orders_by_network;

   ORDER_ID CUSTOMER           ORDER_AMOUNT
___________ _______________ _______________
       2001 TOKYO_STORE              120000
       2002 OSAKA_STORE               85000
       2003 NAGOYA_STORE              64000


-- VPDポリシーのプログラム名をデタラメに変更し、再度実行する
SQL> SELECT * FROM admin.orders_by_network;

行が選択されていません

③CLIENT_IDENTIFIERによるアプリケーション・ユーザー単位でアクセス制御

表とユーザーの作成

CREATE TABLE orders_by_client_id (
  order_id       NUMBER PRIMARY KEY,
  customer_email VARCHAR2(128),
  order_amount   NUMBER
);

INSERT INTO orders_by_client_id VALUES (3001, 'emma@example.com', 120000);
INSERT INTO orders_by_client_id VALUES (3002, 'liam@example.com', 85000);
INSERT INTO orders_by_client_id VALUES (3003, 'emma@example.com', 64000);
COMMIT;

CREATE USER app_user IDENTIFIED BY password;
GRANT CREATE SESSION TO app_user;
GRANT SELECT ON orders_by_client_id TO app_user;

VPDポリシーの作成

CREATE OR REPLACE FUNCTION orders_app_pred (
  p_schema IN VARCHAR2,
  p_object IN VARCHAR2
)
RETURN VARCHAR2
AUTHID DEFINER
AS
BEGIN
  RETURN q'[
    customer_email =
      SYS_CONTEXT('USERENV', 'CLIENT_IDENTIFIER')
  ]';
END;
/

BEGIN
  DBMS_RLS.ADD_POLICY(
    object_schema   => 'ADMIN',
    object_name     => 'ORDERS_BY_CLIENT_ID',
    policy_name     => 'ORDERS_APP_POLICY',
    function_schema => 'ADMIN',
    policy_function => 'ORDERS_APP_PRED',
    statement_types => 'SELECT',
    policy_type     => DBMS_RLS.DYNAMIC
  );
END;
/

CLIENT IDENTIFIERにアプリケーションIDを格納して動作確認

sql app_user/password@サービス名

--emmaのidをClient Identifierに設定
SQL> BEGIN
  2    DBMS_SESSION.SET_IDENTIFIER(
  3      'emma@example.com'
  4    );
  5  END;
  6* /

PL/SQLプロシージャが正常に完了しました。

SQL> SELECT SYS_CONTEXT('USERENV','CLIENT_IDENTIFIER') AS application_user FROM dual;

APPLICATION_USER
___________________
emma@example.com

--emmaのレコードだけアクセス可
SQL> SELECT order_id, customer_email, order_amount FROM admin.orders_by_client_id ORDER BY order_id;

   ORDER_ID CUSTOMER_EMAIL         ORDER_AMOUNT
___________ ___________________ _______________
       3001 emma@example.com             120000
       3003 emma@example.com              64000


-- liamのidをClient Identiferに設定
SQL> BEGIN
  2    DBMS_SESSION.SET_IDENTIFIER(
  3      'liam@example.com'
  4    );
  5  END;
  6* /

PL/SQLプロシージャが正常に完了しました。

SQL> SELECT SYS_CONTEXT('USERENV','CLIENT_IDENTIFIER') AS application_user FROM dual;

APPLICATION_USER
___________________
liam@example.com

--liamのレコードだけアクセス可
SQL> SELECT order_id, customer_email, order_amount FROM admin.orders_by_client_id ORDER BY order_id;

   ORDER_ID CUSTOMER_EMAIL         ORDER_AMOUNT
___________ ___________________ _______________
       3002 liam@example.com              85000

簡単なVPDポリシーを作成し、その動作を確認しました。1つの表には複数のVPDポリシーを設定できます。複数のポリシー条件は、基本的にAND条件として組み合わされます。このため、VPDは、アクセス範囲をポリシー条件によって絞り込む「引き算型」のアクセス制御と捉えられます。

一方、Deep Data Securityは、アクセス権がない状態を起点として、エンドユーザーに付与されたデータ権限を積み重ねます。最終的なアクセス範囲は、適用されるデータ権限の和集合となるため、「足し算型」のアクセス制御と捉えられます。

改めてVPDとDeep Data Securityの違いは以下のような感じです。同じ行・列アクセス制御の機能ですが、それぞれの特徴や要件に応じて使用を検討されると良いかと思います。

スクリーンショット 2026-09-04 003008.png

とはいえ、VPDとDeep Data Securityのどちらを選択すべきか迷う場合もあるため、簡単な選択ガイドを作成しました。判断のポイントは、アクセス制御を対象とする主な利用者、データベースのバージョン、接続に使用するクライアントや開発プラットフォームです。
特に、Deep Data Securityのエンドユーザー・セキュリティ・コンテキストやトークン認証は、現時点では対応していないローコード/ノーコード・ツールやAIエージェント開発プラットフォームもあります。その場合は、対応するツールを選択するか、対応されるまでプログラムから接続処理を実装する必要があります。

スクリーンショット 2026-09-04 003033.png

Select AIやAIエージェント関連ツールからデータベースへアクセスする場合でも、VPDとDeep Data Securityのアクセス制御はデータベース側で強制されます。AIを利用したデータアクセスにおいても、データベース側の基本的なセキュリティ機能として活用できます。

MFAやトークン認証については下記の記事を参考にして下さい。
Oracle Databaseのトークン・ベースの外部認証連携
Oracle Databaseのローカル・ユーザーに対するMFA有効化

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?