【PL/SQL】DBMS_FGAでファイングレイン監査を設定する方法|ADD_POLICY・監査ログ確認・ハンドラ連携

【PL/SQL】ファイングレイン監査(FGA)とPL/SQLの活用 PL/SQL

ファイングレイン監査(FGA: Fine Grained Auditing)は、Oracleで「特定の表にアクセスしたか」だけでなく、特定の列を参照したか特定条件に合う行へアクセスしたかまで絞って監査できる仕組みです。通常の監査よりもログを目的に合わせて絞り込めるため、個人情報、給与、契約金額、機密フラグなどのアクセス証跡を残したい場面で役立ちます。

この記事では、DBMS_FGA.ADD_POLICY を使ったFGAポリシー作成、DBA_FGA_AUDIT_TRAIL / UNIFIED_AUDIT_TRAIL の確認、PL/SQLハンドラ連携、有効化・無効化・削除までを実務向けにまとめます。Oracle監査全体の設計は Oracleの監査(AUDIT)機能の設定方法、統合監査中心の整理は 統合監査(Unified Audit)完全ガイド も参考にしてください。

この記事で扱うこと

  • DBMS_FGAで監査ポリシーを作成する基本形
  • SELECT / UPDATE / DELETE を対象にする指定方法
  • audit_column と audit_column_opts の使い分け
  • 監査ログを確認するSQL
  • PL/SQLハンドラで独自ログへ記録する方法
  • ポリシーの無効化・再有効化・削除
  • 実務で避けたい設計ミス
スポンサーリンク

FGAでできること

FGAは、表やビューに対して条件付きの監査ポリシーを設定します。たとえば、給与列を参照したSELECTだけ記録する、高額取引に対するUPDATEだけ記録する、といった使い方ができます。

対象 使いどころ
SALARY を参照したとき 給与・個人情報・機密列の監査
行条件 amount >= 1000000 高額取引や重要データだけ監査
SQL種別 SELECT,UPDATE,DELETE 参照だけでなく変更操作も追跡
ハンドラ PL/SQLプロシージャを呼び出す 独自ログ・通知・アラート連携

必要な権限

FGAポリシーを管理するユーザーには、監査管理用の権限と DBMS_FGA の実行権限が必要です。権限設計は環境方針に合わせますが、専用の管理ユーザーで実行するのが扱いやすいです。

fga-grants.sql
-- 例: FGAを管理するユーザーに必要な権限を付与
GRANT AUDIT_ADMIN TO SEC_ADMIN;
GRANT EXECUTE ON DBMS_FGA TO SEC_ADMIN;

-- 監査対象表に対する権限も必要
GRANT SELECT, UPDATE, DELETE ON HR.EMPLOYEES TO SEC_ADMIN;
注意: 権限を広く付けすぎると、監査ポリシー自体を変更できるユーザーが増えます。本番環境では、誰がFGAポリシーを作成・変更・削除できるかを監査対象に含めておくと安全です。

DBMS_FGA.ADD_POLICYの基本形

FGAポリシーは DBMS_FGA.ADD_POLICY で作成します。以下は、HR.EMPLOYEESSALARY 列を参照し、かつ給与が10000以上の行にアクセスした場合に監査する例です。

add-fga-policy.sql
BEGIN
  DBMS_FGA.ADD_POLICY(
    object_schema      => 'HR',
    object_name        => 'EMPLOYEES',
    policy_name        => 'FGA_EMP_SALARY',
    audit_condition    => 'SALARY >= 10000',
    audit_column       => 'SALARY',
    handler_schema     => NULL,
    handler_module     => NULL,
    enable             => TRUE,
    statement_types    => 'SELECT',
    audit_column_opts  => DBMS_FGA.ANY_COLUMNS
  );
END;
/

audit_condition は行条件、audit_column は監査対象列です。audit_column を指定しない場合は、対象オブジェクトへのアクセス全体が監査対象になります。

audit_conditionの注意: audit_condition は行ごとに評価される条件式です。複雑な副問合せ、シーケンス、ROWNUM などは使えません。Oracleのバージョンや構成によっては、AND / OR を含む複雑な条件も避ける必要があります。まずは単純な条件から作り、複雑な判定が必要ならビューや別設計で吸収するのが安全です。条件を指定しない場合は TRUE と同じ扱いになります。

SELECT以外も監査する

FGAはSELECTだけでなく、INSERT、UPDATE、DELETEも対象にできます。給与列の参照・変更を追いたい場合は、statement_types に複数のSQL種別を指定します。

fga-select-update-delete.sql
BEGIN
  DBMS_FGA.ADD_POLICY(
    object_schema      => 'HR',
    object_name        => 'EMPLOYEES',
    policy_name        => 'FGA_EMP_SALARY_DML',
    audit_condition    => 'SALARY >= 10000',
    audit_column       => 'SALARY',
    statement_types    => 'SELECT,UPDATE,DELETE',
    audit_column_opts  => DBMS_FGA.ANY_COLUMNS,
    enable             => TRUE
  );
END;
/

監査範囲を広げるほどログ量と確認コストも増えます。最初から全操作を監査するより、実際に追跡したい操作に絞るほうが運用しやすくなります。

audit_column_optsの違い

audit_column に複数列を指定する場合、audit_column_opts で「どれか1列でも参照されたら監査する」のか、「指定列すべてが参照されたら監査する」のかを選びます。

指定 監査される条件 向いている場面
DBMS_FGA.ANY_COLUMNS 指定列のいずれかを参照 1列でも機密なら記録したい
DBMS_FGA.ALL_COLUMNS 指定列すべてを参照 列の組み合わせが危険なときだけ記録したい
fga-any-all-columns.sql
-- どちらかの列を参照したら監査
audit_column      => 'SALARY,COMMISSION_PCT',
audit_column_opts => DBMS_FGA.ANY_COLUMNS

-- 両方の列を参照したら監査
audit_column      => 'SALARY,COMMISSION_PCT',
audit_column_opts => DBMS_FGA.ALL_COLUMNS

監査ログを確認する

FGAの監査ログは、環境によって DBA_FGA_AUDIT_TRAILUNIFIED_AUDIT_TRAIL から確認します。既存環境では両方のどちらを見ればよいか、監査方式を先に確認しておきましょう。データディクショナリの調べ方は Oracleデータディクショナリ完全ガイド にもまとめています。

check-dba-fga-audit-trail.sql
SELECT
    db_user,
    os_user,
    userhost,
    object_schema,
    object_name,
    policy_name,
    statement_type,
    timestamp,
    sql_text
FROM dba_fga_audit_trail
WHERE policy_name = 'FGA_EMP_SALARY'
ORDER BY timestamp DESC;
check-unified-audit-trail.sql
SELECT
    dbusername,
    os_username,
    userhost,
    object_schema,
    object_name,
    fga_policy_name,
    action_name,
    event_timestamp,
    sql_text
FROM unified_audit_trail
WHERE fga_policy_name = 'FGA_EMP_SALARY'
ORDER BY event_timestamp DESC;

SQL_TEXT を見ると、どのSQLで監査が発生したか追跡できます。バインド変数を多用するアプリでは、SQL本文だけでは意図が読みづらいことがあります。バインド変数の考え方は Oracleバインド変数完全ガイド も参考になります。

PL/SQLハンドラで独自ログに記録する

FGAでは監査イベント発生時にPL/SQLハンドラを呼び出せます。標準監査ログとは別に、アプリ運用向けの軽量ログへ書きたい場合に使えます。

create-fga-alert-log.sql
CREATE TABLE sec_admin.fga_alert_log (
  id            NUMBER GENERATED BY DEFAULT AS IDENTITY,
  object_schema VARCHAR2(128),
  object_name   VARCHAR2(128),
  policy_name   VARCHAR2(128),
  db_user       VARCHAR2(128),
  host_name     VARCHAR2(256),
  log_time      TIMESTAMP DEFAULT SYSTIMESTAMP,
  CONSTRAINT pk_fga_alert_log PRIMARY KEY (id)
);
fga-handler-procedure.sql
CREATE OR REPLACE PROCEDURE sec_admin.fga_alert_handler(
  object_schema IN VARCHAR2,
  object_name   IN VARCHAR2,
  policy_name   IN VARCHAR2
) AUTHID DEFINER
IS
BEGIN
  INSERT INTO sec_admin.fga_alert_log (
    object_schema,
    object_name,
    policy_name,
    db_user,
    host_name
  ) VALUES (
    object_schema,
    object_name,
    policy_name,
    SYS_CONTEXT('USERENV', 'SESSION_USER'),
    SYS_CONTEXT('USERENV', 'HOST')
  );
END;
/

ハンドラを登録する場合は、handler_schemahandler_module を指定します。

add-policy-with-handler.sql
BEGIN
  DBMS_FGA.ADD_POLICY(
    object_schema      => 'HR',
    object_name        => 'EMPLOYEES',
    policy_name        => 'FGA_EMP_SALARY_ALERT',
    audit_condition    => 'SALARY >= 10000',
    audit_column       => 'SALARY',
    handler_schema     => 'SEC_ADMIN',
    handler_module     => 'FGA_ALERT_HANDLER',
    statement_types    => 'SELECT,UPDATE',
    audit_column_opts  => DBMS_FGA.ANY_COLUMNS,
    enable             => TRUE
  );
END;
/
ハンドラの注意点: ハンドラ内で例外が発生すると、監査対象のSQLまで失敗することがあります。また、監査対象表に対するDMLをハンドラ内で行うと再帰的に監査が発生する危険があります。ハンドラは軽く、単純に、監査対象外の表へ記録する設計にしてください。

独自ログやトレーサビリティ設計は PL/SQLのロギングとトレーサビリティを両立する監査設計 と相性が良いです。

ポリシーを確認・無効化・有効化・削除する

設定したFGAポリシーは、後から確認・停止・再開・削除できます。調査中だけ一時的に監査したい場合は、削除ではなく無効化を使うと戻しやすくなります。

manage-fga-policy.sql
-- FGAポリシー一覧を確認
SELECT object_schema, object_name, policy_name, enabled, sel, ins, upd, del
FROM dba_audit_policies
WHERE object_schema = 'HR'
  AND object_name = 'EMPLOYEES'
ORDER BY policy_name;

-- 無効化
BEGIN
  DBMS_FGA.DISABLE_POLICY(
    object_schema => 'HR',
    object_name   => 'EMPLOYEES',
    policy_name   => 'FGA_EMP_SALARY'
  );
END;
/

-- 再有効化
BEGIN
  DBMS_FGA.ENABLE_POLICY(
    object_schema => 'HR',
    object_name   => 'EMPLOYEES',
    policy_name   => 'FGA_EMP_SALARY'
  );
END;
/

-- 削除
BEGIN
  DBMS_FGA.DROP_POLICY(
    object_schema => 'HR',
    object_name   => 'EMPLOYEES',
    policy_name   => 'FGA_EMP_SALARY'
  );
END;
/

動作確認用SQL

ポリシー作成後は、監査されるSQLと監査されないSQLを分けてテストします。監査条件と監査列の両方を満たすかがポイントです。

test-fga-policy.sql
-- SALARY列を参照し、条件に合う可能性があるため監査対象
SELECT employee_id, last_name, salary
FROM hr.employees
WHERE salary >= 10000;

-- SALARY列を参照しないため、audit_column指定によっては監査されない
SELECT employee_id, last_name
FROM hr.employees
WHERE department_id = 10;

-- UPDATEもstatement_typesに含めていれば監査対象
UPDATE hr.employees
SET salary = salary
WHERE salary >= 10000;

実務での設計ポイント

観点 推奨 理由
監査範囲 対象表・列・条件を絞る ログ量と性能影響を抑える
ポリシー名 対象と目的が分かる名前にする 調査時に検索しやすい
ハンドラ 軽量処理だけにする 例外や再帰監査の影響を避ける
ログ保存 保存期間とアーカイブ方針を決める 監査ログが増え続けるため
権限 監査管理者を限定する ポリシー改ざんを防ぐ

よくある質問

Q. FGAと通常のAUDITは何が違いますか?
A. 通常のAUDITは操作やオブジェクト単位の監査が中心です。FGAは列や行条件まで絞り込めるため、「給与列を見た」「高額データにアクセスした」のような監査に向いています。
Q. FGAはSELECTだけですか?
A. いいえ。statement_typesINSERT,UPDATE,DELETE,SELECT を指定できます。ただし、必要な操作に絞らないとログが増えます。
Q. ハンドラでメール送信してもよいですか?
A. 可能ですが、監査対象SQLの実行経路に入るため重い処理は避けるべきです。まずはログ表へ書き込み、別ジョブで通知する構成が安全です。
Q. 統合監査環境ではどのビューを見ますか?
A. UNIFIED_AUDIT_TRAIL を確認します。古い構成や移行前の環境では DBA_FGA_AUDIT_TRAIL も確認対象になります。

まとめ

FGAは、Oracleで機密データへのアクセスを条件付きで監査したい場合に強力です。DBMS_FGA.ADD_POLICY で対象表、条件、列、SQL種別を指定し、DBA_FGA_AUDIT_TRAILUNIFIED_AUDIT_TRAIL で監査結果を確認します。

PL/SQLハンドラを使うと独自ログや通知に発展できますが、重い処理や再帰監査は避ける必要があります。まずは対象を絞ったポリシーを作り、ログ量・性能・運用フローを確認しながら本番適用するのが安全です。

参考: Oracle Database PL/SQL Packages and Types Reference – DBMS_FGA