Oracle DBMS_AUDIT_MGMT Built-In Package
Versions 11.1 - 19.3

Security Advisory
Use of this package should be monitored because it is the primary API to managing database auditing. The built-in objects, functions and procedures, provide audit administrators the ability manage the audit trail. In a mixed mode environment, these audit trails comprise the database, operating system (OS), and XML audit trails. In a unified auditing environment, they comprise the unified audit trail.

A bad actor using just one of the package's capabilities such as the FLUSH_UNIFIED_AUDIT_TRAIL with a single line of code can have a devastating impact on your compliance as well as your ability to monitor actions in the database.

The SQL provided in the "How Oracle Works" sections will show you how to determine which users have access to this package and we highly recommend you treat it like SYSDBA.
 
Recommended Security Rules

 NEVER
  • grant EXECUTE on this package to anyone that has the ability to perform actions, through DCL (Data Control Language) or DDL (Data Definition Language) that is part of what you audit (unfortunately, be default, Oracle does)
  • grant EXECUTE on this package to an administrator of Database Vault or other security options installed in your database
 WITH GREAT CARE
  • Monitor any calls to this package and watch for gaps in the audit trail that might have been caused by misuse of these tools
 CAUTIONS
  • Oracle has granted EXECUTE on this package to the EXECUTE_CATALOG_ROLE which is an example of asking the fox to protect the hen house
  • EXECUTE_CATALOG_ROLE is subsequently granted to SYS, DBA, and two other roles so to monitor access to this package you need to carefully protect all of them
 
How Oracle Works
Oracle needs to better lockdown access to this package, for example not granting EXECUTE to the EXECUTE_CATALOG_ROLE which subsequently grants EXECUTE to two other roles.

The code at right will show you the relationships and help you protect your audit trails.
DBMS_AUDIT_MGMT is an essential tool created as part of the default installation of your database. Note that Oracle has severely restricted access to only two roles and not directly to any user.

SELECT grantee, privilege, grantor
FROM dba_tab_privs
WHERE table_name = 'DBMS_AUDIT_MGMT'
ORDER BY 1;

GRANTEE              PRIVILEGE  GRANTOR
-------------------- ---------- ----------
AUDIT_ADMIN          EXECUTE    AUDSYS
EXECUTE_CATALOG_ROLE EXECUTE    AUDSYS

What we see is that a number of Oracle schemas require access to this package and Oracle has explicitly granted them EXECUTE. This is likely intentional on Oracle's part because they "expect" that organizations interested in securing their database will drop the grant to PUBLIC.

SELECT grantee, admin_option, delegate_option, default_role, inherited
FROM dba_role_privs
WHERE granted_role = 'AUDIT_ADMIN'
ORDER BY 1;

GRANTEE                        ADM DEL DEF INH
------------------------------ --- --- --- ---
SYS                            YES NO  YES NO

SELECT grantee, admin_option, delegate_option, default_role, inherited
FROM dba_role_privs
WHERE granted_role = 'EXECUTE_CATALOG_ROLE'
ORDER BY 1;

GRANTEE                        ADM DEL DEF INH
------------------------------ --- --- --- ---
DBA                            NO  NO  YES NO
EXP_FULL_DATABASE              NO  NO  YES NO
IMP_FULL_DATABASE              NO  NO  YES NO
SYS                            YES NO  YES NO

As you can see from the above SQL, EXECUTE is granted to the AUDIT_ADMIN_ROLE which is subsequently granted to SYS. SYS is probably the last user in the database that should have the ability to alter the audit trail as SYS has more escalated privileges than any other user.

EXECUTE is also granted to the EXECUTE_CATALOG_ROLE which again grants privileges to SYS, then grants to everyone with the DBA role, plus to EXP_FULL_DATABASE and IMP_FULL_DATABASE which are often treated a not being highly privileged accounts even though they both have a number of escalated privileges.

If you are not paying attention to DBMS_AUDIT_MGMT then you are not paying attention to the security of your database.
 
DBMS_AUDIT_MGMT Package Information
AUTHID DEFINER
Constants
Name Data Type Value
Audit Trail types
AUDIT_TRAIL_AUD_STD NUMBER 1
AUDIT_TRAIL_FGA_STD NUMBER 2
AUDIT_TRAIL_DB_STD (both AUD + FGA) NUMBER 3
AUDIT_TRAIL_OS NUMBER 4
AUDIT_TRAIL_XML NUMBER 8
AUDIT_TRAIL_FILES (both OS & XML) NUMBER 12
AUDIT_TRAIL_ALL NUMBER 15
OS Audit File Configuration parameters
OS_FILE_MAX_SIZE NUMBER 16
OS_FILE_MAX_AGE NUMBER 17
Miscellaneous
CLEAN_UP_INTERVAL NUMBER 21
DB_AUDIT_TABLEPSACE NUMBER 22
DB_DELETE_BATCH_SIZE NUMBER 23
TRACE_LEVEL NUMBER 24
AUD_TAB_MOVEMENT_FLAG NUMBER 25
FILE_DELETE_BATCH_SIZE NUMBER 26
Purge Job Status values
PURGE_JOB_ENABLE NUMBER 31
PURGE_JOB_DISABLE NUMBER 32
NG Audit Trail write mode configuration
AUDIT_TRAIL_WRITE_MODE NUMBER 33
Write Mode values
AUDIT_TRAIL_QUEUED_WRITE NUMBER 1
AUDIT_TRAIL_IMMEDIATE_WRITE NUMBER 2
Trace Level values
TRACE_LEVEL_DEBUG PLS_INTEGER 1
TRACE_LEVEL_ERROR PLS_INTEGER 2
Unified Audit Trail
AUDIT_TRAIL_UNIFIED NUMBER 51
Container Values
CONTAINER_CURRENT NUMBER 1
CONTAINER_ALL NUMBER 2
Flush Types
FLUSH_CURRENT_INSTANCE NUMBER 1
FLUSH_ALL_INSTANCES NUMBER 2
Partition Interview
DEFAULT_INTERVAL_NUMBER NUMBER 1
DEFAULT_INTERVAL_FREQUENCY VARCHAR2(5) 'MONTH'
Dependencies
ALL_TAB_COLS DBA_USERS DUAL
AMGT$DATAPUMP DBMS_ASSERT GET_AUD_PDB_LIST
AUD_PDB_LIST DBMS_AUDIT_MGMT_LIB GV$INSTANCE
DAM_CLEANUP_JOBS$ DBMS_INTERNAL_LOGSTDBY OBJ$
DAM_CONFIG_PARAM$ DBMS_LOCK PLITBLM
DAM_LAST_ARCH_TS$ DBMS_PDB_EXEC_SQL REGISTRY$
DBA_AUDIT_MGMT_CONFIG_PARAMS DBMS_SCHEDULER V$CONTAINERS
DBA_FREE_SPACE DBMS_SQL V$DATABASE
DBA_TABLES DBMS_STANDARD V$INSTANCE
DBA_TABLESPACES DBMS_STATS V$OPTION
DBA_TAB_PARTITIONS DBMS_UTILITY V$VERSION
Documented Yes
Exceptions
Error Code Reason
ORA-46273 DBMS_AUDIT_MGMT operation failed in one of the PDB
ORA-55906 Secure file log [id: 0 name: ORA$AUDIT_NEXTGEN_LOG] does not exist
First Available 11.1.0.7
Security Model Owned by AUDSYS with EXECUTE granted to the AUDIT_ADMIN and EXECUTE_CATALOG_ROLE roles
Source {ORACLE_HOME}/rdbms/admin/dbmsamgt.sql
Subprograms
 
ALTER_PARTITION_INTERVAL
Alters the interval of partitioned table AUDSYS.AUD$UNIFIED dbms_audit_mgmt.alter_partition_interval(
interval_number    IN PLS_INTEGER := DEFAULT_INTERVAL_NUMBER,
interval_frequency IN VARCHAR2    := DEFAULT_INTERVAL_FREQUENCY);
exec dbms_audit_mgmt.alter_partition_interval(dbms_audit_mgmt.default_interval_frequency, 'DAY');
 
CLEAN_AUDIT_TRAIL
Deletes entries in audit trail according to the timestamp set in set_last_archive_timestamp dbms_audit_mgmt.clean_audit_trail(
audit_trail_type        IN PLS_INTEGER,
use_last_arch_timestamp IN BOOLEAN     := TRUE,
container               IN PLS_INTEGER := CONTAINER_CURRENT,
database_id             IN NUMBER      := NULL,
container_guid          IN VARCHAR2    := NULL);
See IS_CLEANUP_INITIALIZED Demo Below
 
CLEAR_AUDIT_TRAIL_PROPERTY
Clears an audit trail property dbms_audit_mgmt.clear_audit_trail_property(
audit_trail_type     IN PLS_INTEGER,
audit_trail_property IN PLS_INTEGER,
use_default_values   IN BOOLEAN := FALSE);
DECLARE
 att NUMBER := dbms_audit_mgmt.audit_trail_os;
 atp NUMBER := dbms_audit_mgmt.os_file_max_age;
BEGIN
  dbms_audit_mgmt.set_audit_trail_property(att, atp, 30);
  dbms_audit_mgmt.clear_audit_trail_property(att, atp, TRUE);
END;
/
 
CLEAR_LAST_ARCHIVE_TIMESTAMP
Deletes the timestamp set by set_last_archive_timestamp dbms_audit_mgmt.clear_last_archive_timestamp(
audit_trail_type    IN PLS_INTEGER,
rac_instance_number IN PLS_INTEGER := NULL,
container           IN PLS_INTEGER,
database_id         IN NUMBER,
container_guid      IN RAW);
DECLARE
 att NUMBER := dbms_audit_mgmt.audit_trail_os;
BEGIN
  dbms_audit_mgmt.clear_last_archive_timestamp(att, NULL, dbms_audit_mgmt.container_all);
  dbms_audit_mgmt.clear_last_archive_timestamp(att, NULL, dbms_audit_mgmt.container_all);
  dbms_audit_mgmt.clear_last_archive_timestamp(att, NULL, dbms_audit_mgmt.container_all);
END;
/
 
CREATE_PURGE_JOB
Creates a purge job for an audit trail dbms_audit_mgmt.create_purge_job(
audit_trail_type           IN PLS_INTEGER,
audit_trail_purge_interval IN PLS_INTEGER,
audit_trail_purge_name     IN VARCHAR2,
use_last_arch_timestamp    IN BOOLEAN     := TRUE,
container                  IN PLS_INTEGER := CONTAINER_CURRENT);
DECLARE
 att NUMBER := dbms_audit_mgmt.audit_trail_aud_std;
 pje NUMBER := dbms_audit_mgmt.purge_job_enable;
BEGIN
  dbms_audit_mgmt.create_purge_job(att, 48, 'UW_PURGE', TRUE);
  dbms_audit_mgmt.set_purge_job_interval('UW_PURGE', 48);
  dbms_audit_mgmt.set_purge_job_status('UW_PURGE', pje, dbms_audit_mgmt.container_all);
  dbms_audit_mgmt.drop_purge_job('UW_PURGE');
END;
/
 
DEINIT_CLEANUP
De-Initialize DBMS_AUDIT_MGMT dbms_audit_mgmt.deinit_cleanup(
audit_trail_type IN PLS_INTEGER,
container        IN PLS_INTEGER  := CONTAINER_CURRENT);
See IS_CLEANUP_INITIALIZED Demos Below
 
DROP_OLD_UNIFIED_AUDIT_TABLES
Drops the given Old Unified Audit (CLI based) tables dbms_audit_mgmt.drop_old_unified_audit_tables(container_guid IN VARCHAR2);
SELECT con_id, name, guid
FROM v$pdbs
ORDER BY 1;

exec dbms_audit_mgmt.drop_old_unified_audit_tables('4C690F3954EC4B2FBECFAA0CFA1BD955');
 
DROP_PURGE_JOB
Drops the purge job for an audit trail dbms_audit_mgmt.drop_purge_job(audit_trail_purge_name IN VARCHAR2);
See CREATE_PURGE_JOB Demo Above
 
FLUSH_UNIFIED_AUDIT_TRAIL
Writes the unified audit trail records in the SGA queue to disk dbms_audit_mgmt.flush_unified_audit_trail(
flush_type IN PLS_INTEGER := FLUSH_CURRENT_INSTANCE,
container  IN PLS_INTEGER := CONTAINER_CURRENT);
DECLARE
 flt PLS_INTEGER := dbms_audit_mgmt.flush_current_instance;
 con PLS_INTEGER := dbms_audit_mgmt.container_current;
BEGIN
  dbms_audit_mgmt.flush_unified_audit_trail(flt, con);
END;
/
 
GET_AUDIT_COMMIT_DELAY
GETs the audit commit delay set in the database. The default is 15. dbms_audit_mgmt.get_audit_commit_delay RETURN PLS_INTEGER;
SELECT dbms_audit_mgmt.get_audit_commit_delay
FROM dual;
 
GET_AUDIT_TRAIL_PROPERTY_VALUE
Retrieves the value of the property set by set_audit_trail_property dbms_audit_mgmt.get_audit_trail_property_value(
audit_trail_type     IN PLS_INTEGER,
audit_trail_property IN PLS_INTEGER)
RETURN NUMBER;
DECLARE
 att PLS_INTEGER := dbms_audit_mgmt.audit_trail_os;
 atp PLS_INTEGER := dbms_audit_mgmt.os_file_max_age;
 n   NUMBER;
BEGIN
 n := dbms_audit_mgmt.get_audit_trail_property_value(att, atp);
END;
/
 
GET_CLI_PART_ORANUM
Returns the ORACLE NUMBER corresponding to the HIGH_VALUE of CLI Partition dbms_audit_mgmt.get_cli_part_oranum(partname IN VARCHAR2)
RETURN NUMBER;
SELECT dbms_audit_mgmt.get_cli_part_oranum('AUD_UNIFIED_P0')
FROM dual;
 
GET_LAST_ARCHIVE_TIMESTAMP
Returns the timestamp set by set_last_archive_timestamp for the current instance dbms_audit_mgmt.get_last_archive_timestamp(audit_trail_type IN PLS_INTEGER) RETURN TIMESTAMP;
DECLARE
 att NUMBER := dbms_audit_mgmt.audit_trail_aud_std;
 lat TIMESTAMP := TO_TIMESTAMP('15-MAR-17 14:42:42.00','DD-MON-YYYY HH24:MI:SS.FF');
BEGIN
  dbms_audit_mgmt.init_cleanup(att, 24, dbms_audit_mgmt.container_all);
  dbms_audit_mgmt.set_last_archive_timestamp(att, lat, NULL);
END;
/

DECLARE
 att PLS_INTEGER := dbms_audit_mgmt.audit_trail_xml;
 tsp TIMESTAMP;
BEGIN
  tsp := dbms_audit_mgmt.get_last_archive_timestamp(att);
END;
/

DECLARE
 att NUMBER := dbms_audit_mgmt.audit_trail_aud_std;
BEGIN
  IF dbms_audit_mgmt.is_cleanup_initialized(att, dbms_audit_mgmt.container_all) THEN
    dbms_output.put_line('Cleanup Is Initialized');
    dbms_audit_mgmt.deinit_cleanup(att, dbms_audit_mgmt.container_all);
  END IF;
END;
/
 
GET_PART_HIGHVAL_AS_CHAR
Returns the aud$unified table partition HIGH_VALUE as a VARCHAR2. dbms_audit_mgmt.get_part_highval_as_char(partname IN VARCHAR2)
RETURN VARCHAR2;
SELECT partition_name
FROM dba_tab_partitions
WHERE table_name = 'AUD$UNIFIED';

PARTITION_NAME
------------------------------
AUD_UNIFIED_P0
SYS_P1311
SYS_P185
SYS_P2172
SYS_P2501
SYS_P3367
SYS_P3651
SYS_P687

SELECT dbms_audit_mgmt.get_part_highval_as_char('AUD_UNIFIED_P0')
FROM dual;

DBMS_AUDIT_MGMT.GET_PART_HIGHVAL_AS_CHAR('AUD_UNIFIED_P0')
----------------------------------------------------------
2014-07-01 00:00:00

SELECT dbms_audit_mgmt.get_part_highval_as_char('SYS_P687')
FROM dual;

DBMS_AUDIT_MGMT.GET_PART_HIGHVAL_AS_CHAR('AUD_UNIFIED_P0')
----------------------------------------------------------
2019-01-01 00:00:00
INIT_CLEANUP
Initializes DBMS_AUDIT_MGMT dbms_audit_mgmt.init_cleanup(
audit_trail_type         IN PLS_INTEGER,
default_cleanup_interval IN PLS_INTEGER,
container                IN PLS_INTEGER := CONTAINER_CURRENT);
DECLARE
 att NUMBER := dbms_audit_mgmt.audit_trail_aud_std;
BEGIN
  dbms_audit_mgmt.init_cleanup(att, 24, dbms_audit_mgmt.container_all);
END;
/

-- this may take awhile to complete
 
IS_CLEANUP_INITIALIZED
returns TRUE if Audit Cleanup is initialized for the audit trail type, otherwise FALSE

Overload 1
dbms_audit_mgmt.is_cleanup_initialized(
audit_trail_type IN PLS_INTEGER,
container        IN PLS_INTEGER)
RETURN BOOLEAN;
set serveroutput on

DECLARE
 att NUMBER := dbms_audit_mgmt.audit_trail_aud_std;
BEGIN
  IF dbms_audit_mgmt.is_cleanup_initialized(att, dbms_audit_mgmt.container_all) THEN
    dbms_output.put_line('Cleanup Is Initialized');
    dbms_audit_mgmt.set_audit_trail_location(att, 'UWDATA');
    dbms_audit_mgmt.deinit_cleanup(att, dbms_audit_mgmt.container_all);
  ELSE
    dbms_output.put_line('Cleanup Was Not Initialized');
    dbms_audit_mgmt.init_cleanup(att, 24, dbms_audit_mgmt.container_all);
    dbms_audit_mgmt.clean_audit_trail(att, TRUE, dbms_audit_mgmt.container_all);
  END IF;
END;
/
Overload 2 dbms_audit_mgmt.is_cleanup_initialized(
audit_trail_type   IN PLS_INTEGER,
container          IN PLS_INTEGER,
uninitialized_pdbs IN dbms_sql.varchar2s)
RETURN BOOLEAN;
set serveroutput on

DECLARE
 att    NUMBER := dbms_audit_mgmt.audit_trail_aud_std;
 uipdbs dbms_sql.varchar2s;
BEGIN
  uipdbs(1) := 'ORADEV';
  uipdbs(2) := 'ORATEST';
  IF dbms_audit_mgmt.is_cleanup_initialized(att, 2, uipdbs) THEN
    dbms_output.put_line('TRUE');
  ELSE
    dbms_output.put_line('FALSE');
  END IF;
END;
/
 
IS_CLEANUP_INITIALIZED2
Checks if Audit Cleanup is initialized for the audit trail type and returns VARCHAR2 type dbms_audit_mgmt.is_cleanup_initialized2(
audit_trail_type IN PLS_INTEGER,
container        IN PLS_INTEGER := CONTAINER_CURRENT)
RETURN VARCHAR2;
set serveroutput on

DECLARE
 att NUMBER := dbms_audit_mgmt.audit_trail_aud_std;
 ret VARCHAR2(5);
BEGIN
  ret := dbms_audit_mgmt.is_cleanup_initialized2(att);
  dbms_output.put_line(ret);
END;
/
 
IS_DROPPABLE_PARTITION
If the identified aud$unified partition is droppable returns 1; otherwise 0 dbms_audit_mgmt.is_droppable_partition(
partname IN VARCHAR2,
lat      IN TIMESTAMP)
RETURN NUMBER;
SELECT dbms_audit_mgmt.is_droppable_partition('SYS_P185', SYSTIMESTAMP-16) AS "Ok2Drop"
FROM dual;

 Ok2Drop
--------
       1
 
LOAD_UNIFIED_AUDIT_FILES
Loads all spillover audit files to tables. container is the PDB Container in which it is executing dbms_audit_mgmt.load_unified_audit_files(
container IN PLS_INTEGER DEFAULT := CONTAINER_CURRENT);
exec dbms_audit_mgmt.load_unified_audit_files(dbms_audit_mgmt.container_current);
 
MOVE_DBAUDIT_TABLES
Moves DB audit tables to specified tablespace.

Note that the procedure, by default moves it to SYSAUX. Create your own tablespace in a location where it will be safe from being accidentally dropped.
dbms_audit_mgmt.move_dbaudit_tables(audit_trail_tbs IN VARCHAR2 DEFAULT 'SYSAUX');
CREATE TABLESPACE audit_data
DATAFILE 'u01/orabase19/oradata/orabase/auddta.dbf' SIZE 100M
LOGGING FORCE LOGGING ONLINE PERMANENT BLOCKSIZE 8192
EXTENT MANAGEMENT LOCAL UNIFORM SIZE 64K
SEGMENT SPACE MANAGEMENT AUTO;

exec dbms_audit_mgmt.move_dbaudit_tables('audit_data');

Related Topics
Auditing
DBMS_AUDIT_UTIL
DBMS_FGA
Fine Grained Auditing
Unified Audit Policies