Oracleデータベースを安全に運用するには、ユーザーに「必要最小限の権限」だけを与えることが重要です。不要な権限が残っていると、外部からの攻撃に悪用されたり、誤操作で重要なデータが変更されるリスクが高まります。こうしたリスクを避けるための解決策として有効なのが DBMS_PRIVILEGE_CAPTURE です。この機能は「どの権限が実際に使われたか」を記録し、必要な権限と不要な権限を明確に区別できます。この記事では、その仕組みと実際の利用方法、よくあるトラブルや運用上の注意点まで、丁寧に解説します。
💰 【PR】Oracleエンジニアの市場価値、調べてみませんか?
Oracleのスキルは需要が高く、特定の資格や経験を持っていると年収が大幅にアップするケースがあります。まずはIT専門のエージェントで非公開求人をチェックしてみませんか?
ステップ概要(最短手順)
DBMS_PRIVILEGE_CAPTUREを使う際の基本的な流れは以下の通りです。初めて利用する方は、この手順をざっと押さえてから詳細に進むと理解しやすくなります。
- 管理用ユーザーに
CAPTURE_ADMIN権限を付与する。 DBMS_PRIVILEGE_CAPTURE.CREATE_CAPTUREで調査用のポリシーを作成する。...ENABLE_CAPTUREで記録を開始し、対象ユーザーに実際の操作を行わせる。操作が終わったら...DISABLE_CAPTUREで停止する。...GENERATE_RESULTを実行し、結果を確定して辞書ビューから使用状況を確認する。- 「不要」と判断できた権限を段階的に削除(REVOKE)。問題があれば元に戻せるようにバックアップを準備しておく。
DBMS_PRIVILEGE_CAPTUREとは?
DBMS_PRIVILEGE_CAPTUREは、Oracleが提供するセキュリティ機能のひとつで、ユーザーやロールに与えられた権限のうち、実際に使用されたものと使用されなかったものを区別して記録できます。これにより、実運用に基づいた「最小権限化」をデータベース上で実現することが可能です。
例えば「このユーザーにSELECT権限を与えているが、実際にはINSERTやUPDATEも使っていないか?」といった疑問を解決できます。記録の結果を基にすれば、「使われていない権限は外す」といった安全な権限整理が可能になります。
調査の種類
DBMS_PRIVILEGE_CAPTUREにはいくつかの調査モードがあります。用途に応じて使い分けます。
| タイプ | 調べる対象 | 利用例 |
|---|---|---|
G_DATABASE | データベース全体(SYSは除外) | 全体的にどの権限が利用されているか把握したい場合 |
G_ROLE | 指定ロールが有効なセッション | アプリケーション専用ロールが実際に利用されているか確認 |
G_CONTEXT | 条件に合うセッションのみ | 特定のユーザーやモジュールだけに限定して調査 |
G_ROLE_AND_CONTEXT | ロールと条件の両方を満たす場合 | 本番アプリケーションの一部利用状況を限定的に確認 |
G_CONTEXTの条件はSYS_CONTEXT関数で指定します。例えば「ログインユーザーが APP_USER の場合のみ」といった条件設定が可能です。
利用前の前提条件
DBMS_PRIVILEGE_CAPTUREを使う前に、次の条件を確認してください。
- 対象バージョン:Oracle Database 19c(非CDB構成)
- OS:Linux
- 必要権限:
CAPTURE_ADMINを持つ管理ユーザー - 制限:同時に有効化できるポリシーは最大2つまで
- 注意:
SYSユーザーは対象外(記録されません)
これらを満たしていない場合は、事前に環境を整えておきましょう。
実際の使い方とサンプル
以下は実際に使う手順です。サンプルユーザーを作成し、ロールを利用して権限を付与・確認する一連の流れを紹介します。
0. 検証用ユーザーとオブジェクトの準備
サンプルユーザーや表を作成し、後で権限利用を確認できる環境を整えます。
-- 管理者ユーザーで
CREATE USER app_owner IDENTIFIED BY "AppOwner#1" QUOTA UNLIMITED ON users;
GRANT CREATE SESSION, CREATE TABLE TO app_owner;
CREATE USER app_user IDENTIFIED BY "AppUser#1";
GRANT CREATE SESSION TO app_user;
CREATE ROLE r_app_read;
-- app_owner でサンプル表を作成
CONN app_owner/"AppOwner#1"
CREATE TABLE emp (
empno NUMBER PRIMARY KEY,
ename VARCHAR2(30)
);
INSERT INTO emp VALUES (7369, 'SMITH');
COMMIT;
-- 管理者に戻ってロールへ権限を与える
CONN / AS SYSDBA
GRANT SELECT ON app_owner.emp TO r_app_read;
GRANT r_app_read TO app_user;
この時点で app_user は直接権限を持たず、ロールを介して emp 表を参照できる状態になります。
1. 分析用ユーザーの作成
CREATE USER secadmin IDENTIFIED BY "SecAdmin#1";
GRANT CREATE SESSION TO secadmin;
GRANT CAPTURE_ADMIN TO secadmin;
secadmin ユーザーは分析ポリシーを作成・有効化し、結果を確認するための管理ユーザーです。
2. ポリシーを作成
特定ユーザー(例:APP_USER)に限定して権限利用を調査します。
CONN secadmin/"SecAdmin#1"
BEGIN
DBMS_PRIVILEGE_CAPTURE.CREATE_CAPTURE(
name => 'PA_APPUSER',
type => DBMS_PRIVILEGE_CAPTURE.G_CONTEXT,
condition => 'SYS_CONTEXT(''USERENV'',''SESSION_USER'') = ''APP_USER'''
);
END;
/
3. 記録を開始して操作を実行
BEGIN
DBMS_PRIVILEGE_CAPTURE.ENABLE_CAPTURE(name => 'PA_APPUSER');
END;
/
-- app_user でアクセス
CONN app_user/"AppUser#1"
SELECT * FROM app_owner.emp WHERE empno = 7369;
-- 記録を停止
CONN secadmin/"SecAdmin#1"
BEGIN
DBMS_PRIVILEGE_CAPTURE.DISABLE_CAPTURE(name => 'PA_APPUSER');
END;
/
4. 結果を確認
BEGIN
DBMS_PRIVILEGE_CAPTURE.GENERATE_RESULT(name => 'PA_APPUSER');
END;
/
-- 使用された権限
SELECT username, used_role, obj_priv, object_name
FROM dba_used_objprivs
WHERE capture = 'PA_APPUSER';
-- 使用されなかった権限
SELECT username, rolename, obj_priv, object_name
FROM dba_unused_objprivs
WHERE capture = 'PA_APPUSER';
ここで dba_used_objprivs に権限が表示されれば「その権限が実際に使われた」ことを意味します。一方で dba_unused_objprivs に出てきた場合は「期間中に利用されなかった」ことを示します。
コマンド実行結果
SQL> set lin 1000 pages 1000
SQL> col username for a20
SQL> col used_role for a20
SQL> col obj_priv for a20
SQL> col object_name for a30
SQL> SELECT username, used_role, obj_priv, object_name
2 FROM dba_used_objprivs
3 WHERE capture = 'PA_APPUSER';
USERNAME USED_ROLE OBJ_PRIV OBJECT_NAME
-------------------- -------------------- -------------------- ------------------------------
APP_USER PUBLIC EXECUTE DBMS_APPLICATION_INFO
APP_USER R_APP_READ SELECT EMP
APP_USER PUBLIC SELECT DUAL
SQL> SELECT username, rolename, obj_priv, object_name
2 FROM dba_unused_objprivs
3 WHERE capture = 'PA_APPUSER';
no rows selected
💰 【PR】Oracleエンジニアの市場価値、調べてみませんか?
Oracleのスキルは需要が高く、特定の資格や経験を持っていると年収が大幅にアップするケースがあります。まずはIT専門のエージェントで非公開求人をチェックしてみませんか?
5. ポリシーの削除(片付け)
調査が終わったらポリシーを削除して不要なデータを整理します。
BEGIN
DBMS_PRIVILEGE_CAPTURE.DROP_CAPTURE(name => 'PA_APPUSER');
END;
/
トラブルシューティング
DBMS_PRIVILEGE_CAPTUREを利用する際に遭遇しやすいエラーと対処法をまとめます。
| エラー | 主な原因 | 確認・対処方法 |
| ORA-01031 | CAPTURE_ADMIN が付与されていない | GRANT CAPTURE_ADMIN TO ユーザー名; を実行して再試行 |
| ORA-47934 | すでに2つのポリシーが有効 | SELECT name, enabled FROM dba_priv_captures; で確認し不要なものを無効化 |
| 結果が空 | 対象操作が行われていない/条件が厳しすぎる | 条件を緩めて再試行するか、G_DATABASE を利用して広く確認 |
| SYSの結果がない | 仕様 | SYSユーザーは対象外なので設計時に考慮が必要 |
注意事項
- SYSAUX領域の管理:結果はSYSAUX表領域に保存されます。長期間放置すると容量が増加するため、定期的に不要なデータを削除してください。
- 未使用権限の解釈:期間中に使われなかった権限でも、月次や年次の処理で利用される可能性があります。観測期間はできるだけ十分に設定しましょう。
- 権限削除のリスク:不要と判断して権限を削除する場合は、必ずバックアップを取り、万一問題があればすぐにGRANTで戻せるよう準備しておきましょう。
- 運用設計の工夫:本番環境では常時ONにするよりも、業務イベントやリリース時にON/OFFを切り替える運用のほうが効率的です。
よくある質問(FAQ)
Q1. 特定のユーザーだけを調べる方法は?
→ G_CONTEXT を使い、SYS_CONTEXT('USERENV','SESSION_USER')='APP_USER' と条件指定します。
Q2. 確認する主なビューは?
→ DBA_USED_OBJPRIVS と DBA_UNUSED_OBJPRIVS が基本です。必要に応じて “_PATH” が付いたビューを利用すれば付与経路まで追えます。
Q3. 常にONにしても良いですか?
→ 技術的には可能ですが、SYSAUX領域が増大するため推奨されません。期間を区切って実行するほうが安全です。
Q4. 新しいバージョン(例:23ai)で違いはありますか?
→ 基本機能は同じですが、公式ドキュメントの掲載場所や表の仕様が変更される可能性があります。バージョンごとのマニュアルを必ず確認してください。
Q5. ロール経由の権限利用も分かりますか?
→ はい。ビューの USED_ROLE 列に利用されたロール名が表示されるため、直接付与かロール経由かを区別できます。
まとめ
- DBMS_PRIVILEGE_CAPTUREを使えば「使った権限」と「使わなかった権限」を明確に判別できる。
- 特定のユーザーやモジュールを対象にする場合は
G_CONTEXTが便利。 - 同時に有効化できるポリシーは最大2つまで。
- SYSユーザーは対象外であることを理解して設計する。
- 観測期間を十分にとり、不要と判断した権限は安全に削除する。
- 結果データは必ず整理し、SYSAUX領域を圧迫しないよう注意する。
本記事は Oracle Database 19c を対象に記載しています。他のバージョンでは画面や仕様が異なる場合があります。
[参考]
Oracle Database セキュリティ・ガイド 19c
💰 【PR】Oracleエンジニアの市場価値、調べてみませんか?
Oracleのスキルは需要が高く、特定の資格や経験を持っていると年収が大幅にアップするケースがあります。まずはIT専門のエージェントで非公開求人をチェックしてみませんか?




コメント