※ 本記事は2017年3月27日に公開されたものです。

さて、このブログの仮想プライベートデータベースのエントリは12cR2を使って実行して、実行結果を貼り付けているのですが、その過程で12cR2で12cR1までと挙動が変わっているところを発見してしまいました。想定される動作かどうか開発に確認したのですが、どうやら新しい動作がセキュリティ的には正しい動作らしく、ただし、データベースをアップグレードすると挙動が変わってしまう可能性もあるのでご注意ください。

具体的には、ポリシーファンクションでDBMS_SESSION.IS_ROLE_ENABLEDファンクション(12cR2英語マニュアル12cR1日本語マニュアル)を利用できなくなりました。DBMS_SESSION.IS_ROLE_ENABLEDファンクションはロール名を引数にとり、ユーザーがそのロールを保有しているかどうか(現在有効かどうか)をBOOLEAN(TRUE/FALSE)で戻すファンクションです。
12cR1までは、特定のデータベースロール(MYROLE)を保有しているユーザーであれば値を見れるようにしたい場合、以下のようなポリシーファンクションを作成し、実現することができました。

create or replace function app1.vpdsamplefunc
  (v_schema varchar2, v_objname varchar2)
  return varchar2
is begin
  if dbms_session.is_role_enabled('myrole') then
    return '1=1';
  else
    return '0=1';
  end if;
end;
/ 

12cR2ではこのようなポリシーファンクションを作成した場合、DBMS_SESSION.IS_ROLE_ENABLEDファンクションは常にFALSEを戻します。
これはポリシーファンクションは常に定義者権限で実行されるためです。ポリシーファンクションは実行者権限で作成することはできません。(実行者権限で定義しても定義者権限で実行されます)
そして、PL/SQLの仕様で定義者権限で実行されるプログラムではPUBLICロールのみが有効化された状態で実行されます。そのため、DBMS_SESSION.IS_ROLE_ENABLEDファンクションで引数にユーザーが定義したロールを指定しても常にFALSEが戻ります。

ポリシーファンクションは定義者権限で実行されるという仕様は昔からあったのですが、12cR1まではDBMS_SESSION.IS_ROLE_ENABLEDファンクションで実行者に割り当てられているロールによってTRUEを戻していました。12cR2では定義者権限で実行されるプログラムではPUBLICロールのみが有効化されるという正しい動作に修正され、結果として常にFALSEを戻すようになりました。 

では、仮想プライベートデータベースでロールベースのアクセス制御ができなくなってしまったかというと、そうではありません。たとえば次のようにポリシーを作成することで、先ほどのポリシーファンクションと同等の結果を戻すことが確認できました。

 

  • 12cR2の現時点での最新バージョンで確認していますが、将来的にまた動作が変わる可能性があることはご了承ください 

 

create function aaa.has_role (x varchar2) return varchar2
is begin
  if dbms_session.is_role_enabled(x) then return 'TRUE';
  else return 'FALSE';
  end if;
end;
/
create or replace function aaa.vpdfunc
  (v_schema varchar2, v_objname varchar2)
  return varchar2
is begin
  return 'aaa.has_role(''myrole'') =''TRUE''';
end;
/

今回、私が気付いたのはDBMS_SESSION.IS_ROLE_ENABLEDファンクションの挙動の変更ですが、他のファンクションも定義者権限で実行されますので、実行者の権限を利用しようとしているものは挙動が変わる可能性があります。VPDを利用しているシステムを12cR2にアップグレードする際にはご注意ください。

「もくじ」にもどる