2026年4月8日水曜日

Entra IDで認証したリモートMCPサーバーにReal Application Securityを適用する - オンプレミス19c編

リモートMCPサーバーを実行する環境に、Real Application Securityによる保護を実装します。

以下の記事で作成した環境を実装の対象とします。
Oracle Database 19cのデータベースにOracle APEXおよびOracle REST Data Servicesを実装し、フロントにOpenRestyによるリバース・プロキシを配置しています。APEXワークスペースとしてapexdev、スキーマとしてAPEXDEVが作成済みとします。

上記で作成したサンプルのリモートMCPサーバーsampleserverを、Microsoft Entra IDをIdPとしてOpen ID Connect認証できるようにします。Entra IDのアプリとしてORDS MCPおよびORDS MCP Clientを作成します。この作業はAutonomous AI Databaseを対象としたときと同じです。
作業自体は以下の記事の組み合わせになります。


サンプル・データセットのhuman resourcesのインストール



サンプル・データセットのhuman_resourcesをインストールします。2026年4月8日時点での最新であるv23.3.zipをダウンロードします。

curl -OL https://github.com/oracle-samples/db-sample-schemas/archive/refs/tags/v23.3.zip
unzip -q v23.3.zip
ls db-sample-schemas-23.3

apex-arm % curl -OL https://github.com/oracle-samples/db-sample-schemas/archive/refs/tags/v23.3.zip

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current

                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0

100 11.6M    0 11.6M    0     0  3089k      0 --:--:--  0:00:03 --:--:-- 3485k

apex-arm % unzip -q v23.3.zip 

apex-arm % ls db-sample-schemas-23.3 

customer_orders LICENSE.txt product_media README.txt SECURITY.md

human_resources order_entry README.md sales_history

apex-arm % 


human resourcesのディレクトリへ移動します。

cd db-sample-schemas-23.3/human_resources

apex-arm % cd db-sample-schemas-23.3/human_resources 

human_resources % 


ユーザーSYSでデータベースORCLPDB1に接続し、インストール・スクリプトhr_install.sqlを実行します。

sql sys@orclpdb1_tls as sysdba
@hr_install

human_resources % sql sys@orclpdb1_tls as sysdba


SQLcl: 水 4月 08 11:04:37 2026のリリース25.4 Production


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


パスワード (**********?) ******

接続先:

Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production

Version 19.19.0.0.0


SQL> @hr_install


Thank you for installing the Oracle Human Resources Sample Schema.

This installation script will automatically exit your database session

at the end of the installation or if any error is encountered.

The entire installation will be logged into the 'hr_install.log' log file.


Enter a password for the user HR: ******


USERS             

Enter a tablespace for HR [USERS]: 

Do you want to overwrite the schema, if it already exists? [YES|no]: 

Old HR schema has been dropped.


******  Creating REGIONS table ....


Table REGIONSは作成されました。



INDEX REG_ID_PKは作成されました。



Table REGIONSが変更されました。


[中略]


Procedure ADD_JOB_HISTORYがコンパイルされました



Trigger UPDATE_JOB_HISTORYがコンパイルされました



コミットが完了しました。



Installation verification    

____________________________ 

Verification:                


Table             provided    actual 

______________ ___________ _________ 

regions                  5         5 

countries               25        25 

departments             27        27 

locations               23        23 

employees              107       107 

jobs                    19        19 

job_history             10        10 


Thank you!                                                  

___________________________________________________________ 

The installation of the sample schema is now finished.      

Please check the installation verification output above.    

You will now be disconnected from the database.             

Thank you for using Oracle Database!                        

Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production

Version 19.19.0.0.0から切断されました

human_resources % 


サンプル・データセットのインストールが完了したら、最初の作業ディレクトリに戻ります。

cd ../..

human_resources % cd ../..

apex-arm % 




管理ユーザーRASADMINの作成と各種権限の付与



Real Application Securityを構成するためのデータベース・ユーザーとしてRASADMINを作成します。

ユーザーSYSにてデータベースORCLPDB1に接続し、作業を進めます。

sql sys@orclpdb1_tls as sysdba

apex-arm % sql sys@orclpdb1_tls as sysdba


SQLcl: 水 4月 08 11:09:58 2026のリリース25.4 Production


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


パスワード (**********?) ******

接続先:

Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production

Version 19.19.0.0.0


SQL> 


データベース・ユーザーRASADMINを作成し、最低限必要な権限を与えます。

create user rasadmin identified by <パスワード>;
grant create session to rasadmin;

SQL> create user rasadmin identified by ********;


User RASADMINは作成されました。


SQL> grant create session to rasadmin;


Grantが正常に実行されました。


SQL> 


RASADMINに、Real Application Securityを構成するために必要な権限を与えます。オンプレミスではパッケージXS_ADMIN_UTILを使用します。
begin
    sys.xs_admin_util.grant_system_privilege('PROVISION','RASADMIN');
    sys.xs_admin_util.grant_system_privilege('ADMIN_ANY_SEC_POLICY','RASADMIN');
end;
/

SQL> begin

  2      sys.xs_admin_util.grant_system_privilege('PROVISION','RASADMIN');

  3      sys.xs_admin_util.grant_system_privilege('ADMIN_ANY_SEC_POLICY','RASADMIN');

  4  end;

  5* /


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


SQL> 


ロールHR_ROLEを作成し、ユーザーRASADMINに割り当てます。ロールHR_ROLEは後ほどユーザーRASADMINで作成するアプリケーション・ロールEMPLOYEEに割り当てます。
create role hr_role;
grant select on hr.departments to hr_role;
grant select on hr.employees to hr_role;
grant select on hr.jobs to hr_role;
grant select on hr.job_history to hr_role;
grant select on hr.locations to hr_role;
grant select on hr.regions to hr_role;
grant select on hr.countries to hr_role;
grant select on hr.emp_details_view to hr_role;
grant hr_role to rasadmin with admin option;

SQL> create role hr_role;


Role HR_ROLEは作成されました。


SQL> grant select on hr.departments to hr_role;


Grantが正常に実行されました。


SQL> grant select on hr.employees to hr_role;


Grantが正常に実行されました。


SQL> grant select on hr.jobs to hr_role;


Grantが正常に実行されました。


SQL> grant select on hr.job_history to hr_role;


Grantが正常に実行されました。


SQL> grant select on hr.locations to hr_role;


Grantが正常に実行されました。


SQL> grant select on hr.regions to hr_role;


Grantが正常に実行されました。


SQL> grant select on hr.countries to hr_role;


Grantが正常に実行されました。


SQL> grant select on hr.emp_details_view to hr_role;


Grantが正常に実行されました。


SQL> grant hr_role to rasadmin with admin option;


Grantが正常に実行されました。


SQL> 


リモートMCPサーバーはAPEXワークスペースapexdevに紐づくスキーマAPEXDEVに作成しています。

このデータベース・ユーザーAPEXDEVに、RASセッションを操作する権限ADMINISTER_SESSIONを与えます。
begin
    sys.xs_admin_util.grant_system_privilege('ADMINISTER_SESSION','APEXDEV');
end;
/

SQL> begin

  2      sys.xs_admin_util.grant_system_privilege('ADMINISTER_SESSION','APEXDEV');

  3  end;

  4* /


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


SQL> 


以上で、管理ユーザーRASADMINの作成と各種権限の付与が完了しました。


スキーマAPEXDEVの構成



RASのポリシー作成を補助するための設定を行います。このセクション以降は、Autonomous AI Databaseを対象として記事「Entra IDで認証したリモートMCPサーバーにReal Application Securityを適用する - Autonomous AI Database編」と同じなので、実施した手順のみを記載します。

表AUTH_USERSにEntra IDで認証されたユーザーがEMPLOYEE_ID=105, DEPARTMENT_ID=60のDavid Williamsとして認識されるように、1行挿入します。

Entra IDで認証されたユーザーIDは、MCP InspectorよりToolsget_authenticated_identityを実行して取得します。


ユーザーSYSにてデータベースORCLPDB1に接続し、作業を進めます。

apex-arm % sql sys@orclpdb1_tls as sysdba


SQLcl: 水 4月 08 11:27:11 2026のリリース25.4 Production


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


パスワード (**********?) ******

接続先:

Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production

Version 19.19.0.0.0


SQL> 


insert into apexdev.auth_users(employee_id, department_id, email, authenticated_identity) values(105,60,'DWILLIAMS','Entra IDのユーザーのID - upnとして渡される値');
commit;


SQL> insert into apexdev.auth_users(employee_id, department_id, email, authenticated_identity) values(105,60,'DWILLIAMS','********************************');


1行挿入しました。


SQL> commit;


コミットが完了しました。


SQL> 


これらのRAS関連の作業に使用するオブジェクトへのアクセス権限を、ロールMCP_ROLEにまとめます。ユーザー・データへのアクセス権限(HR_ROLE)とは異なるロールとします。

ロールmcp_roleにはMCPサーバーのツールとして呼び出されるプロシージャについても、実行権限を割り当てます。
create role mcp_role;
grant select on apexdev.auth_users to mcp_role;
grant execute on apexdev.oj_mcp_ras_config to mcp_role;
grant select on apexdev.uc_ai_tools to mcp_role;
grant execute on apexdev.run_sql to mcp_role;
grant execute on apexdev.get_current_user to mcp_role;
grant execute on apexdev.get_schema to mcp_role;
grant mcp_role to rasadmin with admin option;

SQL> create role mcp_role;


Role MCP_ROLEは作成されました。


SQL> grant select on apexdev.auth_users to mcp_role;


Grantが正常に実行されました。


SQL> grant execute on apexdev.oj_mcp_ras_config to mcp_role;


Grantが正常に実行されました。


SQL> grant select on apexdev.uc_ai_tools to mcp_role;


Grantが正常に実行されました。


SQL> grant execute on apexdev.run_sql to mcp_role;


Grantが正常に実行されました。


SQL> grant execute on apexdev.get_current_user to mcp_role;


Grantが正常に実行されました。


SQL> grant execute on apexdev.get_schema to mcp_role;


Grantが正常に実行されました。


SQL> grant mcp_role to rasadmin with admin option;


Grantが正常に実行されました。


SQL> 


ユーザーSYSでの作業は以上で完了です。

続いて、ユーザーRASADMINにて、Real Application Securityによる保護を構成します。


Real Application Securityの構成



一連の作業を行なうスクリプトをクローンしたリポジトリmcp-appに、mcp-app/ras-setup/create-ras-prot.sqlとして作成しています。

ユーザーRASADMINでデータベースORCLPDB1に接続し、create-ras-prot.sqlを実行します。

apex-arm % sql rasadmin@orclpdb1_tls


SQLcl: 水 4月 08 11:33:31 2026のリリース25.4 Production


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


パスワード (**********?) ******

接続先:

Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production

Version 19.19.0.0.0


SQL> 


create-ras-prot.sqlを実行します。

@mcp-app/ras-setup/create-ras-prot.sql

SQL> @mcp-app/ras-setup/create-ras-prot.sql

SQL> 

SQL> -- dynamic role EMPLOYEE to access schema HR.

SQL> begin

  2      sys.xs_principal.create_dynamic_role(

  3          name => 'EMPLOYEE',

  4          scope => XS_PRINCIPAL.SESSION_SCOPE

  5      );

  6  end;

  7  /


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


SQL> grant hr_role to employee;


Grantが正常に実行されました。


SQL> 

SQL> -- dynamic role MCPRUNTIME to access MCP server framework.

SQL> begin

  2      sys.xs_principal.create_dynamic_role(

  3          name => 'MCPRUNTIME',

  4          scope => XS_PRINCIPAL.SESSION_SCOPE

  5      );

  6  end;

  7  /


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


SQL> grant mcp_role to mcpruntime;


Grantが正常に実行されました。


SQL> 

SQL> -- namespace template HREMP which refered by ACL

SQL> declare

  2      attrlist XS$NS_ATTRIBUTE_LIST;

  3  begin

  4      attrlist := XS$NS_ATTRIBUTE_LIST();

  5      attrlist.extend(2);

  6      attrlist(1) := XS$NS_ATTRIBUTE('employee_id','0');

  7      attrlist(2) := XS$NS_ATTRIBUTE('department_id','0');

  8      sys.xs_namespace.create_template(

  9          name => 'HREMP',

 10          attr_list => attrlist,

 11          acl => 'SYS.NS_UNRESTRICTED_ACL'

 12      );

 13  end;

 14  /


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


SQL> 

SQL> -- security class emp_priv

SQL> begin

  2      sys.xs_security_class.create_security_class(

  3          name => 'emp_priv',

  4          parent_list => xs$name_list('sys.dml'),

  5          priv_list => xs$privilege_list(xs$privilege('view_sal'))

  6      );

  7  end;

  8  /


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


SQL> 

SQL> -- ACL: emp_acl - Restrict access to the same department as the signed-in user.

SQL> declare

  2      aces xs$ace_list := xs$ace_list();

  3  begin

  4      aces.extend(1);

  5      aces(1) := xs$ace_type(

  6          privilege_list => xs$name_list('select','insert','update','delete'),

  7          principal_name => 'employee' -- application role

  8      );

  9      sys.xs_acl.create_acl(

 10          name => 'emp_acl',

 11          ace_list => aces,

 12          sec_class => 'emp_priv' -- security class

 13      );

 14  end;

 15  /


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


SQL> 

SQL> -- ACL: mgr_acl - Restrict access to the SALARY and COMMISSION_PCT columns

SQL> --                for employees whose manager is the signed-in user.

SQL> declare

  2      aces xs$ace_list := xs$ace_list();

  3  begin

  4      aces.extend(1);

  5      aces(1) := xs$ace_type(

  6          privilege_list => xs$name_list('select','insert','update','delete','view_sal'),

  7          principal_name => 'employee' -- application role

  8      );

  9      sys.xs_acl.create_acl(

 10          name => 'mgr_acl',

 11          ace_list => aces,

 12          sec_class => 'emp_priv'

 13      );

 14  end;

 15  /


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


SQL> 

SQL> -- data security policy employees_ds that includes ACL emp_acl and mgr_acl

SQL> declare

  2      realms xs$realm_constraint_list := xs$realm_constraint_list();

  3      cols xs$column_constraint_list := xs$column_constraint_list();

  4  begin

  5      realms.extend(2);

  6      realms(1) := xs$realm_constraint_type(

  7          realm => q'~department_id = xs_sys_context('HREMP','department_id')~',

  8          acl_list => xs$name_list('emp_acl')

  9      );

 10      realms(2) := xs$realm_constraint_type(

 11          realm => q'~manager_id = xs_sys_context('HREMP','employee_id')~',

 12          acl_list => xs$name_list('mgr_acl')

 13      );

 14      cols.extend(1);

 15      cols(1) := xs$column_constraint_type(

 16          column_list => xs$list('SALARY','COMMISSION_PCT'),

 17          privilege => 'view_sal'

 18      );

 19      sys.xs_data_security.create_policy(

 20          name => 'employee_ds',

 21          realm_constraint_list => realms,

 22          column_constraint_list => cols

 23      );

 24  end;

 25  /


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


SQL> 

SQL> -- apply data security policy employees_ds to hr.employees

SQL> begin

  2      sys.xs_data_security.apply_object_policy(

  3          policy => 'employee_ds',

  4          schema => 'hr',

  5          object => 'employees'

  6      );

  7  end;

  8  /


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


SQL> 

SQL> -- verify configuration

SQL> begin

  2      if (sys.xs_diag.validate_workspace()) then

  3          dbms_output.put_line('All Configurations are correct.');

  4      else

  5          dbms_output.put_line('Some configurations are incorrect.');

  6      end if;

  7  end;

  8  /

All Configurations are correct.



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


SQL> 


最後に実行されるsys.xs_diag.validate_workspace()の結果として、All Configurations are correct.が表示されていれば、Real Application Securityの構成は完了です。

create-ras-prot.sqlで作成したRASの設定を削除するスクリプトdelete-ras-prot.sqlを、リポジトリに含めています。


MCPサーバーsampleserverの更新



リモートMCPサーバーへの接続時にReal Application Securityのセッションを作成し、ツール呼び出し時に作成したセッションをアタッチするように、ORDSのハンドラを変更します。

スキーマAPEXDEVに接続し、RESTモジュールsampleserverのPOSTおよびDELETEハンドラを更新します。

apex-arm % sql apexdev@orclpdb1_tls


SQLcl: 水 4月 08 11:35:11 2026のリリース25.4 Production


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


パスワード (**********?) ******

接続先:

Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production

Version 19.19.0.0.0


SQL> 


以下のコードを実行し、ORDS RESTモジュールのハンドラがプロシージャoj_mcp_ras_post_handlerまたはoj_mcp_ras_delete_handlerを呼び出すように変更します。RASを有効にしない場合はoj_mcp_post_handlerまたはoj_mcp_delete_handlerを呼び出します。
begin
    ords.define_handler(
        p_module_name    => 'sampleserver',
        p_pattern        => 'mcp',
        p_method         => 'POST',
        p_source_type    => 'plsql/block',
        p_source         => 'begin oj_mcp_ras_post_handler(:body,:current_user,:status_code); end;'
    );
    ords.define_handler(
        p_module_name    => 'sampleserver',
        p_pattern        => 'mcp',
        p_method         => 'DELETE',
        p_source_type    => 'plsql/block',
        p_source         => 'begin oj_mcp_ras_delete_handler(:current_user,:status_code); end;'
    );
end;
/

SQL> begin

  2      ords.define_handler(

  3          p_module_name    => 'sampleserver',

  4          p_pattern        => 'mcp',

  5          p_method         => 'POST',

  6          p_source_type    => 'plsql/block',

  7          p_source         => 'begin oj_mcp_ras_post_handler(:body,:current_user,:status_code); end;'

  8      );

  9      ords.define_handler(

 10          p_module_name    => 'sampleserver',

 11          p_pattern        => 'mcp',

 12          p_method         => 'DELETE',

 13          p_source_type    => 'plsql/block',

 14          p_source         => 'begin oj_mcp_ras_delete_handler(:current_user,:status_code); end;'

 15      );

 16  end;

 17* /


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


SQL> 


給与と手当の情報が検索できるように、ユーザーの割り当てをAJAMESに変更します。

update auth_users set employee_id = 103, email = 'AJAMES';
commit;


SQL> update auth_users set employee_id = 103, email = 'AJAMES';


1行更新しました。


SQL> commit;


コミットが完了しました。


SQL> 


以上でリモートMCPサーバーのツール呼び出し時のセッションに、Real Application Securityの動的ロールEMPLOYEEとMCPRUNTIMEが割り当たるようになります。


動作確認



MCP Inspectorを使って動作を確認します。

npx @modelcontextprotocol/inspector

Appsのrun_sqlを開き、以下のSELECT文を実行します。

select employee_id, email, salary from hr.employees

ユーザーAJAMESの部下に限り、給与(SALARY)の情報が一覧されることが確認できます。


今回の記事は以上になります。