Oracle 12c introduced the DBMS_PRIVILEGE_CAPTURE package, which allows you to track the privileges being used, making it much simpler to perform privilege analysis, which in turn allows you to revoke unnecessary privileges and attain a least privilege state and this feature is available without any licence cost.
Step 1:
Create User:
CREATE USER Test_User I DENTIFIED BY test;
GRANT DBA, RESOURCE TO Test_User;
A user-defined condition, when user is Test_User (type = g_role_and_context):
BEGIN
DBMS_PRIVILEGE_CAPTURE.create_capture(
name => 'Test_User_pa',
type => DBMS_PRIVILEGE_CAPTURE.g_role_and_context,
roles => role_name_list('DBA', 'RESOURCE'),
condition => 'SYS_CONTEXT(''USERENV'', ''SESSION_USER'') = ''Test_User'''
);
DBMS_PRIVILEGE_CAPTURE.enable_capture(
name => 'Test_User_pa'
);
END;
/
Verify that the capture is defined and enabled:
COLUMN ROLES FORMAT a20
COLUMN CONTEXT FORMAT a30
COLUMN ENABLED FORMAT a7
SELECT name
, TYPE
, enabled
, roles
, context
FROM dba_priv_captures
ORDER BY name;
Run the Following transaction with user Test_user
CREATE TABLE tab1 (
id NUMBER,
description VARCHAR2(50),
CONSTRAINT tab1_px PRIMARY KEY (id)
);
CREATE SEQUENCE tab1_seq;
CREATE VIEW tab1_view AS
SELECT * FROM tab1;
INSERT INTO tab1
SELECT level, 'Description of ' || TO_CHAR(level)
FROM dual
CONNECT BY level <= 5;
COMMIT;
SELECT name FROM v$database;
Step 3:
Stop the capture and generate the results:
BEGIN
DBMS_PRIVILEGE_CAPTURE.disable_capture ( 'Test_User_pa' );
DBMS_PRIVILEGE_CAPTURE.generate_result ( 'Test_User_pa' );
END;
/
Step 4:
Query system privileges results:
SELECT username, sys_priv
FROM dba_used_sysprivs
WHERE capture = 'Test_User_pa'
ORDER BY username, sys_priv;
Query object privileges results:
SELECT username
, obj_priv
, object_owner
, object_name
, object_type
FROM dba_used_objprivs
WHERE capture = 'Test_User_pa';
Investigate system privileges:
SELECT username
, sys_priv
, used_role
, PATH
FROM dba_used_sysprivs_path
WHERE capture = 'Test_User_pa'
ORDER BY username, sys_priv;
Investigate object privileges:
SELECT username
, obj_priv
, object_owner
, object_name
, used_role
, PATH
FROM dba_used_objprivs_path
WHERE capture = 'Test_User_pa';
Step 6:
At the end, drop the capture definition:
BEGIN
DBMS_PRIVILEGE_CAPTURE.drop_capture ( 'Test_User_pa' );
END;
/
Step 1:
Create User:
CREATE USER Test_User I DENTIFIED BY test;
GRANT DBA, RESOURCE TO Test_User;
A user-defined condition, when user is Test_User (type = g_role_and_context):
BEGIN
DBMS_PRIVILEGE_CAPTURE.create_capture(
name => 'Test_User_pa',
type => DBMS_PRIVILEGE_CAPTURE.g_role_and_context,
roles => role_name_list('DBA', 'RESOURCE'),
condition => 'SYS_CONTEXT(''USERENV'', ''SESSION_USER'') = ''Test_User'''
);
DBMS_PRIVILEGE_CAPTURE.enable_capture(
name => 'Test_User_pa'
);
END;
/
Verify that the capture is defined and enabled:
COLUMN ROLES FORMAT a20
COLUMN CONTEXT FORMAT a30
COLUMN ENABLED FORMAT a7
SELECT name
, TYPE
, enabled
, roles
, context
FROM dba_priv_captures
ORDER BY name;
Run the Following transaction with user Test_user
CREATE TABLE tab1 (
id NUMBER,
description VARCHAR2(50),
CONSTRAINT tab1_px PRIMARY KEY (id)
);
CREATE SEQUENCE tab1_seq;
CREATE VIEW tab1_view AS
SELECT * FROM tab1;
INSERT INTO tab1
SELECT level, 'Description of ' || TO_CHAR(level)
FROM dual
CONNECT BY level <= 5;
COMMIT;
SELECT name FROM v$database;
Step 3:
Stop the capture and generate the results:
BEGIN
DBMS_PRIVILEGE_CAPTURE.disable_capture ( 'Test_User_pa' );
DBMS_PRIVILEGE_CAPTURE.generate_result ( 'Test_User_pa' );
END;
/
Step 4:
Query system privileges results:
SELECT username, sys_priv
FROM dba_used_sysprivs
WHERE capture = 'Test_User_pa'
ORDER BY username, sys_priv;
Query object privileges results:
SELECT username
, obj_priv
, object_owner
, object_name
, object_type
FROM dba_used_objprivs
WHERE capture = 'Test_User_pa';
Investigate system privileges:
SELECT username
, sys_priv
, used_role
, PATH
FROM dba_used_sysprivs_path
WHERE capture = 'Test_User_pa'
ORDER BY username, sys_priv;
Investigate object privileges:
SELECT username
, obj_priv
, object_owner
, object_name
, used_role
, PATH
FROM dba_used_objprivs_path
WHERE capture = 'Test_User_pa';
Step 6:
At the end, drop the capture definition:
BEGIN
DBMS_PRIVILEGE_CAPTURE.drop_capture ( 'Test_User_pa' );
END;
/