権限分析機能を試す (Oracle Database 12c)

Oracle Database 12cの新機能である権限分析（Privilege Analysis）機能を試します（実行はOracle Database 19c）。アプリケーション・ユーザーが使用している権限をキャプチャし、必要な権限と不要な権限を視覚化するための機能です。
この機能の利用には従来 Database Vault オプションが必要でしたが、Oracle Database 18c から Enterprise Edition の標準ライセンスで利用できるようになりました。


# 準備
  ここではアプリケーション用のユーザーを作成し、いくつか権限を付与ます。既存のアプリケーションでテストする場合は当然不要です。

```
SQL> CREATE USER priv1 IDENTIFIED BY priv1 DEFAULT TABLESPACE USERS TEMPORARY TABLESPACE temp;

ユーザーが作成されました。

SQL> GRANT CREATE SESSION, CREATE TABLE, UNLIMITED TABLESPACE, CREATE SEQUENCE, CREATE PROCEDURE TO priv1;

権限付与が成功しました。
```

DBMS_PRIVILEGE_CAPTURE.CREATE_CAPTUREプロシージャを実行して、権限のキャプチャを行う準備をします。name パラメーターには一意な名前、typeパラメーターには取得するタイプを指定します。
このプロシージャはCAPTURE_ROLEロールを持ったユーザーが実行します。

|typeパラメータ|説明|
|:---|:---|
|G_DATABASE|データベース全体のキャプチャ (SYS以外)|
|G_ROLE|特定のロールをキャプチャ|
|G_CONTEXT|特定のコンテキストの評価式がTRUEになる場合にキャプチャ|
|G_ROLE_AND_CONTEXT|特定のコンテキストの評価式がTRUEになり、指定したロール内の場合にキャプチャ|

descriptionパラメーターにはコメントを記述することができます。roles オプションや context オプションは、typeパラメーターにG_ROLEやG_CONTEXTを指定した時に必要です。
下記の例ではタイプにG_DATABASEを指定してポリシーを作成しています。実際にキャプチャを開始するにはDBMS_PRIVILEGE_CAPTURE.ENABLE_CAPTURE
プロシージャを実行します。
  状態の確認はDBA_PRIV_CAPTURESビューを参照しますが、ENABLE_CAPTUREプロシージャとDISABLE_CAPTUREプロシージャを実行する度にレコードが追加されていきます。

```
SQL> EXEC DBMS_PRIVILEGE_CAPTURE.CREATE_CAPTURE(name=>'db1', type=>DBMS_PRIVILEGE_CAPTURE.G_DATABASE);

PL/SQLプロシージャが正常に完了しました。

SQL> EXEC DBMS_PRIVILEGE_CAPTURE.ENABLE_CAPTURE('db1');

PL/SQLプロシージャが正常に完了しました。

SQL> SELECT NAME, TYPE, ENABLED FROM DBA_PRIV_CAPTURES;

NAME                 TYPE                 E
-------------------- -------------------- -
db1                  DATABASE             Y
ORA$DEPENDENCY       DATABASE             N

SQL>
```

# アプリケーションの実行
 権限のキャプチャが開始されてからアプリケーションを実行します。使用された権限がSYSAUX表領域内に格納されます。下記の例では自動採番列を持ったテーブルの作成、レコードの挿入だけを実行しています。

```
$ sqlplus priv1/priv1

SQL*Plus: Release 19.0.0.0.0 - Production on 水 10月 9 23:47:02 2019
Version 19.3.0.0.0

Copyright (c) 1982, 2019, Oracle.  All rights reserved.



Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0
に接続されました。

SQL> CREATE TABLE gen1 (id NUMBER GENERATED ALWAYS AS IDENTITY, val VARCHAR2(10)) ;

表が作成されました。

SQL> INSERT INTO gen1(val) VALUES ('data1');

1行が作成されました。

SQL> COMMIT;

コミットが完了しました。

SQL>
```

# レポート作成
  キャプチャが完了したらDBMS_PRIVILEGE_CAPTURE.GENERATE_RESULTプロシージャを実行します。DBMS_PRIVILEGE_CAPTURE.DISABLE_CAPTUREプロシージャによりキャプチャを無効にしないとこのプロシージャは実行できません。
DBMS_PRIVILEGE_CAPTURE.GENERATE_RESULTプロシージャを実行すると、DBA_USED_{PRIVS|SYSPRIVS|OBJPRIVS} ビュー、DBA_UNUSED_{PRIVS|SYSPRIVS|OBJPRIVS} ビューから使用した（または使用しなかった）権限を確認することができるようになります。
これらのビューの検索もはCAPTURE_ROLEロール持ったユーザーが実行します。

```
SQL> EXEC DBMS_PRIVILEGE_CAPTURE.GENERATE_RESULT('db1');
BEGIN DBMS_PRIVILEGE_CAPTURE.GENERATE_RESULT('db1'); END;

*
行1でエラーが発生しました。:
ORA-47932: 権限の取得db1は有効化されています。 ORA-06512:
"SYS.DBMS_PRIVILEGE_CAPTURE", 行61
ORA-06512: 行1


SQL> EXEC DBMS_PRIVILEGE_CAPTURE.DISABLE_CAPTURE('db1');

PL/SQLプロシージャが正常に完了しました。

SQL> EXEC DBMS_PRIVILEGE_CAPTURE.GENERATE_RESULT('db1');

PL/SQLプロシージャが正常に完了しました。

SQL> SELECT SYS_PRIV, OBJ_PRIV, USER_PRIV, OBJECT_OWNER, OBJECT_NAME FROM DBA_USED_PRIVS WHERE CAPTURE='db1';

SYS_PRIV             OBJ_PRIV             USER_PRIV                 OBJECT_OWNER                   OBJECT_NAME
-------------------- -------------------- ------------------------- ------------------------------ ------------------------------
CREATE SEQUENCE
UNLIMITED TABLESPACE
                     EXECUTE                                        SYS                            DBMS_APPLICATION_INFO
CREATE SESSION
                     SELECT                                         SYS                            DUAL
                     EXECUTE                                        SYS                            DBMS_STANDARD
CREATE TABLE

7行が選択されました。

SQL> SELECT SYS_PRIV, USER_PRIV, OBJ_PRIV, OBJECT_OWNER, OBJECT_NAME FROM DBA_UNUSED_PRIVS WHERE CAPTURE='db1' AND USERNAME='PRIV1';

SYS_PRIV             USER_PRIV                 OBJ_PRIV             OBJECT_OWNER                   OBJECT_NAME
-------------------- ------------------------- -------------------- ------------------------------ ------------------------------
CREATE PROCEDURE

```

接続時にCREATE SESSIONシステム権限が使用されています。これ以外のシステム権限としてテーブルの作成（CREATE TABLE)と自動採番列の内部で使われるCREATE SEQUENCE権限の使用が出力されています。またクオータ設定が無い表領域内のテーブルに対してレコードを格納したため、UNLIMITED TABLESPACEシステム権限が使用されています。
DBMS_APPLICATION_INFOパッケージ、DUALテーブルに対するアクセスはアプリケーションとしては実行していませんが、SQL*Plus等から自動実行されたプログラムによるものと思われます。

DBA_UNUSED_PRIVSビューからはCREATE PROCEDUREシステム権限が使われていないことがわかります。