統合監査(Unified Auditing)で新たな問題が発覚したので、記載しておきます。
数か月前にリリースした環境で、構成は以下の通りです。
問題となったポリシーは以下のような定義です。(これでも簡略化しています・・・)
create audit policy ADU_POL_01
actions ALL on test.t1
when '(
instr(SYS_CONTEXT(''USERENV'',''HOST'') ,''myhost1'') <> 1
and
(
instr(SYS_CONTEXT(''USERENV'',''HOST'') ,''myhost2'') <> 1
or instr(SYS_CONTEXT(''USERENV'',''CURRENT_USER'') ,''TESTUSR1'') <> 1
)
and
(
(
instr(SYS_CONTEXT(''USERENV'',''CURRENT_USER''),''TESTUSR2'') <> 1
and instr(SYS_CONTEXT(''USERENV'',''CURRENT_USER''),''TESTUSR1'') <> 1
)
or
(
instr(SYS_CONTEXT(''USERENV'',''OS_USER''),''oracle'') <> 1
and instr(SYS_CONTEXT(''USERENV'',''OS_USER''),''grid'') <> 1
)
)
or
(
instr(SYS_CONTEXT(''USERENV'',''CLIENT_PROGRAM_NAME'') ,''PROG1'') = 1
or instr(SYS_CONTEXT(''USERENV'',''CLIENT_PROGRAM_NAME'') ,''PROG2'') = 1
or instr(SYS_CONTEXT(''USERENV'',''CLIENT_PROGRAM_NAME'') ,''PROG3'') = 1
)
)'
EVALUATE PER STATEMENT;
sqlplusからTESTUSR1で接続した場合、監査されない筈なのですが、以下のようなSQLが監査証跡に記録されていました。
create global temporary table sys.ora_temp_1_ds_1110138 sharing=none on commit p reserve rows cache noparallel as select /*+ no_parallel(t) no_parallel_index(t) dbms_stats cursor_sharing_exact use_weak_name_resl dynamic_sampling(0) no_monit oring xmlindex_sel_idx_tbl no_substrb_pad */"COL1","COL3","COL4", rowid SYS_DS_ ALIAS_0 from "TEST"."T1" sample ( .0381150381) t WHERE 1 = 2 create global temporary table sys.ora_temp_1_ds_1110138 sharing=none on commit p reserve rows cache noparallel as select /*+ no_parallel(t) no_parallel_index(t) dbms_stats cursor_sharing_exact use_weak_name_resl dynamic_sampling(0) no_monit oring xmlindex_sel_idx_tbl no_substrb_pad */"COL1","COL3","COL4", rowid SYS_DS_ ALIAS_0 from "TEST"."T1" sample ( .0381150381) t WHERE 1 = 2
sysスキーマにテーブル作成しているのが気になるので、検証環境でテストしてみます。
SQL> create global temporary table sys.ora_temp_1_ds_1110138 (略)
*
ERROR at line 1:
ORA-01031: insufficient privileges
TESTUSR1にはDBAロールが付与されていますが、DBA権限ではsysスキーマにオブジェクトは作れませんでした。
sampleを使っているところとか、統計情報関連っぽいです。
それでテーブル名でMOS(MyOracleSupport)を検索したところ、ヒストグラム統計取得時に作成される一時表である事が判りました。(数字部分はその時々で変わります)
なので検証環境でヒストグラム統計を取得してみます。
SQL> conn TESTUSR1/password
Connected.
SQL> exec dbms_stats.gather_table_stats(ownname=>'TEST',tabname=>'T1',method_opt=>'FOR ALL COLUMNS SIZE 100');
PL/SQL procedure successfully completed.
SQL> exec DBMS_AUDIT_MGMT.FLUSH_UNIFIED_AUDIT_TRAIL;
PL/SQL procedure successfully completed.
SQL> select dbusername,OBJECT_NAME,event_timestamp,sql_text from unified_audit_trail where UNIFIED_AUDIT_POLICIES like '%ADU_POL_01%' order by event_timestamp;
no rows selected
最初のテストでは監査証跡が記録されませんでした。と言うより、create global temporary table自体が実行されていません。
更に調べたところ、ヒストグラム統計取得時に、テーブルに複数回アクセスする必要がある時に、問題の一時表が作成される事が判りました。
ので、データ量を増やして再テストです。
まずテーブルに対するselect部分のみ実行し、監査証跡が作成されない事を確認します。
SQL> select /*+ no_parallel(t) no_parallel_index(t) dbms_stats cursor_sharing_exact use_weak_name_resl dynamic_sampling(0) no_monitoring xmlindex_sel_idx_tbl no_substrb_pad */"COL1","COL3","COL4", rowid SYS_DS_ALIAS_0 from "TEST"."T1" sample ( .0381150381) t WHERE 1 = 2;
no rows selected
SQL> exec DBMS_AUDIT_MGMT.FLUSH_UNIFIED_AUDIT_TRAIL;
PL/SQL procedure successfully completed.
SQL> select dbusername,OBJECT_NAME,event_timestamp,sql_text from unified_audit_trail where UNIFIED_AUDIT_POLICIES like '%ADU_POL_01%' order by event_timestamp;
no rows selected
次にヒストグラム統計を取得時します。
SQL> exec dbms_stats.gather_table_stats(ownname=>'TEST',tabname=>'T1',method_opt=>'FOR ALL COLUMNS SIZE 100');
PL/SQL procedure successfully completed.
SQL> exec DBMS_AUDIT_MGMT.FLUSH_UNIFIED_AUDIT_TRAIL;
PL/SQL procedure successfully completed.
SQL> select dbusername,OBJECT_NAME,event_timestamp,sql_text from unified_audit_trail where UNIFIED_AUDIT_POLICIES like '%ADU_POL_01%' order by event_timestamp;
DBUSERNAME
------------------------------
OBJECT_NAME
----------------------------------------------------------------------------------------------------------------------
EVENT_TIMESTAMP
---------------------------------------------------------------------------
SQL_TEXT
--------------------------------------------------------------------------------
TESTUSR1
T1
17-JAN-20 04.07.07.760694 PM
create global temporary table sys.ora_temp_1_ds_1070116 sharing=none on commit p
今度は監査証跡が作成されてしまっていました。
サポートに問い合わせを上げ、Oracle社の環境でも再現する事が確認されました。
まだ結果待ちの状態ですが、バグなのは明らかですね・・・。
これも証跡収集ツールの方でフィルタリングしてもらうしか無さそうです。
後日追記。
1か月くらいかかってサポートから回答が来ましたが、やはりバグでした。
再帰文が不適切に監査されていて、再帰文の監査に監査ポリシーの条件句をうまくハンドル出来ない事象だそうです。
パッチ適用後に以下の様にONLY TOPLEVEL句を指定する事で回避できるそうです。
create audit policy <監査ポリシー名>
actions ALL on <オーナー名>.<テーブル名>
when '<条件句>'
EVALUATE PER STATEMENT ONLY TOPLEVEL;
しかし個別パッチがありません。(19cでは修正が含まれています)
Extended supportがあればパッチ作成申請が出せるのですが、ありません・・・
やはり証跡収集ツールの方でフィルタリングしてもらうしか無さそうです。