Database Audit and Audit trail purging

There are several reason to enable database audit and at least as much reason to not enable database audit. For today I will focus on what can be done after the audit has enabled and how to get rid of the audit data quite easily. It is nothing new nor is it rocket engineering. 🙂 Ok, removing data is mostly a quite easy task, sometimes to easy…
Rather than deleting or truncating the data, I would like to user the procedures provided by DBMS_AUDIT_MGMT. This post is kind of a sequel to my post earlier this february about Manage Audit Trails with DBMS_AUDIT_MGMT

Enable Audit

Ok, first of all we have to set the corresponding init.ora parameter and enable the database audit. In my case I’ll also enable audit of all sys operation. This is not necessary when you plan to use standard audit. I just did it because I restarted the database anyway. ok lame excuse, I will come back again later on.

Set the init.ora parameter:

alter system set audit_sys_operations=true scope=spfile;

alter system set audit_trail=db_extended scope=spfile;

startup force;

show parameter audit

Initialize the audit infrastructure. In this example I’ve initialized the standard audit and set a default interval of 10 days.

BEGIN
  DBMS_AUDIT_MGMT.INIT_CLEANUP(
    AUDIT_TRAIL_TYPE => DBMS_AUDIT_MGMT.AUDIT_TRAIL_AUD_STD,
    DEFAULT_CLEANUP_INTERVAL => 240 /*hours*/
  );
END;
/

commit;

Create a dedicated tablespace for the audit data and change the location of the audit trail. If this is not done AUD$ will remain in the SYSAUX tablespace.

create tablespace audit_data datafile '/u01/oradata/TDB03/audit01TDB03.dbf' 
size 100M autoextend on next 50M maxsize 5G;

BEGIN
  DBMS_AUDIT_MGMT.SET_AUDIT_TRAIL_LOCATION(
    AUDIT_TRAIL_TYPE => DBMS_AUDIT_MGMT.AUDIT_TRAIL_AUD_STD,
    AUDIT_TRAIL_LOCATION_VALUE => 'AUDIT_DATA'
  );
END;
/

commit;

Review the audit settings

col PARAMETER_NAME for a30
col PARAMETER_VALUE for a15
col AUDIT_TRAIL for a20
select PARAMETER_NAME, PARAMETER_VALUE, AUDIT_TRAIL 
from DBA_AUDIT_MGMT_CONFIG_PARAMS 
where audit_trail = 'STANDARD AUDIT TRAIL';

PARAMETER_NAME                 PARAMETER_VALUE AUDIT_TRAIL
------------------------------ --------------- --------------------
DEFAULT CLEAN UP INTERVAL      12              STANDARD AUDIT TRAIL
DB AUDIT TABLESPACE            AUDIT_DATA      STANDARD AUDIT TRAIL
DB AUDIT CLEAN BATCH SIZE      10000           STANDARD AUDIT TRAIL

col segment_name for a10
select owner,segment_name,tablespace_name from dba_segments where segment_name ='AUD$';

OWNER                          SEGMENT_NA TABLESPACE_NAME
------------------------------ ---------- ------------------------------
SYS                            AUD$       AUDIT_DATA

Ok, the audit infrastructure has been setup and configured. Now lets enable audit for certain system privilege and objects. The first part of the following audit statements have been taken from $ORACLE_HOME/rdbms/admin/secconf.sql. This script is used in 11g to enable audit during database creation.

audit alter any table by access;
audit create any table by access;
audit drop any table by access;
audit Create any procedure by access;
audit Drop any procedure by access;
audit Alter any procedure by access;
audit Grant any privilege by access;
audit grant any object privilege by access;
audit grant any role by access;
audit audit system by access;
audit create external job by access;
audit create any job by access;
audit create any library by access;
audit create public database link by access;
audit exempt access policy by access;
audit alter user by access;
audit create user by access;
audit role by access;
audit create session by access;
audit drop user by access;
audit alter database by access;
audit alter system by access;
audit alter profile by access;
audit drop profile by access;
audit database link by access;
audit system audit by access;
audit profile by access;
audit public synonym by access;
audit system grant by access;

audit delete on sys.aud$;
audit alter on default;
audit grant on default;

There are a few data dictionary views to review which object and system privilege has audit enabled.

select  * from DBA_STMT_AUDIT_OPTS;

USER_NAME  PROXY_NAME AUDIT_OPTION                 SUCCESS    FAILURE
---------- ---------- ---------------------------- ---------- ----------
                      ALTER SYSTEM                 BY ACCESS  BY ACCESS
                      SYSTEM AUDIT                 BY ACCESS  BY ACCESS
                      CREATE SESSION               BY ACCESS  BY ACCESS
                      CREATE USER                  BY ACCESS  BY ACCESS
                      ALTER USER                   BY ACCESS  BY ACCESS
                      DROP USER                    BY ACCESS  BY ACCESS
                      PUBLIC SYNONYM               BY ACCESS  BY ACCESS
                      DATABASE LINK                BY ACCESS  BY ACCESS
                      ROLE                         BY ACCESS  BY ACCESS
                      PROFILE                      BY ACCESS  BY ACCESS
                      CREATE ANY TABLE             BY ACCESS  BY ACCESS
                      ALTER ANY TABLE              BY ACCESS  BY ACCESS
                      DROP ANY TABLE               BY ACCESS  BY ACCESS
                      GRANT TABLE                  BY ACCESS  BY ACCESS
                      CREATE PUBLIC DATABASE LINK  BY ACCESS  BY ACCESS
                      GRANT ANY ROLE               BY ACCESS  BY ACCESS
                      SYSTEM GRANT                 BY ACCESS  BY ACCESS
                      ALTER DATABASE               BY ACCESS  BY ACCESS
                      CREATE ANY PROCEDURE         BY ACCESS  BY ACCESS
                      ALTER ANY PROCEDURE          BY ACCESS  BY ACCESS
                      DROP ANY PROCEDURE           BY ACCESS  BY ACCESS
                      ALTER PROFILE                BY ACCESS  BY ACCESS
                      DROP PROFILE                 BY ACCESS  BY ACCESS
                      GRANT ANY PRIVILEGE          BY ACCESS  BY ACCESS
                      CREATE ANY LIBRARY           BY ACCESS  BY ACCESS
                      EXEMPT ACCESS POLICY         BY ACCESS  BY ACCESS
                      GRANT ANY OBJECT PRIVILEGE   BY ACCESS  BY ACCESS
                      CREATE ANY JOB               BY ACCESS  BY ACCESS
                      CREATE EXTERNAL JOB          BY ACCESS  BY ACCESS

select * from DBA_PRIV_AUDIT_OPTS;

USER_NAME  PROXY_NAME PRIVILEGE                    SUCCESS    FAILURE
---------- ---------- ---------------------------- ---------- ----------
                      CREATE EXTERNAL JOB          BY ACCESS  BY ACCESS
                      CREATE ANY JOB               BY ACCESS  BY ACCESS
                      GRANT ANY OBJECT PRIVILEGE   BY ACCESS  BY ACCESS
                      EXEMPT ACCESS POLICY         BY ACCESS  BY ACCESS
                      CREATE ANY LIBRARY           BY ACCESS  BY ACCESS
                      GRANT ANY PRIVILEGE          BY ACCESS  BY ACCESS
                      DROP PROFILE                 BY ACCESS  BY ACCESS
                      ALTER PROFILE                BY ACCESS  BY ACCESS
                      DROP ANY PROCEDURE           BY ACCESS  BY ACCESS
                      ALTER ANY PROCEDURE          BY ACCESS  BY ACCESS
                      CREATE ANY PROCEDURE         BY ACCESS  BY ACCESS
                      ALTER DATABASE               BY ACCESS  BY ACCESS
                      GRANT ANY ROLE               BY ACCESS  BY ACCESS
                      CREATE PUBLIC DATABASE LINK  BY ACCESS  BY ACCESS
                      DROP ANY TABLE               BY ACCESS  BY ACCESS
                      ALTER ANY TABLE              BY ACCESS  BY ACCESS
                      CREATE ANY TABLE             BY ACCESS  BY ACCESS
                      DROP USER                    BY ACCESS  BY ACCESS
                      ALTER USER                   BY ACCESS  BY ACCESS
                      CREATE USER                  BY ACCESS  BY ACCESS
                      CREATE SESSION               BY ACCESS  BY ACCESS
                      AUDIT SYSTEM                 BY ACCESS  BY ACCESS
                      ALTER SYSTEM                 BY ACCESS  BY ACCESS

select * from DBA_OBJ_AUDIT_OPTS;

OWNER OBJECT_NAME          OBJECT_TYPE ALT AUD COM DEL GRA IND INS LOC REN SEL UPD REF EXE CRE REA WRI FBK
----- -------------------- ----------- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
SYS   AUD$                 TABLE       -/- -/- -/- S/S -/- -/- -/- -/- -/- -/- -/- -/- -/- -/- -/- -/- -/-
SYS   VERIFY_FUNCTION      PROCEDURE   -/- -/- -/- -/- S/S -/- -/- -/- -/- -/- -/- -/- -/- -/- -/- -/- -/-
SYS   VERIFY_FUNCTION_11G  PROCEDURE   -/- -/- -/- -/- S/S -/- -/- -/- -/- -/- -/- -/- -/- -/- -/- -/- -/-

select * from ALL_DEF_AUDIT_OPTS;

ALT AUD COM DEL GRA IND INS LOC REN SEL UPD REF EXE FBK REA
--- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
S/S -/- -/- -/- S/S -/- -/- -/- -/- -/- -/- -/- -/- -/- -/-

Audit trail housekeeping

So far we’ve spend quite some time on setting up the audit. Let’s come to the actual part of the post, the housekeeping. The plan is to have regular database job, which purge the audit data as required. For this I defined the following steps:

  • Create a report of your audit trail (optional)
  • Export your audit trail information for longterm archiving (optional)
  • Set the archive timestamp as soon as audit data has been archived
  • Purge archived audit data

I the current example I’ll skip the first to steps.

Create daily archive timestamp job. This job will be a regular dbms_scheduler job.


BEGIN
  DBMS_SCHEDULER.CREATE_JOB (
    job_name   => 'DAILY_AUDIT_ARCHIVE_TIMESTAMP',
    job_type   => 'PLSQL_BLOCK',
    job_action => 'BEGIN DBMS_AUDIT_MGMT.SET_LAST_ARCHIVE_TIMESTAMP(AUDIT_TRAIL_TYPE => 
                   DBMS_AUDIT_MGMT.AUDIT_TRAIL_AUD_STD,LAST_ARCHIVE_TIME => sysdate-10); END;', 
    start_date => sysdate, 
    repeat_interval => 'FREQ=HOURLY;INTERVAL=24', 
    enabled    =>  TRUE,
    comments   => 'Create an archive timestamp'
  );
END;
/

Create daily purge job

BEGIN
  DBMS_AUDIT_MGMT.CREATE_PURGE_JOB(
    AUDIT_TRAIL_TYPE           => DBMS_AUDIT_MGMT.AUDIT_TRAIL_AUD_STD,
    AUDIT_TRAIL_PURGE_INTERVAL => 24 /* hours */,
    AUDIT_TRAIL_PURGE_NAME     => 'Daily_Audit_Purge_Job',
    USE_LAST_ARCH_TIMESTAMP    => TRUE
  );
END;
/

commit;

The defined AUDIT JOB’s are then visible in DBA_AUDIT_MGMT_CLEANUP_JOBS.

col JOB_NAME for a30
col JOB_FREQUENCY for a40
select JOB_NAME,JOB_STATUS,AUDIT_TRAIL,JOB_FREQUENCY from DBA_AUDIT_MGMT_CLEANUP_JOBS;

JOB_NAME               JOB_STAT AUDIT_TRAIL          JOB_FREQUENCY
---------------------- -------- -------------------- ------------------------
DAILY_AUDIT_PURGE_JOB  ENABLED  STANDARD AUDIT TRAIL FREQ=HOURLY;INTERVAL=24

As we can see in dba_scheduler_jobs, DBMS_SCHEDULER.CREATE_JOB is just creating a other scheduler job.

col next_run_date for a50
select job_name, next_run_date, state, enabled from dba_scheduler_jobs where job_name like '%AUDIT%';

JOB_NAME                       NEXT_RUN_DATE                                      STATE           ENABL
------------------------------ -------------------------------------------------- --------------- -----
DAILY_AUDIT_ARCHIVE_TIMESTAMP  31-MAY-11 01.46.58.000000 PM +02:00                SCHEDULED       TRUE
DAILY_AUDIT_PURGE_JOB          31-MAY-11 01.49.34.900000 PM EUROPE/VIENNA         SCHEDULED       TRUE

Conclusion

For new Oracle 11g database auditing is enabled by default. Unfortunately Oracle does not setup a housekeeping. To make sure, that you do not end up with a full AUDIT_TRAIL you have to either switch off auditing or define some housekeeping jobs. With DBMS_AUDIT_MGMT this is a pretty easy job. It is that easy, that it is worth to think about having some kind of rolling audit window. Define a short retention time to save disk space, but long enough to have access to the audit information of the last hours or days. You may then be able to answer questions like “Did anybody change something?”, “I can not access XY but I could yesterday…”. When enabling audit for sys operation you will also be able to review what user SYS did all day long. Depending on the amount of audit data it will be quite a task to create nice audit reports.

7 thoughts on “Database Audit and Audit trail purging

  1. Pingback: Database Audit and Audit trail purging - Stefan Oehrli

  2. Murad

    What is the name of script for DBMS_AUDIT_MGMT package under $ORACLE_HOME/rdbms/admin

  3. Stefan Oehrli Post author

    Hi

    The package DBMS_AUDIT_MGMT is generated by the script dbmsamgt.sql. This script is executed by catpdbms.sql respectively catproc.sql.

    Cheers
    Stefan

  4. Jeremy

    I know this is an old post, but I have a question in regards to the exporting of the audit trail for retention. I know that you can’t use DATAPUMP to export this particular table because it’s owned by SYS (which is somewhat infuriating). Do you have any other ideas aside from CTAS or the legacy export tool to export the data in this table?

    Do you know if Oracle supports changing the owner of aud$? (I’ve looked but can’t find anything that would support this).

    Thanks in advance!

    Jeremy

  5. Stefan Oehrli Post author

    Hi Jeremy

    Good point, I’ve never thought about really data pump the table. I am not aware that Oracle officially allow to move the AUD$ table in a different schema. On the other hand oracle is moving the tables itself when installing label security (see MOS Note 278184.1. In one of the label security create script ( $ORACLE_HOME/rdbms/admin/catlbacs.sql ) can check what oracle is doing. I’m not sure why Oracle is doing this. In MOS Note 1073588.1 Oracle mention that for certain objects like AUD$ apply special rules for reorganizing. This would open the “possibility” that you do something like Oracle for label security. E.g create a SEC user move AUD$ to this user and create a synonym in sys. But make sure to first initialize the audit trail with dbms_audit_mgmt.

    If you want to stay Oracle compliant, you have to go for CATS described in MOS Note 73408.1

  6. Kevin Post author

    Hi, just a quick question about the default_cleanup_interval. I’m having trouble understanding the purpose of this setting. I wish to set up auditing and will create an auto purge job so is this setting related
    to when I can actually run the purge again?

    thanks for any help here,

    kev

  7. Stefan Oehrli Post author

    Hi Kevin

    The default clean up interval is currently not used. It is planned to be used in future versions of DBMS_AUDIT_MGMT. See MOS Note

    Oracle Support Document 1243324.1 Parameter DEFAULT_CLEANUP_INTERVAL of DBMS_AUDIT_MGMT.INIT_CLEANUP procedure

    To purge the audit trail you can run a manual purge job by executing DBMS_AUDIT_MGMT.CLEAN_AUDIT_TRAIL or by setting up a purge job with DBMS_AUDIT_MGMT.CREATE_PURGE_JOB. CREATE_PURGE_JOB is basically just creating a scheduler job executing CLEAN_AUDIT_TRAIL.

    For both procedures you can set USE_LAST_ARCH_TIMESTAMP. If set to true purge does only remove audit trails which have been marked with DBMS_AUDIT_MGMT.SET_LAST_ARCHIVE_TIMESTAMP Audit Vault will execute DBMS_AUDIT_MGMT.SET_LAST_ARCHIVE_TIMESTAMP when it load’s the audit data into the vault

    Manually purge all Audit Trails
    [cc lang=”sql”]
    BEGIN
    DBMS_AUDIT_MGMT.CLEAN_AUDIT_TRAIL(
    audit_trail_type => DBMS_AUDIT_MGMT.AUDIT_TRAIL_ALL,
    use_last_arch_timestamp => FALSE);
    END;
    /
    [/cc]
    Set up a regular job to purge all audit trail. USE_LAST_ARCH_TIMESTAMP is set to true => manually run DBMS_AUDIT_MGMT.SET_LAST_ARCHIVE_TIMESTAMP mark audit records.
    [cc lang=”sql”]
    BEGIN
    DBMS_AUDIT_MGMT.CREATE_PURGE_JOB(
    audit_trail_type => DBMS_AUDIT_MGMT.AUDIT_TRAIL_ALL,
    audit_trail_purge_interval => 100 /* hours */,
    audit_trail_purge_name => ‘CLEANUP’,
    use_last_arch_timestamp => TRUE);
    END;
    /
    [/cc]

    Cheers
    Stefan

Comments are closed.