※ 本記事は2017年3月13日に公開されたものです。
さて今回は仮想プライベートデータベースを利用してアプリケーションユーザーごとのアクセス制御を実現してみましょう。
アプリケーションユーザー名の識別には、このブログの第14回「実際の利用者をデータベースに伝播する ~ セッション情報」で紹介したクライアント識別子(Client Identifier)を利用します。
では、データベースに必要な設定をおこなっていきます。
まずはアプリケーションが利用するデータベースユーザーの作成です。今回はAPP1USERというユーザーを作成して、APP1.TESTTAB表へのアクセス権限を付与します。
create user app1user identified by oracle; grant create session to app1user; grant select on app1.testtab to app1user;
上記ユーザーの作成はアプリケーション用のユーザーに簡単なパスワードをつけている悪い例です。
次にファイングレインアクセスコントロールのポリシーファンクションの変更です。
今回は接続ユーザーがAPP1USERの場合には、アプリケーションユーザー(クライアント識別子)のデータのみ戻す設定をおこないます。フローチャートは省略しますが、ファンクションには以下の赤字の2行を追加するだけです。
create or replace function app1.vpdfunc
(v_schema varchar2, v_objname varchar2)
return varchar2
is begin
if upper(sys_context('userenv','session_user')) = 'PUKU' then
if sys_context('userenv','ip_address') = '10.185.155.180' and
sys_context('userenv','client_program_name') like 'sqlplus%' then
return '1=1';
else
return '0=1';
end if;
elsif upper(sys_context('userenv','session_user')) = 'APP1USER' then
return 'name = upper(sys_context(''userenv'',''client_identifier''))';
else
return 'name = upper(sys_context(''userenv'',''session_user''))';
end if;
end;
/
では実際にアクセスしてみましょう。
まずはAPP1USERでデータベースに接続します。
SQL> connect app1user/oracle@appdb 接続されました。
ログイン直後のデフォルトの状態では、クライアント識別子に値は設定されていません(NULLが設定されています)。
SQL> select sys_context('userenv','client_identifier') from dual;
SYS_CONTEXT('USERENV','CLIENT_IDENTIFIER')
--------------------------------------------------------------------------------
クライアント識別子に値が設定されていない場合、APP1.TESTTAB表にアクセスしてもファイングレインアクセスコントロールによって条件「NAME = ”」が付加されますので結果は戻りません。
SQL> select * from app1.testtab; レコードが選択されませんでした。
次にクライアント識別子をSATOに設定します。SQL*Plus上でクライアント識別子を設定するには、DBMS_SESSIONパッケージのSET_IDENTIFIERプロシージャ(12cR2英語マニュアル、12cR1日本語マニュアル)を実行します。
SQL> execute dbms_session.set_identifier('sato') PL/SQLプロシージャが正常に完了しました。
クライアント識別子に値が正しく設定されたことを確認します。
SQL> select sys_context('userenv','client_identifier') from dual; SYS_CONTEXT('USERENV','CLIENT_IDENTIFIER') -------------------------------------------------------------------------------- sato
クライアント識別子にSATOという値が設定されている場合、ファイングレインアクセスコントロールによって「NAME = ‘SATO’」という条件が付加されますので、1行の結果が戻ります。
SQL> select * from app1.testtab; NAME ---------------- SATO
次にクライアント識別子をITOに設定し、値を確認します。
SQL> execute dbms_session.set_identifier('ito') PL/SQLプロシージャが正常に完了しました。 SQL> select sys_context('userenv','client_identifier') from dual; SYS_CONTEXT('USERENV','CLIENT_IDENTIFIER') -------------------------------------------------------------------------------- ito
現在はクライアント識別子がITOという値に設定されているため、先ほどとは異なる結果が戻ります。
SQL> select * from app1.testtab; NAME ---------------- ITO
クライアント識別子をクリアするにはDBMS_SESSIONパッケージのCLEAR_IDENTIFIERプロシージャ(12cR2英語マニュアル、12cR1日本語マニュアル)を実行します。プロシージャを実行すると、クライアント識別子の値は設定されていない状態となり、表を検索しても結果は戻らなくなります。
SQL> execute dbms_session.clear_identifier PL/SQLプロシージャが正常に完了しました。 SQL> select sys_context('userenv','client_identifier') from dual; SYS_CONTEXT('USERENV','CLIENT_IDENTIFIER') -------------------------------------------------------------------------------- SQL> select * from app1.testtab; レコードが選択されませんでした。
次回はいよいよWEBアプリケーションでアプリケーションユーザーごとのアクセス制御を実装します。
