Oracle FAQ Your Portal to the Oracle Knowledge Grid
HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US
 

Home -> Community -> Mailing Lists -> Oracle-L -> RE: Auditing

RE: Auditing

From: Brijesh Satdev <bsatdev_at_rolta.com>
Date: Fri, 22 Jun 2001 04:22:45 -0700
Message-ID: <F001.00333662.20010622042221@fatcity.com>

Hi
all,
<SPAN
class=651312311-22062001> 
In
what follows is the oracle documentation for auding by triggers:
<SPAN
class=651312311-22062001> 
<SPAN
class=651312311-22062001>Auditing Through Database Triggers
 

You
can use triggers to supplement the built-in auditing features of ORACLE. Although you can write triggers to record information similar to that recorded by the AUDIT command, do so only when you need more detailed audit information. For example, you can use triggers to provide value-based auditing on a per-row basis for tables.
 

Note:
In some fields, the ORACLE AUDIT command is considered a security audit facility, while triggers can provide a financial audit facility.
 

When
deciding whether to create a trigger to audit database activity, consider the advantages that the standard ORACLE database auditing features provide compared to auditing by triggers:
 

<SPAN
class=651312311-22062001>· Standard auditing options cover DML and DDL statements regarding all types of schema objects and structures. In contrast, triggers can audit only DML statements issued against tables.
 

<SPAN
class=651312311-22062001>· All database audit information is recorded centrally and automatically using the auditing features of ORACLE.
 

<SPAN
class=651312311-22062001>· Auditing features enabled using the standard ORACLE features are easier to declare and maintain and less prone to errors than are auditing functions defined through triggers.
 

<SPAN
class=651312311-22062001>· Any changes to existing auditing options can also be audited to guard against malicious database activity.
 

<SPAN
class=651312311-22062001>· Using the database auditing features, you can generate records once every time an audited statement is issued (BY ACCESS) or once for every session that issues an audited statement (BY SESSION). Triggers cannot audit by session; an audit record is generated each time a trigger-audited table is referenced.
 

<SPAN
class=651312311-22062001>· Database auditing can audit unsuccessful data access. In comparison, any audit information generated by a trigger is rolled back if the triggering statement is rolled back.
 

<SPAN
class=651312311-22062001>· Connections and disconnections, as well as session activity (such as physical I/Os, logical I/Os, and deadlocks), can be recorded by standard database auditing.
 

When
using triggers to provide sophisticated auditing, normally use AFTER triggers. By using AFTER triggers, you record auditing information after the triggering statement is subjected to any applicable integrity constraints, preventing cases where audit processing is carried out unnecessarily for statements that generate exceptions to integrity constraints.
 

When
you should use AFTER row vs. AFTER statement triggers depends on the information being audited. For example, row triggers provide value-based auditing on a per-row basis for tables. Triggers can also allow the user to supply a "reason code" for issuing the audited SQL statement, which can be useful in both row and statement-level auditing situations.
 

The
following trigger audits modifications to the EMP table on a per-row basis. It requires that a "reason code" be stored in a global package variable before the update. The trigger demonstrates:
 

<SPAN
class=651312311-22062001>· how triggers can provide value-based auditing
 

<SPAN
class=651312311-22062001>· how to use public package variables
 

<SPAN
class=651312311-22062001>Comments within the code explain the functionality of the trigger.
 

<SPAN
class=651312311-22062001> 
 

CREATE
TRIGGER audit_employee
 

<SPAN
class=651312311-22062001> 
 

AFTER
INSERT OR DELETE OR UPDATE ON emp
 

<SPAN
class=651312311-22062001> 
 

FOR
EACH ROW
 

<SPAN
class=651312311-22062001> 
 

<SPAN
class=651312311-22062001>BEGIN
 

<SPAN
class=651312311-22062001> 
 

/*
AUDITPACKAGE is a package with a public package
 

<SPAN
class=651312311-22062001> 
 

<SPAN
class=651312311-22062001>   variable REASON. REASON could be set by the
 

<SPAN
class=651312311-22062001> 
 

<SPAN
class=651312311-22062001>   application by a command such as EXECUTE
 

<SPAN
class=651312311-22062001> 
 

<SPAN
class=651312311-22062001>   AUDITPACKAGE.SET_REASON(reason_string). Note that a
 

<SPAN
class=651312311-22062001> 
 

<SPAN
class=651312311-22062001>   package variable has state for the duration of a
 

<SPAN
class=651312311-22062001> 
 

<SPAN
class=651312311-22062001>   session and that each session has a separate copy of
 

<SPAN
class=651312311-22062001> 
 

<SPAN
class=651312311-22062001>   all package variables. */
 

<SPAN
class=651312311-22062001> 
 

IF
auditpackage.reason IS NULL THEN
 

<SPAN
class=651312311-22062001> 
 

<SPAN
class=651312311-22062001>   raise_application_error(-20201,'Must specify reason with ',
 

<SPAN
class=651312311-22062001> 
 

<SPAN
class=651312311-22062001>  
'AUDITPACKAGE.SET_REASON(reason_string)');
 

<SPAN
class=651312311-22062001> 
 

END
IF;
 

<SPAN
class=651312311-22062001> 
 

<SPAN
class=651312311-22062001> 
 

/*
If the above conditional evaluates to TRUE, the
 

<SPAN
class=651312311-22062001> 
 

<SPAN
class=651312311-22062001>   user-specified error number and message is raised,
 

<SPAN
class=651312311-22062001> 
 

<SPAN
class=651312311-22062001>   the trigger stops execution, and the effects of the
 

<SPAN
class=651312311-22062001> 
 

<SPAN
class=651312311-22062001>   triggering statement are rolled back. Otherwise, a
 

<SPAN
class=651312311-22062001> 
 

<SPAN
class=651312311-22062001>   new row is inserted into the pre-defined auditing
 

<SPAN
class=651312311-22062001> 
 

<SPAN
class=651312311-22062001>   table named AUDIT_EMPLOYEE containing the existing
 

<SPAN
class=651312311-22062001> 
 

<SPAN
class=651312311-22062001>   and new values of the EMP table and the reason code
 

<SPAN
class=651312311-22062001> 
 

<SPAN
class=651312311-22062001>   defined by the REASON variable of AUDITPACKAGE. Note
 

<SPAN
class=651312311-22062001> 
 

<SPAN
class=651312311-22062001>   that the "old" values are NULL if triggering
 

<SPAN
class=651312311-22062001> 
 

<SPAN
class=651312311-22062001>   statement is an INSERT and the "new" values are NULL
 

<SPAN
class=651312311-22062001> 
 

<SPAN
class=651312311-22062001>   if the triggering statement is a DELETE. */
 

<SPAN
class=651312311-22062001> 
 

INSERT
INTO audit_employee VALUES
 

<SPAN
class=651312311-22062001> 
 

<SPAN
class=651312311-22062001>   (:old.ssn, :old.name, :old.job_classification, :old.sal,
 

<SPAN
class=651312311-22062001> 
 

<SPAN
class=651312311-22062001>   :new.ssn, :new.name, :new.job_classification, :new.sal,
 

<SPAN
class=651312311-22062001> 
 

<SPAN
class=651312311-22062001>   auditpackage.reason, user, sysdate );
 

<SPAN
class=651312311-22062001> 
 

<SPAN
class=651312311-22062001>END;
 

<SPAN
class=651312311-22062001>Optionally, you can also set the reason code back to NULL if you want to force the reason code to be set for every update. The following AFTER statement trigger sets the reason code back to NULL after the triggering statement is executed:
 

<SPAN
class=651312311-22062001> 
 

CREATE
TRIGGER audit_employee_reset
 

<SPAN
class=651312311-22062001> 
 

AFTER
INSERT OR DELETE OR UPDATE ON emp
 

<SPAN
class=651312311-22062001> 
 

<SPAN
class=651312311-22062001>BEGIN
 

<SPAN
class=651312311-22062001> 
 

<SPAN
class=651312311-22062001>  
auditpackage.set_reason(NULL);
 

<SPAN
class=651312311-22062001> 
 

<SPAN
class=651312311-22062001>END;
 

The
previous two triggers are both fired by the same type of SQL statement. However, the AFTER row trigger is fired once for each row of the table affected by the triggering statement, while the AFTER statement trigger is fired only once after the triggering statement execution is completed. <SPAN
class=651312311-22062001> 
<SPAN
class=651312311-22062001> 
<SPAN
class=651312311-22062001> 
<SPAN
class=651312311-22062001>Regards,
<SPAN
class=651312311-22062001>Brij.

  <FONT face=Tahoma
  size=2>-----Original Message-----From: root_at_fatcity.com   [mailto:root_at_fatcity.com]On Behalf Of Nirmal Kumar Muthu   KumaranSent: Friday, June 22, 2001 4:12 PMTo: Multiple   recipients of list ORACLE-LSubject: RE:   Auditing
  Hi Norrell,
  I just tested ur case.
  Can you tell me, how it's possible ,
  when doing auditing, oracle will refer to the sys.aud$ table itself, correct?.   

  If i droped it (even there is a
  synonym on that name),
  Oracle giving an error, it's not able   to find the sys.aud$ table.
  Nirmal,   

    -----Original Message----- <FONT

    face=Arial size=1>From:   <FONT face=Arial 
    size=1>Norrell, Brian [SMTP:BNorrell_at_QuadraMed.com] <FONT 
    face=Arial size=1>Sent:   <FONT face=Arial 
    size=1>Thursday, June 21, 2001 6:33 PM <FONT face=Arial 
    size=1>To:     <FONT face=Arial 
    size=1>Multiple recipients of list ORACLE-L <FONT face=Arial 
    size=1>Subject:        <FONT 
    face=Arial size=1>RE: Auditing 

    aud$ is one of the few system tables that can     have an owner other than sys. You can     create it under another schema (like system) and give sys a private     synonym pointing to system.aud$.  Then put     the trigger on the alternate aud$
    create table system.aud$ as select * from     sys.aud$; drop table sys.aud$;
    create synonym sys.aud$ for system.aud$;     create trigger x on system.aud$ as ...     

    Brian Norrell <FONT face=Arial
    size=2>Manager, MPI Development <FONT face=Arial     size=2>QuadraMed 511 E John Carpenter     Frwy, Su 500 Irving, TX 75062
    (972) 831-6600
    -----Original Message----- <FONT
    face=Arial size=2>Sent: Thursday, June 21, 2001 6:00 AM <FONT     face=Arial size=2>To: Multiple recipients of list ORACLE-L     This will not work as you can't create triggers     on sys objects. So tell me the way how i     should create triggers on aud$.
    -----Original Message----- <FONT
    face=Arial size=2>Sharma Sent: Thursday,     June 21, 2001 2:56 PM To: Multiple
    recipients of list ORACLE-L
    i think u can use triggers such kind of     auditing. create aud$ table with one more     column, and try updating the column as soon <FONT face=Arial     size=2>user fires some sql.
    this is just a thought. could find another     opinion.
    saurabh -----
    Original Message ----- To: Multiple     recipients of list ORACLE-L <ORACLE-L_at_fatcity.com> <FONT     face=Arial size=2>Sent: Thursday, June 21, 2001 11:15 AM     > Hi all there, <FONT face=Arial
    size=2>> I am auditing a database where 400 users are concurrently     accessing the > database.
    > Now in the table AUD$ we have all the     records of the user transactions.But >     is there any way to store what sort of query he is running so that i     can see <FONT face=Arial
    size=2>> the actual text of query which was fired 3 days before.     > Regards, <FONT face=Arial
    size=2>> Anand > <FONT
    face=Arial size=2>> -- > Please see     the official ORACLE-L FAQ: <A href="http://www.orafaq.com"     target=_blank>http://www.orafaq.com <FONT face=Arial     size=2>> -- > Author: Anand
    >   INET:
    karhadkar_at_rolta.com > <FONT
    face=Arial size=2>> Fat City Network Services    -- (858)     538-5051  FAX: (858) 538-5051 >
    San Diego, California        -- Public     Internet access / Mailing Lists >



    > To REMOVE yourself from this mailing list,     send an E-Mail message > to:
    ListGuru_at_fatcity.com (note EXACT spelling of 'ListGuru') and in     > the message BODY, include a line
    containing: UNSUB ORACLE-L > (or the     name of mailing list you want to be removed from).  You may     > also send the HELP command for other     information (like subscribing). Received on Fri Jun 22 2001 - 06:22:45 CDT

Original text of this message

HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US