Oracle AI Database 26aiにDeep Data Securityという新しいアクセス制御の機能が追加されました。Oracle Databaseには、VPD(Virtual Private Database)やRAS(Real Application Security)等のアクセス制御の機能がありますが、それらのコンセプトを受け継ぎながら、より使いやすく、AI Agentのようなエンタープライズのアプリケーションにも対応した新たな行・列レベルのアクセス制御の機能です。
Oracle AI Database 23.26.2~、Standard Edition以上から使用することが可能です。
Deep Data Securityの機能のポイントとしては、以下の2点が挙げられます
- 従来のデータベース・ユーザーではなく、実際のエンドユーザーを対象にしたアクセス制御を目的としている
- データ権限、データ・ロールという新しい仕組みで、複雑になりがちなアクセスポリシーを明瞭にさせる
まず1点目のエンド・ユーザーについてですが、Oracle Databaseには外部認証として古くはOracle Internet DirectoryからActive Directory, 最近ではMicrosoft EntraIDやOCI IAM等の外部ユーザーを使用してデータベースにログインできる認証強化の機能を提供しています。
従来では、例えばtaro.suzuki@xxx.comというユーザーでEntraIDでログイン認証を受けた後、アクセストークンを使用してOracle Databaseにログインするとします。この場合、Oracle Database側ではtaro.suzuki@xxx.comにマッピングさせるために何らかのデータベース・ユーザーが必要となります。
SQL> select username,external_name from user_users;
--データベース・ユーザー AZURE_GLOBALUSRにマッピングされている
USERNAME EXTERNAL_NAME
-------------- --------------------------------------
AZURE_GLOBALUSR azure_user=taro.suzuki@xxx.com
Deep Data Securityのエンド・ユーザーでログインした場合は、以下のようにDatabase側ではマッピングするDBユーザーを必要としません。エンド・ユーザーは、接続時に自動的に作成され、セッション切断時に削除されます。上記との比較した場合、Deep Data Securityはより純粋なエンドユーザーとして動作していることが分かります
SQL> select username,external_name from user_users;
USERNAME EXTERNAL_NAME
-------------- --------------------------------------
XS$NULL
このエンド・ユーザーは、スキーマ・オブジェクトを持つことはできません。データ・ロールというDeep Data Security専用のロールが付与されることで、表やビューへアクセスできるようになります。
では、必ずEntra IDやOCI IAMと外部認証したデータベースしか使用できないの? とガッカリされる方もおられるかもしません。安心して下さい、ローカル・エンド・ユーザーという方法で、外部認証ではなく従来のようにデータベースだけのユーザーでDeep Data Securityを使用することができます。
まとめるとこんな感じになります。IdPで認証された外部エンド・ユーザーとしての動作の仕組みを理解することがDeep Data Securityのコンセプトや機能概要を理解しやすいため、ここでは外部エンド・ユーザーを前提とした説明をしていきます。
スライドには、もう一つ重要な要素として、エンド・ユーザー・セキュリティ・コンテキストというものがあります。IdPから受け取ったそれぞれのアクセス・トークンには、ユーザーやアプリケーション・ロール、クライアントの情報など様々なアイデンティティの属性が格納されています。
これらは、エンド・ユーザー・セキュリティ・コンテキストとしてデータベース接続時にセッションに格納され、セッション終了と共に解放されます。これをORA_END_USER_CONTEXTで値を取り出し、ポリシーの条件として使用することができます。
SQL> SELECT ora_end_user_context.USERNAME FROM dual;
USERNAME
------------------------
"taro.suzuki@xxx.com"
2点目として、このエンドユーザーが表やビューのオブジェクトに対してどういったアクセスを許可させるか、というのがデータ権限とデータ・ロールという役目になります。
データ権限は、CREATE DATA GRANTで表またはビューの行や列に対してアクセス可能な範囲を指定するポリシーを作成します。例えば、下記のデータ権限はこのような意味になります。
- 表: HR.EMPLOYEE
- 列条件: SELECT(全列)とUPDATE(phone列のみ)を許可
- 行条件: 表のemail列とエンドユーザー・セキュリティコンテキストのユーザー名が一致
CREATE DATA GRANT EmployeesOwnRecord AS
SELECT, UPDATE (phone) <----列
ON hr.employees
WHERE email = ORA_END_USER_CONTEXT.username <----行
TO employees_role;
このデータ権限を誰に付与するか?というのが最後のTOで指定している箇所です。ここで指定するのがデータ・ロールです。データ・ロールはDeep Data Securityのためのロールで、複数のデータ権限をまとめる入れ物の役割を担います。
アプリケーションでは、数百を超えるアクセス・パターンに応じてデータ権限が作成されるので、それらを用途や組織・グループ等に応じてデータ・ロールに取りまとめていきます。
まとめると以下のようなイメージです。データロールは、最終的にはEntra ID場合だとアプリケーション・ロール、OCI IAMだとグループにマッピングされます。IdP側のユーザーは、自分が所属するグループに応じて付与されるDeep Data Securityのデータ・ロールとデータ権限が変わる = アクセスが行・列レベルで制御されるということになります。
そしてエンド・ユーザーが実行するSQLは、同じSQLにも関わらずデータ権限に応じてDeep Data SecurityがSQLを強制的に書き換えます。データベース側の制御なので、どんなアプリケーションやツールでも同じ結果となり回避できない強制的なアクセス制御として動作します。
説明だけだと少し難解なので、実際に手を動かしてみると動作イメージがつかめるかと思います。とはいえ、トークン認証が動作するデータベースまで準備するのはちょっと・・という人も多いかと思うので、代わりにローカル・エンドユーザーを使います。
ローカル・エンドユーザーは、従来のパスワード認証にようにユーザー名とパスワードで直接ログインできるユーザーです。以下のような特徴を持っており、トークン認証を使わずともDeep Data Securityをお手軽に使用することができます。
ローカル・エンドユーザーによる実行例
ドキュメントにあるローカル・エンド・ユーザーによるDeep Data Securityの実行例を解説を加えて紹介します。
テスト・データの準備
-- HRユーザーの作成 ※NO AUTHENTICATIONオプションでHRはログインはできない
CREATE USER hr NO AUTHENTICATION
DEFAULT TABLESPACE users
QUOTA UNLIMITED ON users;
-- employees表の作成
CREATE TABLE hr.employees (
employee_id NUMBER PRIMARY KEY,
first_name VARCHAR2(50),
last_name VARCHAR2(50),
email VARCHAR2(128),
manager VARCHAR2(128),
ssn VARCHAR2(20),
salary NUMBER(10,2),
phone VARCHAR2(20)
);
--データの投入
INSERT INTO hr.employees VALUES (100, 'Victoria', 'Williams', 'vwilliams', NULL, '219-09-9999', 13000, '555-0100');
INSERT INTO hr.employees VALUES (200, 'Marvin', 'Anderson', 'manderson', 'vwilliams', '457-55-5462', 12030, '555-0200');
INSERT INTO hr.employees VALUES (300, 'Chris', 'Evans', 'cevans', 'vwilliams', '321-12-4567', 6900, '555-0300');
INSERT INTO hr.employees VALUES (400, 'Emma', 'Baker', 'ebaker', 'manderson', '733-02-9821', 8200, '555-0400');
INSERT INTO hr.employees VALUES (500, 'Taylor', 'Mills', 'tmills', 'manderson', '558-76-1243', 9000, '555-0500');
COMMIT;
SELECT * FROM hr.employees;
EMPLOYEE_ID FIRST_NAME LAST_NAME EMAIL MANAGER SSN SALARY PHONE
----------- ---------- --------- ---------- ---------- ----------- ------ --------
100 Victoria Williams vwilliams 219-09-9999 13000 555-0100
200 Marvin Anderson manderson vwilliams 457-55-5462 12030 555-0200
300 Chris Evans cevans vwilliams 321-12-4567 6900 555-0300
400 Emma Baker ebaker manderson 733-02-9821 8200 555-0400
500 Taylor Mills tmills manderson 558-76-1243 9000 555-0500
ローカル・エンドユーザーの作成 (※ユーザー名が小文字指定になっていることに注意)
CREATE END USER "manderson" IDENTIFIED BY <password>;
CREATE END USER "ebaker" IDENTIFIED BY <password>;
データ・ロールの作成
-- ローカル・エンドユーザー用のデータ・ロールを作成
CREATE OR REPLACE DATA ROLE employee_role;
CREATE OR REPLACE DATA ROLE manager_role;
-- 通常のデータベース・ロールを作成し、CREATE SESSIONの権限を付与する
CREATE ROLE db_role;
GRANT CREATE SESSION TO db_role;
-- 作成したデータベース・ロールをデータ・ロールに付与する
GRANT db_role TO employee_role;
-- Marvin(一般社員かつ管理者)には、employee_roleとmanager_roleの両方のデータ・ロールを付与
GRANT DATA ROLE manager_role TO "manderson";
GRANT DATA ROLE employee_role TO "manderson";
-- Emma(一般社員)にはemployee_roleだけを付与
GRANT DATA ROLE employee_role TO "ebaker";
データ権限の作成
-- employees表のemail列とエンドユーザー・セキュリティコンテキストのusernameが一致する行と
-- すべての列がSELECTできる。employee_roleデータロールに付与 --> 一般社員用
CREATE OR REPLACE DATA GRANT hr.employees_own_record
AS SELECT
ON hr.employees
WHERE email = ORA_END_USER_CONTEXT.username
TO employee_role;
-- employees表のmanager列とエンドユーザー・セキュリティコンテキストのusernameが一致する行と
-- ssn列を除く列がSELECTできる。manager_roleデータロールに付与--> 管理者用
CREATE OR REPLACE DATA GRANT hr.manager_direct_reports
AS SELECT (ALL COLUMNS EXCEPT ssn)
ON hr.employees
WHERE manager = ORA_END_USER_CONTEXT.username
TO manager_role;
ローカル・エンドユーザー ebaker(Emma)で実行。自分行のみがSELECTできる
--ebakerでログイン (※小文字指定のユーザ名になっている点に注意)
sqlplus '"ebaker"'/<password>@//<host>:<port>/<PDB-service-name>
--エンドユーザー・セキュリティコンテキストの値を確認
SELECT ORA_END_USER_CONTEXT.username FROM dual;
USERNAME
----------
"ebaker"
--hr.emloyees表を検索。employee_role -> hr.employees_own_recordのデータ権限が適用
SELECT * FROM hr.employees;
EMPLOYEE_ID FIRST_NAME LAST_NAME EMAIL MANAGER SSN SALARY PHONE
----------- ---------- --------- ------ --------- ----------- ------ --------
400 Emma Baker ebaker manderson 733-02-9821 8200 555-0400
ローカル・エンドユーザー manderson(Marvin)で実行。自分の行 + MANAGER列が自分になっている行もSELECTできる。ただし自分以外のSSN列はNULL
--mandersonでログイン (※小文字指定のユーザ名になっている点に注意)
sqlplus '"manderson"'/<password>@//<host>:<port>/<PDB-service-name>
--エンドユーザー・セキュリティコンテキストの値を確認
SELECT ORA_END_USER_CONTEXT.username FROM dual;
USERNAME
----------
"manderson"
--hr.emloyees表を検索。manager_role -> hr.manager_direct_reportsのデータ権限が適用
SELECT * FROM hr.employees;
EMPLOYEE_ID FIRST_NAME LAST_NAME EMAIL MANAGER SSN SALARY PHONE
----------- ---------- --------- ---------- ---------- ----------- ------ --------
200 Marvin Anderson manderson vwilliams 457-55-5462 12030 555-0200
400 Emma Baker ebaker manderson 8200 555-0400
500 Taylor Mills tmills manderson 9000 555-0500
このようにデータ権限の付与は加算的であり、最終的な権限は付与されるすべてのデータ権限のユニオン(和集合)になります。
いかかでしょうか?従来のOracle Databaseの行列アクセス制御の機能に比べて、アクセスポリシーの作成や権限付与がシンプルになったように伝われば幸いです。
次回は、Deep Data Securityの主要コンセプトである外部エンド・ユーザーを使用したDeep Data Securityの設定手順や認証パターンによる動作の違いなどトークン認証時における諸々の動作について紹介します。
また、トークンベースの外部認証について詳しくはこちらを参照下さい。実際にIdP側の設定やトークンの動作について体験しておくとDeep Data Securityの理解が深まると思います。
参考: トークン認証を用いたDeep Data Security + SQLcl MCP Server
AI AgentからMCPサーバー経由でOracle Databaseにアクセスした場合も、当然ですが結果はSQL*Plusの場合と同様です。AI Agentは、ディクショナリビューなどOracle Database内を色々検索して試行錯誤しますが、失敗します。※LLMは、まだDeep Data Securityの存在を知らないので、RASやVPDとして間違って認識している。
トークン認証でOracle Databaseに接続
Emmaで実行。同様にデータ権限で自分のレコードのみに制限される
Nullになっている列をなんとか表示させようとしても×
また、このようなMCPサーバーやDBにアクセスするツールを使用する管理者・開発者向けに個々にユーザーを払い出してDBにアクセスさせるような使い方は、比較的にDeep Data Securityへの移行は抵抗なく進めるかと思います。
ただ、DBに共有ユーザーひとつでコネクションプーリングで接続しているようなアプリケーションの場合、個々のエンドユーザーで接続する方式には変更することは簡単ではありません。この解決案としては、アプリケーション内のJDBCでDBへのコネクション後に、明示的にトークンから生成したにエンド・ユーザー・セキュリティ・コンテキストをセットすることで解決できるのですが、この点についても次回少し触れられればと思います。







