5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Deep Data SecurityとEntra IDによるダイレクト・アクセス方式

5
Last updated at Posted at 2026-05-18

前回は、Deep Data Securityの機能概要とローカル・エンドユーザーの実行例を紹介しました。今回は、Deep Data Securityの主要な目的であるトークン・ベース認証の外部エンド・ユーザーに対するアクセス制御の設定や動作を紹介します。

まず、Oracle Databaseのトークン・ベース認証についてですが、アプリケーションの用途によってOracle Databaseにアクセスする方式がいくつかあります。最も分かりやすいのは、下記のダイレクト・アクセスの方式です。

image.png

これは、自身のPCからSQLclやSQL DeveloperなどのSQLツール、VS CodeやClaude DesktopでOracle SQLcl MCP Serverを使ってデータベースにアクセスするなど、データベース接続に必要なアクセストークンを取得して渡すまでのフローは自身のPC内で完結するものです。
直接データベースを自由にアクセスできる管理者や開発者などの小規模なユーザー向けのアプリケーションが用途として該当します。現行のパスワード認証からEntraIDやOCI IAMのユーザーを各個人に払い出して、トークン認証に切り替えるだけなので、既存の使い方に対する影響は比較的軽微なものになるのではないかと思います。

今回はこのダイレクト・アクセス方式をドキュメントの設定例にエンドユーザー・コンテキストの要素を加えて、少し拡張した内容を紹介します。エンドユーザーコンテキストとは、ポリシーの条件等で使うために任意の値をセッション変数のように格納しておく方法です。

<前提> Entra IDとのトークン・ベース認証

今回はIdPを使用するので、こちらの手順を参考にOracle Database 23.26.2~とEntraIDとのトークン・ベースの認証が完了済みであること

Entra ID側の設定

新しいユーザーを作成。ユーザー名はそれぞれemmaとmarvinとする。
image.png

データ・ロールとマッピングさせるアプリ・ロール(EMPLOYEE, MANAGER)を作成する。アプリロール -> アプリロールの作成
image.png

以下のように作成できていればOK
image.png

次に作成したアプリロールが利用できるようにアクセス権を付与する
APIのアクセス許可 -> アクセス許可の追加 -> 自分のAPIをクリックし、自身のアプリケーションを選択する
image.png

アプリケーションの許可 -> Employeeをチェックして、アクセス許可を追加
image.png

既定のディレクトリに~をクリックし、以下のようにEMPLOYEEとMANAGERに付与されればOK
image.png

最後に作成したアプリロールをユーザーまたはグループに割り当てる
エンタープライズ・アプリ -> ユーザーとグループ -> Add user/group
image.png

ユーザーはemmaを選択
image.png

ロールはEMPLOYEEを選択して作成
image.png

同じ手順でmarvinには、EMPLOYEEとMANAGERの両方のロールを割り当てる。以下のよう作成できていればOK

image.png

Oracle Database側の設定

テスト・データの準備

-- 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(100),
  job_code      VARCHAR2(10),
  department_id NUMBER,
  ssn           VARCHAR2(20),
  salary        NUMBER(10,2),
  manager_id    NUMBER
);

--データの投入 ※@<your-entraID-domain>の部分を自身のEntra IDのドメインに置き換える
--例) victoria@<your-entraID-domain> --> victoria@xxxxxxx.ONMICROSOFT.COM
INSERT INTO hr.employees VALUES (100, 'Marvin', 'Smith', 'marvin@xxxx.onmicrosoft.com', 'mgr', 1234, '543-65-7890', 12000, 1);
INSERT INTO hr.employees VALUES (200, 'Emma', 'Baker', 'emma@xxxx.onmicrosoft.com', 'ic', 1234, '304-12-3465', 2000, 100);
INSERT INTO hr.employees VALUES (300, 'Luis', 'Pitt', 'luis@xxxx.onmicrosoft.com', 'ic', 1234, '432-45-6076', 1250, 100);
INSERT INTO hr.employees VALUES (400, 'Daniel', 'Radcliff', 'daniel@xxxx.onmicrosoft.com', 'ic', 1234, '592-12-1234', 800, 100);
commit;


--表のデータを確認
select * from hr.employees
EMPLOYEE_ID FIRST_NAME LAST_NAME EMAIL                          JOB_CODE DEPARTMENT_ID SSN          SALARY MANAGER_ID
----------- ---------- --------- ------------------------------ -------- ---------------- ------------ ------ ----------
100         Marvin     Smith     marvin@xxxx.onmicrosoft.com   mgr      1234             543-65-7890 12000  1
200         Emma       Baker     emma@xxxx.onmicrosoft.com     ic       1234             304-12-3465 2000   100
300         Luis       Pitt      luis@xxxx.onmicrosoft.com     ic       1234             432-45-6076 1250   100
400         Daniel     Radcliff  daniel@xxxx.onmicrosoft.com   ic       1234             592-12-1234 800    100

EntraIDのアプリロールとマッピングするデータ・ロール等の作成

--データロールを作成
CREATE DATA ROLE employee_role MAPPED TO 'AZURE_ROLE=EMPLOYEE';
CREATE DATA ROLE manager_role MAPPED TO 'AZURE_ROLE=MANAGER';

-- CREATE SESSIONを持つ通常のDBロールを作成
CREATE ROLE db_role;
GRANT CREATE SESSION TO db_role;

-- データロールに作成したDBロールを付与
GRANT db_role TO employee_role;
GRANT db_role TO manager_role;

データ権限の作成
①一般社員用データ権限 (自分の行だけ参照できる。ssn列は更新可能)

-- employees表のemail列とエンドユーザー・セキュリティコンテキストのusernameが一致する行
-- すべての列がSELECT, ssn列はUPDATEを許可。mployee_roleデータロールに付与 
CREATE OR REPLACE DATA GRANT hr.employees_own_record
  AS SELECT, UPDATE(ssn)
  ON hr.employees
  WHERE upper(email) = upper(ORA_END_USER_CONTEXT.username)
  TO employee_role;
  

②MGR用データ権限 (自分の部下の行が参照できる。ただし、ssn列は除く)
エンドユーザー・コンテキストに自身のemployee_idを代入し、それを条件に使用している
※エンドユーザーは実オブジェクトを持てないので、HRスキーマに作成しそれを参照するようなことをやっている

--HRのEMP_CTX.IDのエンドユーザーコンテキストを作成
CREATE OR REPLACE END USER CONTEXT HR.EMP_CTX USING JSON SCHEMA '{
    "type": "object",
    "properties": {
      "ID": {
        "type": "integer",
        "o:onFirstRead": "HR.ctx_pkg.init_user_context"
      }
    }
  }';

--エンドユーザー・コンテキスト:EMP_CTX.IDに自分のemployee_idをUpdateするプロシージャ
CREATE OR REPLACE PACKAGE hr.ctx_pkg AS
    PROCEDURE init_user_context;
  END;
  /

CREATE OR REPLACE PACKAGE BODY hr.ctx_pkg AS
    PROCEDURE init_user_context IS
      sql_stmt VARCHAR2(4000);
    BEGIN
      sql_stmt := '
        UPDATE END_USER_CONTEXT t
        SET t.CONTEXT.ID = (
           SELECT e.employee_id
           FROM hr.employees e
           WHERE upper(e.email) = upper(ora_end_user_context.USERNAME)
         )
        WHERE owner = ''HR''
        AND name = ''EMP_CTX'';
      ';
      EXECUTE IMMEDIATE sql_stmt;
    END;
  END;
  /

--HRのコンテキストの操作に必要な権限をデータロール:manager_roleに付与
GRANT UPDATE ANY END USER CONTEXT TO HR;
GRANT CREATE ANY END USER CONTEXT TO HR;
CREATE ROLE IF NOT EXISTS hr_context_admin;
GRANT EXECUTE ON hr.ctx_pkg TO hr_context_admin;
GRANT hr_context_admin TO manager_role ;

--ディクショナリビューからHRのコンテキストを参照できるデータ権限をmanager_roleに付与
CREATE OR REPLACE DATA GRANT hr.EMPLOYEE_CONTEXT_GRANT
    AS SELECT ON SYS.END_USER_CONTEXT
     WHERE OWNER = 'HR' AND NAME = 'EMP_CTX'
      TO manager_role ;

-- employees表のmanager_idとエンドユーザー・コンテキスト:EMP_CTX.IDが一致する行
-- ssn列以外はSELECT可 
CREATE OR REPLACE DATA GRANT hr.HRAPP_MANAGER_ACCESS
    AS SELECT (ALL COLUMNS EXCEPT ssn)
    ON hr.employees 
    WHERE manager_id = ORA_END_USER_CONTEXT.HR.EMP_CTX.ID
    TO manager_role;

エンドユーザー(Emma)で実行。自分行のみがSELECTできる

--emmaでログイン (※SQLclでインタラクティブ接続)
sql /@サービス名

--Entra IDのログイン画面にリダイレクトされるので、emma@xxxx.onmicrosoft.comでログイン。
--ログインが成功すればプロンプトが戻り、データベースに接続する

Copyright (c) 1982, 2026, Oracle.  All rights reserved.

接続先:
Oracle AI Database 26ai EE High Perf Release 23.26.2.0.0 - Production
Version 23.26.2.0.0

--エンドユーザー・セキュリティコンテキストの値を確認
SQL> SELECT ORA_END_USER_CONTEXT.username FROM dual;

USERNAME
--------------------------------------------
emma@xxxx.onmicrosoft.com

--hr.emloyees表を検索。employee_role -> hr.employees_own_recordのデータ権限が適用
SQL> SELECT * FROM hr.employees;

EMPLOYEE_ID FIRST_NAME LAST_NAME EMAIL                       MANAGER                     SSN          SALARY PHONE
----------- ---------- --------- --------------------------- --------------------------- ------------ ------ --------
400         Emma       Baker     emma@xxxx.onmicrosoft.com   marvin@xxxx.onmicrosoft.com 733-02-9821 8200   555-0400

--salary列は権限ないので更新できない
SQL> UPDATE hr.employees SET salary = 9000;

0行更新しました。

--ssn列は更新できる
SQL> UPDATE hr.employees SET ssn = '111-222-3333';
1行更新しました。

エンドユーザー(Marvin)で実行。自分の行 + MANAGER列が自分のemployee_idになっている部下の行も表示。ただし自分以外のSSN列はNULL

--marvinでログイン (※SQLclでインタラクティブ接続)
sql /@サービス名

--Entra IDのログイン画面にリダイレクトされるので、marvin@xxxx.onmicrosoft.comでログイン。
--ログインが成功すればプロンプトが戻り、データベースに接続する

--エンドユーザー・セキュリティコンテキストの値を確認
SQL> SELECT ORA_END_USER_CONTEXT.username FROM dual;

USERNAME
----------------------------------------------
marvin@xxxx.onmicrosoft.com

--エンドユーザー・コンテキストの値を確認。自身のEMPLOYEE_ID:100が入っている
SQL> SELECT ora_end_user_context.HR.EMP_CTX.ID FROM DUAL;

EMP_CTX
__________
100

--hr.emloyees表を検索。employee_role -> hr.employees_own_recordと
-- manager_role -> hr.manager_direct_reportsのデータ権限が適用
SQL> SELECT * FROM hr.employees;

EMPLOYEE_ID  FIRST_NAME  LAST_NAME  EMAIL                         JOB_CODE  DEPARTMENT_ID  SSN           SALARY  MANAGER_ID
-----------  ----------  ---------  ----------------------------  --------  -------------  ------------  ------  ----------
100          Marvin      Smith      marvin@xxxx.onmicrosoft.com   mgr       1234           543-65-7890  12000   1
200          Emma        Baker      emma@xxxx.onmicrosoft.com     ic        1234                         2000    100
300          Luis        Pitt       luis@xxxx.onmicrosoft.com     ic        1234                         1250    100
400          Daniel      Radcliff   daniel@xxxx.onmicrosoft.com   ic        1234                         800     100

今回は、EntraIDのユーザーを直接アプリロールに割り当てました。より実務的には、グループをアプリロールに割り当てることで、ユーザーがグループへ参加した際に自動的にデータロール(データ権限)が付与されるという仕組みになります。利用しているEntraIDのグループがあれば、それに対応したアクセス・レベルを決め、データ権限の条件を考え、データロールに付与していくというのが基本設計になります。

また、今回のようなダイレクト・アクセスではなく、ERPのような業務アプリケーションやAnalytics、Enterprise AIシステムのような中間アプリケーションがある場合、アプリケーションはデータベースに単一の代表ユーザーでコネクション・プーリングを使い、データベースへの接続コストを効率化していることが多いかと思います。
コネクション・プーリングを毎回ユーザーごとに接続をするようにコードを変更することは、パフォーマンスの観点からやりたくないので、代わりにエンドユーザー・セキュリティ・コンテキストを既存のデータベース・セッションにアタッチするという方法があります。

エンドユーザー・セキュリティ・コンテキストとは、エンドユーザーのアイデンティや属性情報を格納しており、主にアクセストークンから生成されます。ダイレクト・ログインの場合は、データベース接続時に自動的に作成されているのですが、このエンドユーザー・セキュリティ・コンテキストをアプリケーション・コード内で明示的に生成することができます。

image.png

つまり、アプリケーションがデータベースにコネクション済みだとすると、プールから借りてきたコネクションにエンドユーザー・セキュリティ・コンテキストをアタッチして、IdPのエンド・ユーザーとしてSQLを実行させることができます。
そして、コネクションを返す際にデタッチする。既存のDBコネクションにアタッチ/デタッチしながらエンドユーザーを切り替えることで、コネクション・プーリングを維持しながらDeep Data Securityのエンドユーザーへのアクセス制御を実現します。
例えば、Javaの場合、oracle.jdbc.EndUserSecurityContextクラスをアプリケーションに実装します。Pythonや.NET、各フレームワークにも実装方法が用意されています。

中間アプリケーションの場合の構成例としては、OBO(On-Behalf-Of)フローによるエンドユーザー代理のアクセスとアプリケーションのIdentityを用いたアクセスの2種類の方式があるのですが、次回はこれらの違いやアプリケーションへの実装方法について紹介したいと思います。

5
3
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
5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?