Skip to Main Content

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Umesh.

Asked: March 24, 2001 - 1:17 am UTC

Last updated: November 01, 2012 - 10:20 pm UTC

Version: 8.1.5.0

Viewed 10K+ times! This question is

You Asked

Ho Tom

platform Windows NT

I set
audit_trial =DB in init.ora

startup the database

svrmgr >connect internal/<password>

svrmgr> audit user;

svrmgr > connect scott/tiger

svrmgr > create table emp123 ( n number);

svrmgr > connect sys/change_on_install

svrmgr > select * from aud$;

I see no rows selected

How do I proceed

Thanks in advance
Umesh

and Tom said...

Audit USER audits "CREATE USER", "ALTER USER", "DROP USER" commands. You are auditing the USER command.

You need to review the SQL Reference manual with a list of things in mind you want to audit and use the appropriate audit command to enable it.

For example:


sys@TKYTE816> select * from aud$;

no rows selected

sys@TKYTE816> audit table;

Audit succeeded.

sys@TKYTE816> connect scott/tiger
Connected.
scott@TKYTE816> create table abc ( x int );

Table created.

scott@TKYTE816> connect sys/manager
Connected.

sys@TKYTE816> select count(*) from aud$;

COUNT(*)
----------
1




Rating

  (81 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

audting

Umesh Kasturi, March 24, 2001 - 9:32 am UTC

It has helped greatly for my review

audit select

Charlie, July 24, 2002 - 12:23 am UTC

Hi Tom,

How can I audit specific user selecting on one of my tables?

I tried:

AUDIT SELECT ON T1 BY access by user1;

which doesn't work. And I don't want to use
"AUDIT SELECT TABLE BY user1 BY ACCESS WHENEVER SUCCESSFUL". Since it will audit every SINGLE table, which is too much.

Thanks,



Tom Kyte
July 24, 2002 - 10:21 pm UTC

that doesn't work cause it isn't valid sql.

you can audit select on T1 by SESSION or by ACCESS -- not at the user level. You either either selects on the table -- or not.

In 9i, there is Fine Grained Access Control that gives you this finer grained control

Turn off

Marcio, August 20, 2003 - 9:26 am UTC

Tom, I read this on manual:
</code> http://download-west.oracle.com/docs/cd/B10501_01/server.920/a96521/audit.htm#1633 <code>

Caution:
The NOAUDIT statement only specifies auditing options; it does not disable auditing as a whole. To turn auditing off and stop Oracle from generating audit records, set the initialization parameter AUDIT_TRAIL in the database's initialization parameter file as described in "Enabling and Disabling Auditing".

Well, if I issued NOAUDIT any... what was being audit -- What do I do? I mean, Oracle keeps generating records on database? I thought the audid was turned off.

thks, Marcio

Tom Kyte
August 21, 2003 - 8:12 am UTC

they are just saying "you want auditing totally off -- just set the init.ora parameter" noaudit can be used to reduce (to zero if you desire) what is audited but the audit code is still being executed (statements are looked at to see "hmm, do I need to audit this -- no -- ok, continue on).



third party tool generating sql -want to understand

A reader, August 23, 2003 - 1:25 pm UTC

Tom,

i wanted to post this query in a separate thread - but i am not geetting chance for the past 1 week.. here it goes.

06:22:31.734 SQL t@2200 select UPPER(value) from nls_database_parameters where parameter=UPPER('NLS_CHARACTERSET')
06:22:31.750 SQL t@2200 select * from mxSchema
06:22:31.750 SQL t@2200 -->select
06:22:31.750 SQL t@2200 -->select
06:22:31.750 SQL t@2200 -->select
06:22:31.750 SQL t@2200 select * from mxVer6 where mxOid = :va
06:22:31.765 SQL t@2200 :va=1
06:22:31.765 SQL t@2200 -->select
06:22:31.765 SQL t@2200 select * from mxAdmin where mxType = :va
06:22:31.765 SQL t@2200 :va=5
06:22:31.765 SQL t@2200 -->select
06:22:31.781 SQL t@2200 select * from mxVer6 where mxOid = :va
06:22:31.781 SQL t@2200 :va=1
06:22:58.984 SQL t@2200 -->select
06:22:58.984 SQL t@2200 select * from V_Prod_Code@TSTEENWL V_Prod_Code,V_Order_DocQuote4@TSTEENWL V_Order_DocQuote4 where V_Order_DocQuote4.order_row_id = :va and (V_Prod_Code.sub_requisition_num = V_Order_DocQuote4.sub_requisition_num)
06:22:58.984 SQL t@2200 :va15L-6DQ
06:23:02.953 SQL t@2200 --select
06:23:02.968 SQL t@2200 select * from lxRO_4de5d474 where lxToLat = :va and lxToId = :vb
06:23:02.968 SQL t@2200 :va=1306907764
06:23:02.968 SQL t@2200 :vb=117440512
06:23:02.984 SQL t@2200 -->select
06:23:02.984 SQL t@2200 select * from lxRO_4de5d474 where lxOid in (:va)
06:23:02.984 SQL t@2200 :va=201326592
06:23:02.984 SQL t@2200 -->select
06:23:03.078 SQL t@2200 select * from lxBO_4de5d474 where lxOid = :va
06:23:03.093 SQL t@2200 :va=33554432
06:23:03.093 SQL t@2200 -->select
06:23:03.093 SQL t@2200 select * from V_Order_DocQuote4@TSTEENWL where order_row_id = :va
06:23:03.093 SQL t@2200 :va15L-6DQ
06:23:04.140 SQL t@2200 --select
06:23:04.156 SQL t@2200 select * from lxBO_4de5d474 where lxOid = :va
06:23:04.156 SQL t@2200 :va=16777216
06:23:04.156 SQL t@2200 -->select
06:23:04.156 SQL t@2200 select * from V_Prod_Code@TSTEENWL where r1 = :va
06:23:04.156 SQL t@2200 :va20288-281-11407-T
06:23:06.937 SQL t@2200 --select
06:23:06.937 SQL t@2200 select mxOid,mxFlags,mxParent from mxBusType where mxName = :va
06:23:06.937 SQL t@2200 :va=LINKS Line Item
06:23:06.937 SQL t@2200 -->select
06:23:06.953 SQL t@2200 select * from mxPolicy where mxName = :va
06:23:06.953 SQL t@2200 :va=LINKS Line Item
06:23:06.953 SQL t@2200 -->select


the above lines are generated by one of the tool which we are using ...not sure how it does the search..I understand the select staements and bind variables (one of your favourite!!) but dont know how they are holding the resultset of each query and processing the whole process ...and getting the output.
this is just a search operation on an object.
Can you throw some light on this, so i can understand better


Thanks for your time and patience.




Tom Kyte
August 23, 2003 - 6:24 pm UTC

umm, not really. all we are seeing is the sql they are executing. their logic, that is well hidden away from you.

if you are using a tool, what you really need to know is:

a) how to use the tool
b) that the tool performs well for you
c) that the tool gets the right answers

stop auditing for all client

Linden, August 27, 2003 - 6:40 pm UTC

Tom,

Short of change the init parameter for audit and bounce the database, how can I stop auditing for any client? I can stop auditing on all other users except when the user_name is any client. I tried NOAUDIT delete table by any client, of  course it returned no such user.
 

SQL> select * from sys.dba_stmt_audit_opts;

USER_NAME                      PROXY_NAME                     AUDIT_OPTION                             SUCCESS    
------------------------------ ------------------------------ --------------------------------------
ANY CLIENT                                                    SELECT TABLE                             BY SESSION 
ANY CLIENT                                                    INSERT TABLE                             BY SESSION 
ANY CLIENT                                                    DELETE TABLE                             BY SESSION 
ANY CLIENT                                                    EXECUTE PROCEDURE                        BY SESSION 
ANY CLIENT                                                    UPDATE TABLE                             BY SESSION 


Thanks.
 

Tom Kyte
August 27, 2003 - 7:30 pm UTC

what version and how did you enable auditing for 'ANY CLIENT'

My follow up

Linden, August 28, 2003 - 1:27 pm UTC

The version is Oracle 8.1.7.4.1. To be honest, I don't remember how I enabled that. Since sys.dba_stmt_audit_opts is just a view, I found those records were actually in SYS.AUDIT$ table, so I went in to delete them. Now I kind of stopped all auditing actions except it still generating auditing records for SYSTEM, I guess that is built in.

My further question regarding AUDIT is that based on this audit trail if I can built a monitoring procedure that keeps track of all users of their actions (actually all select statements on one schema, since this is a warehouse, that's the only thing they can do), capture those statements, get timing statistics and get an EXPLAIN PLAN for those statements. The purpose of it would be 1) to track the usage; and 2) to monitor performance. Is this practical or doable, if not, what is the better approach?

I would appreciate greatly your thought on this.

Tom Kyte
August 29, 2003 - 8:04 am UTC

you deleted from sys.audit$???


everything you want to do is done automagically for you in 9i. In 8i, you will not be able to do this effectively.

AUDIT & FGAC

A reader, September 26, 2003 - 8:22 am UTC

HI, TOM!

We have a production application which uses more than 400 tables. We are willing to have a better access control and allow auditing at the user level in a near future. Tell me, taking into account this number of tables, should we use Fine Grained Access Control? Or would it be better to develop another application to control access to other applications (transformed into modules)?

Thanks again.
Best regards.


Tom Kyte
September 26, 2003 - 10:40 am UTC

FGAC is not about auditing...

FGAC is about access control and whether it is 1 table, 400 tables, 40,000 tables whatever -- it is an appropriate technology to consider in order to implement access control.


DBMS_FGA (fine grained auditing) might be useful to look at for auditing

A reader, September 30, 2003 - 3:38 pm UTC


audit_file_dest

jas, March 17, 2004 - 9:45 am UTC

hi tom

platform Windows NT

I set
audit_trial =DB in init.ora

and audit_file_dest=$oracle_home/rdbms/audit
which is also default
i have enabled auditing.
but nothing appears in audit directory.


Tom Kyte
March 17, 2004 - 11:02 am UTC

connect / as sysdba and see. the audit file dest is where "sysdba" connection auditing goes.

by setting audit-trail to db, you've said "put the other stuff into the db".

if you set to OS it'll use the OS audit trail facility (eg: the windows "event" viewer)

Ken, November 18, 2004 - 2:00 pm UTC

This is how you get that 'ANY CLIENT' turned on if you're still interested:

SQL> audit create session by sys;

SQL> select * from dba_stmt_audit_opts;

USER_NAME  PROXY_NAME AUDIT_OPTION         SUCCESS    FAILURE
---------- ---------- -------------------- ---------- ---------
ANY CLIENT            CREATE SESSION       BY ACCESS  BY ACCESS

It might get turned on by other auditing statements for sys; I didn't play with it.  It does audit logon/logoff for sys, it doesn't get conn internal or conn as sydba. 

Auditing Create Control File

Magesh, November 29, 2004 - 1:23 pm UTC

Tom,
Can you tell me how to enable auditing for Create Control File command? 

Version - 9.2.0.3

  1* select *from audit_actions where action=57
 
    ACTION NAME
---------- ---------------------------
        57 CREATE CONTROL FILE
 
SQL> audit create control file;
audit create control file
             *
ERROR at line 1:
ORA-00969: missing ON keyword
 
 

Tom Kyte
November 29, 2004 - 3:38 pm UTC

thing is -- if you are recreating controlfiles, you are SYSDBA - and the database isn't open.

So, audit_trail=db isn't a happening thing, it would be to the OS audit trail and sysdba logins are always audited.

Further, to audit more than just the fact that SYSDBA logged in, you would set audit_sys_operations.

And by setting that -- all SQL statements issued by SYS are audited.....


So, since create controlfile is a sysdba thing

And sysdba is not audited via the audit command

you were looking in the wrong place. see audit_sys_operations (new in 9i, before that -- no can do)

Auditing

A reader, November 30, 2004 - 9:47 am UTC

Ok, if that's the case, audit for sys operations is going to be written to the operating system file and not to the aud$ right? So what action=57 in aud$ represent or what is its significance? Also, I am able to audit create procedure but not create function or create package. Why is this so ?
What difference does it make between auditing procedure and other db objects like function/package?

SQL> audit create procedure;
 
Audit succeeded.
 
SQL> audit create function;
audit create function
             *
ERROR at line 1:
ORA-00969: missing ON keyword
 
 
SQL> audit create package;
audit create package
             *
ERROR at line 1:
ORA-00969: missing ON keyword
 

Tom Kyte
November 30, 2004 - 10:02 am UTC

where did "action=57" come from? and what does action=57 have to do with the above discussion?

create procedure covers both, just like there is no "grant create function", "grant create package"

</code> http://docs.oracle.com/docs/cd/B10501_01/server.920/a96540/statements_48a.htm#2059461 <code>

procedure covers more than just stored procedures.




Auditing

Magesh, November 30, 2004 - 9:55 am UTC

Let me rephrase my above question# 1, What does action=57 in Audit_actions represent or what is its significance? Sorry for the confusion!


Tom Kyte
November 30, 2004 - 10:08 am UTC

same signifcance as 27 and many others. that is just a mapping of the command column of v$session.

Auditing

Magesh, November 30, 2004 - 10:33 am UTC


Operating System auditing

N.Balasubramanian, December 06, 2004 - 12:11 am UTC

Hi Tom,
In your Second book (Effective Oracle by design) you have mentioned (page 28) that "if the DBA mucked with the audit trail (not possible if you use operating system auditing and don't give the DBA operating system privileges), you can detect that (and get rid of her)"

Please explain how to do this.

Tom Kyte
December 06, 2004 - 11:35 am UTC

how do what -- use the operating system audit trail? not giving them OS privs (which mandates you tell us the OS) or how to get rid of them :)


a) os audit trail = set the audit_trail parameter for os auditing instead of db auditing.

b) don't let them log in as the ORACLE software owner (they don't need to)

c) as the Donald would say "your fired"

OS Auditing

B Smith, September 17, 2005 - 10:16 am UTC

Hi,

I am very clear with audit_trail=db and associated views/tables.

As I understand, irrespective of setting of AUDIT_TRAIL, auditing of sysdba logons, database startup / shutdown etc. is always done in Windows Event manager. Now if I set audit_trail=os, and then restart my database then what exactly happens and where do I look for details. Now so far from forums I have understood that along with audit_trail=os, we have to set audit_file_dest to the folder where the OS file would get generated. Then if you want to audit each stmt given by sys then set audit_sys_operations=true (9i and above). Now when I set
audit_sys_operations=true OR/AND audit_file_dest, my database does not start and produces following error. My init.ora has

audit_trail=OS
audit_sys_operations=TRUE
audit_file_dest=C:\Temp

The error which comes is and database does not open -
LRM-00101: unknown parameter name 'audit_sys_operations'
LRM-00101: unknown parameter name 'audit_file_dest'
ORA-01078: failure in processing system parameters

My question is - What is the meaning and how do we use the following -
audit_trail=OS
audit_sys_operations=TRUE
audit_file_dest=C:\Temp

Regards,

B Smith.


Tom Kyte
September 17, 2005 - 11:32 am UTC

the event log is where the OS audit trail can go to as well.



On windows you only have:


ops$xp10gr1\tkyte@ORA10GR1> show parameter audit

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
audit_sys_operations                 boolean     FALSE
audit_trail                          string      NONE
ops$xp10gr1\tkyte@ORA10GR1>

and you only have audit_sys_operations if you are using current software. 

Auditing,

sns, September 27, 2005 - 10:40 am UTC

Is there a way to track what tables and indexes of a particular schema were accessed by different users while running their queries (SELECT statement)?

The users normally execute queries through a front end application.

We have lots and lots of indexes that are eating up huge amount of space. We need to figure the indexes that are not used and could be dropped.

Thanks,


Tom Kyte
September 27, 2005 - 12:10 pm UTC

alter index I monitoring usage;

and query v$object_usage later, much much later.

(read about this in the sql reference or the admin guide - or search for "monitoring usage" on this site)

good one,

sns, September 27, 2005 - 1:06 pm UTC

Yes I would do that by altering the index.
Does monitoring the usage of index impacts performance?

Also, is there a way to monitor which tables are scanned full I mean full table scan?

Thanks,

Tom Kyte
September 27, 2005 - 1:46 pm UTC

No, it just flags a YES or NO to indicate the index was or was not used as an ACCESS method.


I would never recommend looking for what tables are full scanned.

I would look for query that consumes lots of resources.


but in 9i and above, you can surely use v$sql_plan, but I'd rather focus on the high load sql, not sql that does a full scan.

Auditing records inserted by dbms_job

Mateen, December 08, 2005 - 6:38 pm UTC

Hi Tom,
I have enabled auditing on a table in 9i using
audit insert, update, delete on <table> by access;
When I insert data into this table through sql plus, dba_audit_trail is getting populated with appropriate audit information.

But if I submit a job using dbms_job and the job is inserting data into the same table using insert stmt, but dba_audit_trail is not recording any information.

Am I missing anything? Appreciate your help.
Thanks in advance.

Tracking password change

Yogesh, February 28, 2006 - 9:35 am UTC

How can we track change of attributes using Audit? (Oracle 8174)

what I have done is 

AUDIT_TRAIL = DB (init.ora) 

$ sqlplus system/********

SQL> audit alter user;
Audit succeeded.

SQL>alter user v1 identified by d234;

SELECT * FROM DBA_AUDIT_TRAIL;
SELECT * FROM AUD$;

works fine ... 

but when I use following sequence 

$ sqlplus v1/********

SQL>alter user v1 identified by d234;

SELECT * FROM DBA_AUDIT_TRAIL;
SELECT * FROM AUD$;

Nothing is logged in these views. Where I'm I going wrong? 

 

Tom Kyte
February 28, 2006 - 9:48 am UTC

you were auditing the use of the PRIVILEGE "alter user"

In order to alter another users password, you need to use the ALTER USER (which should likely really be named alter ANY user) privilege.

In order to alter YOUR OWN password, you need no privilege whatsoever.


You can read about system event triggers and code a BEFORE ALTER database trigger to capture information before any ALTER statement is executed.


Need your suggestion on auditing

A reader, April 25, 2006 - 3:10 am UTC

Tom,
we need to implement auditing on one of our tables and later we want to reuse the same logic to other tables if we need. We are working on Oracle 9i.

I think of two approaches.
can you suggest which one is better or any other better approach other than these two.

1) Have one common audit trail table which consists of few columns to identify a module/table and columns for auditing as follows:

Audit column 1 Name
Audit Column 1 Old Value
Audit Column 1 New Values
Audit column 2 Name
Audit Column 2 Old Value
Audit Column 2 New Values
.
.
.
we may have 5 to 6 such sets and this may increase depending on requirements.

In this case, for every record in a table we want to audit, we will have only 1 record in audit table.


2) Have a similar audit trail table. Instead of having such audit column 1,2 ,etc have only 3 columns.

Few Primary Key columns
.
.
.
Audit column Name
Audit column old value
Audit Column New value.

In this case, for every record in a table we want to audit, we will have more than 1 record in audit table.

As our requirement is to extend this auditing functionality for other tables in future, can you please advice which is better approach.

Thanks Tom.


Tom Kyte
April 25, 2006 - 5:39 am UTC

I'd rather write a piece of code that writes code here.

Write a code generator that audits entire row images, this storing of just the changes makes the audit information so hard to use - that is is useless.

A reader, April 27, 2006 - 5:18 am UTC

Tom,
Thanks for the reply.
Does it mean that i need to capture the entire row
instead of specific columns in another table?
If so, i may need to have an audit table for every table i want to audit.Please correct me if i am wrong.



Tom Kyte
April 27, 2006 - 3:02 pm UTC

that is what I'm saying - and you would write a procedure that you could pass a table name and have that procedure do the create of the table and whatever else you needed.

Alexander the ok, May 11, 2006 - 1:50 pm UTC

Hi Tom,

I have a question about how auditing works. Basically, I was looking how to audit everything by everyone. I thought it was as easy as setting audit_trail=DB. This apparently does nothing and you have to explicitly say what kind of thing it is you want to audit like "audit delete any table".

My question is, do we have to explicitly state for every possible action for every user "audit whatever..."? Is there any "audit all" type of thing?

Tom Kyte
May 11, 2006 - 8:05 pm UTC

Alexander the ok, May 11, 2006 - 4:46 pm UTC

Sorry Tom I retract my previous question. I thought about it more I don't want to track everything.

I am curious though why when I audit dml operations it shows up as a 103 action# (session rec) instead of action# 2,3,6 or 7 (audit_actions table).

Also, you tweaked a little above at the thought of deleting from aud$

</code> http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:404742183816#12661627954503

Thought you might like to know the documentation actually suggests it, and states further down it is the only sys object that show be modified.

http://download-west.oracle.com/docs/cd/B14117_01/network.101/b10773/cfgaudit.htm#1006479 <code>

Control-F for "DELETE FROM SYS.AUD$;"

Alexander the ok, May 14, 2006 - 12:29 pm UTC

Tom if we post two followups in a row because we made a mistake or whatever do you not see the second one? Is there any way to notify you that the most recent thing we posted is the question we want answered?

Tom Kyte
May 14, 2006 - 7:09 pm UTC

My user interface has me see them "purely linearly" - in a time based fashion. I see them in order by time and I see them "once" (big FIFO queue)...

Alexander the ok, May 14, 2006 - 7:52 pm UTC

Ok that's cool, I got that impression.

I was interested to hear your thoughts on the above about deleting from aud$. I already made a costing mistake by playing around in sys once before...But if it's ok, then it will be helpful for me in testing auditing.

How the audit commands work is not very clear to me an requires experimentation. For example, "audit procedure;" would lead you to believe that would audit anything to do with procedures but so far creating them is the only thing that is showing up in aud$ and thus I'm filling up the table it would be easier to start from a clean slate by being able to delete.

A reader, May 17, 2006 - 12:26 am UTC

Tom,

Lots of information/notes on metalink regarding how to move aud$ out of system tablespace, can i move it online as i am using 10.2.0.1.

Thanks.

Tom Kyte
May 17, 2006 - 6:48 am UTC

that is something to discuss with support, but I'd hazzard a guess of "no".

More likely would be

a) create a new one but named different
b) pause for a moment as you rename aud$ and this new table to swap names
c) archive the old aud$

A reader, July 12, 2006 - 2:17 pm UTC

Tom,

I was looking at this command "audit create procedure"
but my requirement needs auditing just one function ( if someone modifies or drops it). Is there any workaround
for DB Version 9.2.0.6 and up?

TIA.



Tom Kyte
July 12, 2006 - 4:01 pm UTC

use of a DDL trigger could be something to look at.

create a "after create" DDL trigger, it can look at the object names, object types - audit whatever you want (in your own audit trail)


</code> http://docs.oracle.com/docs/cd/B19306_01/appdev.102/b14251/adfns_triggers.htm#sthref1154 http://docs.oracle.com/docs/cd/B19306_01/appdev.102/b14251/adfns_triggers.htm#i1007895 <code>

A reader, July 14, 2006 - 2:02 pm UTC

Tom,

Maybe i wasn't clear enough the function i need audited belongs in the SYS schema please provide your valuable feedback.

TIA.

Tom Kyte
July 14, 2006 - 2:50 pm UTC

</code> http://www.google.com/musicl?lid=Xviz7FPbtVH&aid=7ZazE0blASJ&sa=X&oi=music&ct=result <code>

The same remains the same :)

Same answer. DDL trigger.


but why would you have something in SYS - you shouldn't have any of YOUR stuff in SYS - that would be a big big no-no.

So, you probably want to audit sysdba operations since that is the only POSSIBLE thing that could be going on here and since you hardly EVER use sysdba, the audit will be small.

A reader, July 14, 2006 - 4:37 pm UTC

Weird audit requirement by auditors "how do you track if someone changes verify_function" :-)

These folks are most non technical with certification credits like CISSP or CISAA or etc etc ...


Tom Kyte
July 14, 2006 - 4:53 pm UTC

why not just audit SYSDBA to the file system then.

That'll catch it, and catch all of the other (rare, rare, so rare) "as sysdba" operations.

Problem is - if one has the ability to munge the function in SYS, one has the ability to zap any audit trail you store in the database...

Can Oracle auditing do this?

Mathew Butler, September 27, 2006 - 4:54 am UTC

I'm looking for an minimum impact means of auditing update/insert/merge statements that DON'T come from a specific set of applications as a means to track unathorised data modifications.

I understand that this may not be foolproof, depending on how the application is identified. ie: If identified by V$session.program a smart "user" might think to change the name of the application executable to sidestep auditing.

Also helpful would be tracking user logons, to include time, application identifier and IP addresses.

We are in the process of reviewing our system security.

Regards,

Tom Kyte
September 27, 2006 - 5:08 am UTC

need more environmental details. would it be safe to say "we want to track all sql's performed against a set of objects UNLESS the parsing schema was 'X'"

eg: do the safe applications use a common database account and you want to audit for everything EXCEPT them?

Additional info.

Mathew Butler, September 27, 2006 - 5:46 am UTC

We are running 9.2.

Each user logs on with their own credentials, so user name is unique per session - we can't filter by parsing schema. I think we must pick up some attributes of the application client(s) for identification, else set something from the application ( in a global context maybe? ) that can be picked up and interpretted by audit.

This is a client/server system.

We do not expect to have many audit records ( except for upgrades, and maintenance work ). The requirement is to track unauthorised data changes.

Cheers,

Tom Kyte
September 27, 2006 - 7:17 am UTC

guess my first thought is:

logon trigger sets app context with "probable client program name"

you would then need a trigger "before insert or update or delete" on the tables of interest that would use ora_sql_txt builtin to save the sql in your own audit trail.

I'm in between flights right now and don't have time to test fine grained access control, but I'll book mark this one and if I get time this week (not 100% sure on that), I'll research that a bit.

Auditing

jas, November 08, 2006 - 3:21 pm UTC

Hi Tom,

One of DBA setup following. Can you please sugegst is it valid?

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
audit_file_dest string /data01/app/oracle/admin/KOUST
/adump
audit_sys_operations boolean FALSE
audit_syslog_level string
audit_trail string NONE

AUDIT DELETE TABLE, INSERT TABLE, UPDATE TABLE, SELECT TABLE BY JAS BY ACCESS;

Tom Kyte
November 08, 2006 - 8:11 pm UTC

if the database started, it is valid.

suppose a better question would be:

this is what we want to do, to accomplish, do these settings achieve that.

if your goal was to disable auditing - you have achieved that.
</code> http://docs.oracle.com/docs/cd/B19306_01/server.102/b14237/initparams016.htm#sthref91 <code>

check the audit configurations

Dawar, January 16, 2007 - 12:35 pm UTC

DB: 10g

I run the following sql to check the audit configurations.

DB: 10.1.0.5.0

SQL> select name, value from v$parameter
2 where name like 'audit%';

NAME VALUE
---------------------- ---------------------------------------------
audit_sys_operations FALSE
audit_file_dest /opt/db_1/rdbms/audit
audit_trail NONE


**********************************************
DB: 10.1.0.4.0

NAME VALUE
---------------------- ------------------------
audit_sys_operations FALSE
audit_file_dest /opt/db_2/rdbms/audit
audit_trail DB_EXTENDED


1) What are "audit_sys_operations " parameters?
Are they new to 10g?
If it is false, what is it mean?

2) In my DB #1 audit_trail is NONE and DB2 audit_trail equals to DB_EXTENDED.

what is the difference btw NONE & DB_EXTENDED values?

cheers,
Dawar

Errorcode

Marcel, February 07, 2007 - 8:57 am UTC

Hi Tom,

while I audit the database every entry has an errorcode ! What is the name of the table to resolve the code into an text ? Is there an table ?

Marcel
Tom Kyte
February 07, 2007 - 6:44 pm UTC

show me what error code you mean.

A reader, February 08, 2007 - 1:03 am UTC

select action_name, returncode
from dba_audit_session;

ACTION_NAME RETURNCODE
--------------- ----------
LOGON 1017
Tom Kyte
February 08, 2007 - 8:19 am UTC

$ oerr ora 1017

or

ops$tkyte%ORA10GR2> exec dbms_output.put_line( sqlerrm( -1017 ) );
ORA-01017: invalid username/password; logon denied

PL/SQL procedure successfully completed.


or

http://docs.oracle.com/docs/cd/B19306_01/server.102/b14219/toc.htm

Error message

Michel Cadot, February 08, 2007 - 1:56 am UTC

At Unix prompt:
> oerr ORA 1017
01017, 00000, "invalid username/password; logon denied"

At SQL prompt, use sqlerrm function, for instance:
SQL> exec dbms_output.put_line(sqlerrm(-1017));
ORA-01017: invalid username/password; logon denied

Regards
Michel

Auditing

Marcel, February 15, 2007 - 2:30 am UTC

Hi Tom,

when I try to use the audit options :

SQL> audit connect whenever not successful;
SQL> audit conext whenever successful;
SQL> audit session by <USER>;
SQL> audit all privileges by <user> whenever usccessful;

everything works until this point, but in the
DBA_AUDIT_OBJECT table aren't the entries generated by DROP, TRUNCATE and alter table move tablespace !

The views dba_priv_audit_opts and dba_stmt_audit_opts list
the audit command.

Thanks in advance
Marcel
Tom Kyte
February 15, 2007 - 11:52 am UTC

audit conext?

but - basically - you seem to not be auditing those things when successful?

full test case, cut and paste please.

Remark to the last question

A reader, February 15, 2007 - 4:14 am UTC

Is ist possible that some statements only logged with the statement ID ?

Marcel

Marcel, February 16, 2007 - 5:06 am UTC

Hi Tom,

thanks for you're review...

I think I found the problem...

Until now I am only auditing with the all privileges option
The all privileges option audits only the create for the table audit.

audit all privileges by <USER> whenever successful;

because I need the CREATE TABLE for creating a table;

When I want to audit the DDL issued against the DB I must
audit the according DDL statement.

audit table by <USER> whenever not successful;
audit table by <USER> whenever successful;
audit sequence by <USER> whenever successful;
audit sequence by <USER> whenever not successful;
audit alter system by <USER> whenever successful;
audit alter system by <USER> whenever not successful;
audit procedure by <USER> whenever not successful;
audit procedure by <USER> whenever successful;
audit trigger by <USER> whenever successful;
audit trigger by <USER> whenever not successful;
audit view by <USER> whenever successful;
audit view by <USER> whenever not successful;
audit system grant by <USER> whenever successful;
audit system grant by <USER> whenever not successful;
audit create synonym by <USER> whenever successful;
audit create synonym by <USER> whenever not successful;
audit create synonym by <USER> whenever not successful;
noaudit select any table by <USER>;


I am right so far ?

Thanks again and Kölle alaaf :-)

Marcel

Auditing

Sandeep, February 20, 2007 - 11:12 pm UTC

Hi Tom,

I am seeing the following and I'm trying to figure out if anyone besides sys is able to delete
"delete from sys.aud$" events from sys.aud$.

My setup is the following:

SQL> show parameter audit

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
audit_file_dest string /u01/app/oracle/admin/orcl/adu
mp
audit_sys_operations boolean FALSE
audit_syslog_level string
audit_trail string DB


I have the following auditing option turned on:

SQL> select * from dba_stmt_audit_opts;

USER_NAME PROXY_NAME
------------------------------ ------------------------------
AUDIT_OPTION SUCCESS FAILURE
---------------------------------------- ---------- ----------

CREATE SESSION BY ACCESS BY ACCESS


I am seeing the login/logout information as you would expect in sys.aud$. I am also seeing the
"delete from sys.aud$" records that I also expect. The problem I have is that "system" is able to
delete from sys.aud$ fine but it is unable to delete any of the "delete from sys.aud$" rows. Here
is an example:

devsol10: sqlplus system/******

SQL*Plus: Release 10.2.0.1.0 - Production on Tue Feb 20 17:05:36 2007

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


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bit Production
With the Partitioning, OLAP and Data Mining options

-- show that there are rows in sys.aud$
SQL> select count(*) from sys.aud$;

COUNT(*)
----------
2

-- show I can delete the 2 rows
SQL> delete from sys.aud$;

2 rows deleted.

-- delete again
SQL> delete from sys.aud$;

0 rows deleted.

-- show that 2 delete from sys.aud$ events are still there.
-- shouldn't there just be 1?
SQL> select t2.name, t1.obj$creator || '.' || t1.obj$name
2 from sys.aud$ t1, audit_actions t2
3 where t1.action# = t2.action;

NAME
----------------------------
T1.OBJ$CREATOR||'.'||T1.OBJ$NAME
--------------------------------------------------------------------------------
DELETE
SYS.AUD$

DELETE
SYS.AUD$


SQL> select count(*) from sys.aud$;

COUNT(*)
----------
2

-- connect as sys and show that it can delete the rows
SQL> connect sys/oracle as sysdba;
Connected.
SQL> delete from sys.aud$;

2 rows deleted.

SQL> select count(*) from sys.aud$;

COUNT(*)
----------
0


I have 2 questions:
- Is this intended behavior?
- Is there a permission I can give to someone that is non-sys to delete these records from sys.aud$?

Thanks,
Sandeep
Tom Kyte
February 21, 2007 - 10:50 am UTC

question for you - why would you want people to be able to remove records from the audit trail - including the records that show they did that????????

sort of "defeats" auditing does it not?

Audit The Auditor auditing

Robert, April 02, 2007 - 3:56 pm UTC


Tom,

I want to be able to capture any changes to the audit policies.
To "Audit The Auditor" if you will.
According to the documentation, the best you can do is set "audit_sys_operations=true".
But you can enable/disable auditing by users other than sys.

How can I audit the auditor to make sure all modifications, etc. to the audit policies are captured?

Thanks,

Robert.

Has anyone parsed the OS audit files?

Dave, August 28, 2007 - 4:52 pm UTC

Has anyone written something to parse the OS files created when you set audit_sys_operations=true (SQLLDR/Perl/shell/etc) ?

I want to move these files offsite and load them into another Oracle database.
Tom Kyte
September 04, 2007 - 3:32 pm UTC

in 10gr2 - they could be XML, tons of parsers for that - is that an option?

A reader, September 05, 2007 - 2:00 am UTC

To Dave from Des Moines,

Why not use dbms_lob to read the files?

Noaudit Statement

A reader, November 06, 2007 - 8:41 am UTC

Hi,

how can I disable these auditing options ? I am little bit confused !!!

It's Version 9.2.0.7.0

CREATE RULE
CREATE ANY RULE
ALTER ANY RULE
DROP ANY RULE
EXECUTE ANY RULE
MANAGE ANY QUEUE
ENQUEUE ANY QUEUE
DEQUEUE ANY QUEUE
ADMINISTER RESOURCE MANAGER
CREATE EVALUATION CONTEXT
CREATE ANY EVALUATION CONTEXT
ALTER ANY EVALUATION CONTEXT
DROP ANY EVALUATION CONTEXT
EXECUTE ANY EVALUATION CONTEXT
CREATE RULE SET
CREATE ANY RULE SET
ALTER ANY RULE SET
DROP ANY RULE SET
EXECUTE ANY RULE SET

Regrads
Marcel
Tom Kyte
November 06, 2007 - 9:37 am UTC

ops$tkyte%ORA10GR2> noaudit create rule;

Noaudit succeeded.

Madhu, November 22, 2007 - 11:46 pm UTC

Hey Tom,

Requirement: 
-------------------------
We want to audit all DML operations done on a table by the application users. There are several application users who do the DML and it is required to track which application user, did what DML operation. 

When connection is made to the database, the schema to which all the application users connect is the one and the same ¿ i.e. we use PUBLICUSER credentials for establishing DB connection for all different application users.

Therefore the detail of which application user is performing the DML is not available for oracle. It is available in the application code. Our primary requirement is that we need to have the detail of the application user doing the transaction to be passed into the database so that we can audit the DML operations done.

To take an example:

Let¿s say that the table to be audited is EMP which is in SCOTT schema:

SQL> desc EMP
 Name                                      Null?     Type
 -----------------------------------------   --------  ----------------------------
 EMPNO                              NOT NULL  NUMBER (4)
 ENAME                                               VARCHAR2 (10)
 JOB                                                 VARCHAR2 (9)
 MGR                                                 NUMBER (4)
 HIREDATE                                             DATE
 SAL                                                 NUMBER (7,2)
 COMM                                                NUMBER(7,2)
 DEPTNO                                              NUMBER(2)

Let¿s say that there are 4 application users; user1, user2, user3 & user4. Now when they connect to the database, the connection is to schema SCOTT. So all the 4 application users will connect to the same db schema `Scott¿.  The app users will do some transactions; they may roll it back etc. And we need to track that. ¿ The tricky part being that we need to track which application user has done the DML. 

We are planning to track the Edit Audits through Triggers. Before the actual Data record Insert into the EMP table the trigger should insert the Record into the Audit Table, along with the UserID.

Can you please let us know the alternative options?

We used the approach of using
SYS_CONTEXT 
Global Temporary Tables which are transaction specific.
to store the UserID.

But then, the approaches did not workout as we have distributed transactions (under the COM+ Environment).

Tom Kyte
November 26, 2007 - 11:18 am UTC

dbms_session.set_identifier


and let oracle do the auditing for you (fine grained auditing). It'll audit the identifier set.

Set Identifier

Madhu, November 27, 2007 - 11:37 pm UTC

Tom,

Thanks for your reply.

But then I had few questions on Set Identifier.

Let us say I have 3(insert) operations to be performed in a transaction.

Now, for every DML operation we explicitly get the Connection object, use it and release it. (Microsoft COM+ Distributed Environment).

Since we explicitly get a connection every time, and as we would have a different session every time do you think the set value will be retained across, since it is set in a session specific variable(CLIENT_IDENTIFIER).

Let me know at what level I have to set this identifier.

Please let me know your thoughts on using this in Microsoft OleDB ?


Tom Kyte
November 28, 2007 - 10:43 pm UTC

... Now, for every DML operation we explicitly get the Connection object, use it
and release it. (Microsoft COM+ Distributed Environment). ...

that would be classified as "not smart"

all of your transactions are single statements? that is the most trivial application on the planet if so.


this doesn't sound right to me.

Record level Audit Old\New value same Error

sasirekha, April 30, 2008 - 9:54 am UTC

I have some problem using Audit Record.



Generally if we map a record to the audit Record, it will track the details of the table insert, update, delete.



While I update the record, it will insert two different row in audit record like Audit Action K and N.



But both are contain the same values..



I need the old and new value.



Can any one please give me the solution with this !


Tom Kyte
April 30, 2008 - 11:02 am UTC

questions from me:

what is an "audit record", must be well defined - they are using it

"if we map a record to the audit record" - not really sure what that means

"like audit action K and N" - K and N?? huh?

"but both are contain the same values - I need the old and new value" - well, why didn't they access the old and new values?

where is the sample, the example, the thing that shows us what you are really doing....

export of audit table

Vinod, May 19, 2008 - 10:25 am UTC

Tom ,

I would like to export the past 120 days records from AUD$ table in 10g . Which column should i use as a baseline for export based on sysdate ?
(like query=sysdate - .....)

-Vinod



Tom Kyte
May 19, 2008 - 6:11 pm UTC

use a create table as select organization external and query the DBA information instead - you'll get much more useful stuff that you could query in another instance easily.

Erick Alejandro Lau, June 06, 2008 - 11:17 am UTC

Hello,

There are multiple Q/A appearing in a single entry when I search your site, so I am not able to write a review for the proper question.

In first follow up, you suggest Fine Grained Access Control for an auditing question. In other case, you correctly state that FGAC is not for auditing, but Fine Grained Auditing is.

Noaudit ?

Greg, July 02, 2008 - 3:06 pm UTC

I noticed you showed the noaudit command above with "noaudit create rule" ..

I'm curious, is there anything special needed for "ADMINISTER RESOURCE MANAGER" ?? or is it something I'm doing? or something else?

SQL > select * from DBA_PRIV_AUDIT_OPTS;

USER_NAME                      PROXY_NAME                     PRIVILEGE                                SUCCESS    FAILURE
------------------------------ ------------------------------ ---------------------------------------- ---------- ----------
JORACLE                                                       ADMINISTER RESOURCE MANAGER              BY ACCESS  BY ACCESS

1 row selected.

SQL > noaudit ADMINISTER RESOURCE MANAGER;
noaudit ADMINISTER RESOURCE MANAGER
        *
ERROR at line 1:
ORA-00956: missing or invalid auditing option


SQL > noaudit ADMINISTER RESOURCE MANAGER by joracle;
noaudit ADMINISTER RESOURCE MANAGER by joracle
        *
ERROR at line 1:
ORA-00956: missing or invalid auditing option

RN, July 16, 2008 - 12:36 pm UTC

Hi Tom,

When we use statement level auditing (sql_statement_clause from the doc http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/statements_4007.htm#g2274817 )
only the statements executed against the objects owned by the audited user are being logged in the audit trail. For example, when I say: "audit insert table, update table, delete table by SCOTT by access;" the audit trail records only inserts/updates/deletes done on tables owned by SCOTT. If scott inserts/updates/deletes on a table owned by another user, that does not get recorded in the audit trail. From the documentation, it appears that statement level auditing would be done on the particular statement issued by the audited user, without regard to the owner of the object, but that does not seem to be the case. Is it a misleading documentation or am I missing any syntax options here? If this is not possible by Oracle auditing, what is the other solution, triggers?

thanks,
RN
Tom Kyte
July 17, 2008 - 11:32 am UTC

are you sure

sys%ORA10GR2> connect /
Connected.
ops$tkyte%ORA10GR2> drop table t;

Table dropped.

ops$tkyte%ORA10GR2> create table t ( x int );

Table created.

ops$tkyte%ORA10GR2> insert into t values ( 1 );

1 row created.

ops$tkyte%ORA10GR2> commit;

Commit complete.

ops$tkyte%ORA10GR2> grant all on t to scott;

Grant succeeded.

ops$tkyte%ORA10GR2> connect / as sysdba
Connected.
sys%ORA10GR2> audit insert table,
  2  update table, delete table by SCOTT by access;

Audit succeeded.


sys%ORA10GR2> connect scott/tiger
Connected.
scott%ORA10GR2> delete from emp where 1=0;

0 rows deleted.

scott%ORA10GR2> delete from ops$tkyte.t;

1 row deleted.

scott%ORA10GR2> connect / as sysdba
Connected.
sys%ORA10GR2> column userid format a8
sys%ORA10GR2> column obj$creator format a10
sys%ORA10GR2> column obj$name format a15
sys%ORA10GR2> select statement, userid, obj$creator, obj$name from aud$;

 STATEMENT USERID   OBJ$CREATO OBJ$NAME
---------- -------- ---------- ---------------
        11 SCOTT    SCOTT      EMP
        16 SCOTT    OPS$TKYTE  T


RN, July 17, 2008 - 12:24 pm UTC

Thanks for the reply Tom. Below is my testcase, any idea why I am getting different results?


SQL> sho user
USER is "SYS"

SQL> create user test_audit identified by test_audit;

User created.

SQL> create user test_schema identified by test_schema;

User created.

SQL> grant connect, resource to test_audit, test_schema;

Grant succeeded.

SQL> create table test_schema.t1 (n number);

Table created.

SQL> grant all on test_schema.t1 to test_audit;

Grant succeeded.

SQL> audit insert table, update table, delete table by test_audit by access;

Audit succeeded.

SQL> conn test_audit/test_audit
Connected.
SQL> insert into test_schema.t1 values (100);

1 row created.

SQL> commit;

Commit complete.

SQL> conn / as sysdba
Connected.
SQL> SELECT username,
extended_timestamp,
owner,
obj_name,
action_name
FROM dba_audit_trail
WHERE owner = 'TEST_AUDIT'
ORDER BY timestamp
/

no rows selected

SQL> conn test_audit/test_audit
Connected.
SQL> create table t2 (n number);

Table created.

SQL> insert into t2 values (100);

1 row created.

SQL> commit;

Commit complete.

SQL> conn / as sysdba
Connected.
SQL> SELECT username,
extended_timestamp,
owner,
obj_name,
action_name
FROM dba_audit_trail
WHERE owner = 'TEST_AUDIT'
ORDER BY timestamp
/

USERNAME EXTENDED_TIMESTAMP OWNER
------------------------------ ---------------------------------------------------------------------------
------------------------------
OBJ_NAME
------------------------------------------------------------------------------------------------------------------------
--------
ACTION_NAME
----------------------------
TEST_AUDIT 17-JUL-08 03.28.47.952368 AM +00:00
TEST_AUDIT
T2
INSERT


1 row selected.

==> AS YOU CAN SEE, IT RECORDS ONLY THE INSERT ACTIVITY TO THE TABLE OWNED BY TEST_AUDIT USER, NOT OTHERS. IS THERE
ANYTHING WRONG IN WHAT I AM DOING?


SQL> select * from dba_stmt_audit_opts where user_name = 'TEST_AUDIT';

USER_NAME PROXY_NAME AUDIT_OPTION SUCCESS
FAILURE
------------------------------ ------------------------------ ---------------------------------------- ---------- ----------
TEST_AUDIT INSERT TABLE
BY ACCESS BY ACCESS
TEST_AUDIT UPDATE TABLE BY ACCESS BY
ACCESS
TEST_AUDIT DELETE TABLE BY ACCESS BY ACCESS

3 rows selected.

SQL> select * from dba_priv_audit_opts where user_name = 'TEST_AUDIT';

no rows selected

Thank you verymuch.
RN

Tom Kyte
July 17, 2008 - 12:33 pm UTC

where USERNAME = 'TEST_AUDIT'

change your query against dba_audit_trail, you want to see the records for TEST_AUDIT, you are querying the records against test audits objects, not the records recorded for the test_audit user

RN, July 17, 2008 - 12:39 pm UTC

Thanks Tom! You are a genius, how can you spot it at one look? I was struggling with this since yesterday! Thanks so much for helping out!

Have a nice day!
Tom Kyte
July 17, 2008 - 12:42 pm UTC

well, I was coming at it from the perspective of "it is audited, so it must be the thing that reports on what was in fact audited that is wrong - the record is there"

you were looking at the audit command...
I was looking at the report that showed what was audited....

auditing

A reader, August 28, 2008 - 8:53 am UTC

Tom:

Do you like table designs that store audit data in same production table meaning after a user saves a record it becomes read-only. Any updates are keyed in as new records?

You sort of blocking the user from doing any updates to old records. but "old" includes any record saved.
Tom Kyte
August 29, 2008 - 10:27 pm UTC

depends entirely on the application needs.

In 11g, I would give serious consideration to the flashback data archive.

Pre-11g, if I had the need to keep a history - then sure, that would be one approach. Another would be to save the old record into a history table, and then update

auditing

A reader, October 15, 2008 - 11:33 pm UTC

Tom:

I have a requirement to implement audit trails for db applications to include: who accessed the db, what db was accessed, which records were accessed, changed or deleted.

1. Is there a way to implement this in oracle. That sounds like every select, insert, update, delete on any table needs to be audited which is going to affect performance in a big way.

2. for 1 user --> 1 db account I assume we can let oracle do this or write application code or create customized triggers? correct. How would do this with application table accounts.


Tom Kyte
October 17, 2008 - 8:38 pm UTC

well, since databases do auditing, "what database was accessed" is "obvious", the one you are currently in.

1) read about fine grained auditing.

2) if the database doesn't know who the user is.... please think about this. How could the database audit the "real user". Read about dbms_session.set_identifier. Your applications will have to use that to tell the database WHO is doing stuff.

auditing

A reader, October 18, 2008 - 1:05 am UTC

Tom:

Can you summarize on when is it best to use oracle internal auditing versus creating custom tables/triggers. I am trying to decide which one to use for audit control.


It seems oracle dumps all audit info the admin defined in one big audit_trail table while custom editing requries table and a triger for each schema table that needs audit.
Tom Kyte
October 18, 2008 - 10:05 pm UTC

sure, I'll say what I've said so many times in the past:

do not write code unless and until you are forced to, if the builtin capabilities comes very close to meeting or meets or exceeds your needs - STOP - you are done, just use it.

So, now, YOU using your intimate knowledge of YOUR needs - you make the call. Me, I'm lazy, if the builtin stuff does it - by gosh, that's my approach every single time.

auditing

A reader, October 19, 2008 - 11:56 am UTC

Tom:

There are two argumes to what you say in the industry:
1. When you use built-in features you locked yourself to that database vendor. in this case if you write in pl/sql you are still locked with oracle.
2. when you use built-in features you lower your potential sales and revenue that can generated by writing and maintaining code.


Do you know of general high level auditing needs that are not supported by Oracle. it sounds to me you can do everything with built-in features.

also, one key point is that we do not have DBA control over DB. this is done by another organization. We do have an account with DBA role though. If we went with Database builtin features are we going to be dependent on that organization. that would be bad decision as there are a lot of politics invloved. i think all they have to do is turn auditing on to DB and we can run the audut commands as needed. is this correct?




Tom Kyte
October 21, 2008 - 11:38 am UTC

1) then why did you buy a product in the first place. When you start using the OS you are locked into the OS. When you started programming in language X, you locked yourself into X. People lock themselves into the language, the framework, the IDE (integrated development environment), the source code control, the application server, *everything* in short - and then say "but we want to be database independent". Never ceases to amaze.

Look - you pay a lot for the software you purchase. You can either

a) maximize that investment and develop your stuff faster and cheaper
b) minimize that investment, waste the money you've already paid, spend more on your own development costs, and lock yourself into yourself.


2) go away. Just go away. Come on, think about this. Really think. Your company would maximize profit by....

a) spending lots of money you YOUR development salary, while waiting for YOU to deliver something that YOU have to maintain, that is totally proprietary to YOU

b) delivering a product faster, with less overall cost, because they used what they bought.




... it sounds to me you can do everything with built-in features. ...

bingo...



Your organizational structure is pretty bad there. First, no way would anyone in development have DBA - that is way way too much power. Second, the development organization needs to have someone on it that actually knows the database (a DBA/developer or a developer/DBA - whichever)



SMK - as I've said ad-nauseum to you over and over in response to any question like this:

... i think all they have to do is turn auditing on to DB and we can run
the audut commands as needed. is this correct?....

"IT DEPENDS" - go and read the other responses to see why it "DEPENDS" if you don't remember (it'll be along the lines of, well, umm, only YOU know what your needs are - we document what we can do - if what we do comes close to meeting, meets or exceeds your needs - USE IT)

auditing

sam, October 22, 2008 - 12:15 am UTC

Tom:

I think the hickup that people have about locking themselves into he product are license costs. As you know Unix, Java, Language X are free of charge.

You know that Java has become the most popular language on planet because it is "portable" and "free". In theory it can run on any machine and any operating system, even though it is difficult to code in and pretty complex. so the industry did not pay attention to development and maintenance costs to Java thinking that my application can run with any database i can switch to.


For auditing, my needs are simple. I want to know when User A logged in to the database and what did he do. What data did he select, update or delete and when did he log out.

You can correct me if i am wrong. It seems I can simply set AUDIT_TRAIL=DB and audit all the tables in schema for all users (if i have one db account per user or set dbms_session.client_id if application user) and all the information is stored automatically for me in one audit trail table. All i have to do is query it.

The other alternative is to create one audit table and trigger for every stingle table which mean lots of tables and code for maintenance. This sounds a very poor and inefficient design that I can't ever imagine a need for.




Tom Kyte
October 22, 2008 - 8:46 am UTC

unix, java, language x are 'free' - hahahahahahahahahahahahaha - ouch, that hurt when I fell out of my chair.

None of those are "free".


... You know that Java has become the most popular language on planet because it is
"portable" and "free". ...

but wait, don't many/most java programs use SQL, so do VB, php, <you name it>. Perhaps, SQL is the language you meant.

but wait, I've read many articles that say 'javascript' - ugly warts and all - would be by far the most popular programming language (many java apps generate javascript - and sql, java is defeating itself!)

umm, no, I did not know that java is *the most popular*, please point the references. Did you know that C is portable and C is free? Why isn't C the most popular language on the planet? Oh, wait, that would be because actually - COBOL is the most widely used (would not most widely used be relevant here?) Portable and Free has never made anything "the most popular".

And Java isn't free - the decision to use java, and then the modeling tools, the IDE of choice the source code control system, the higher development costs - Java costs $$$$.

I see all languages - many people consider java "too hard, too big, not very portable". There are many php developers out there that are pretty sure php is the cat's meow. Then you talk to a python developer, or a ruby developer or a VB developer (oh, and they'll talk and talk about .net this that or the other - that's a pretty popular platform).

And the license costs? You've paid them, you will be paying them. If you are not going to make use of what you have bought why the heck did you buy it, what are you doing using it right here, right now, what are you thinking?

SMK - I've said this to you over and over - do what you will, you will do what you want. Please don't ask me to rubber stamp your idea - You asked me and I answered. And my answers are always consistent:

exploit the heck out of your platform. Period. Use what you have. Do not write code.



you can achieve your goal via standard auditing. No code needs to be written.

auditing

A reader, October 23, 2008 - 12:04 am UTC

Tom Kyte
October 23, 2008 - 9:23 am UTC

and would you like the 1,000 other equally non-scientific ones that say "x is the most popular"

I mean a real reference, done by someone impartial... You did see that maybe it is by and far C# as well right?


... Tiobe uses Google, MSN and Yahoo! search engines to measure the Web ¿chatter¿ and hence the popularity of each programming language. ...

maybe that means it really finds the most confusing language, the hardest language, the language people most like to gripe about.

Point is - so what if Java is the most popular (I don't think it is, it is certainly in vogue, much like Cobol, Ada, C and C++ have been in the last 20 years)?

auditing

sam, November 06, 2008 - 10:56 am UTC

Tom:

I want to explore the builtin auditing features of oracle.
so i assume the first thing you do is set AUDIT_TRAIL=DB and then I can run the AUDIT command on users/tables etc to see how it works and check the different views oracle has. Is this correct?

2. I asked DBA to set the parameter up and he says they only do FULL auditing. Is there something called "FULL". never heard of this one.

3. if i set AUDIT_TRAIL=DB is it really usnig a lot of resourses or you use resourse when you actually run the AUDIT command and select what you want to audit.
Tom Kyte
November 11, 2008 - 2:19 pm UTC

no, the first thing you do of course is read the documentation.


so, start there, and after you confirm you have read it (which means most of your questions will fall by the wayside)......

Alexander, February 03, 2009 - 3:59 pm UTC

Tom,

What would be the proper way to age out auditing records from aud$ if for argument's sake after awhile it starting using significant space?

Thanks.

audit_trail='db,extended'

A reader, March 18, 2009 - 12:21 pm UTC

Tom,
As I understand from the documentation, audit_trail='db,extended' will capture the SQL statement and bind information in addition to the standard audit information. We audit only failed attempts. Sometimes there is a need to audit statements. My thought was that changing audit_trail requires a database restart. If I can set audit_trail to db,extended, we will capture more information which might help in finding out what exactly was being done. We can always turn off writing to audit trail by noaudit command. Would setting audit_trail to db,extended be a good idea? Oracle 10gr2.

Thanks...
Tom Kyte
March 19, 2009 - 10:12 am UTC

if you want the ability to capture the extended information at some point without having to restart - then that would be the way to do it.

Not entirely sure how to address "would it be a good idea", it is a decision - either

a) have it on so we can use it if and when we want without a restart
b) have it off, and know that if we want it on, we need to restart

Need your suggestion

Anamika, September 14, 2009 - 7:50 am UTC

Hi Tom,

First of all, thanks a lot for sharing your wonderful ideas & solutions....!

I need your suggestion to finalize the approach for creating audit entries from PL/SQL procedures.

For auditing, our application stores entire row images (pipe delimited string) as pre-image & post-image in application audit tables. These audit tables have been created at module level, so one audit table has audit entries for multiple business tables (from same functional module). These audit tables have PREIMAGE, POSTIMAGE columns with VARCHAR2 (4000) limit.

Example can be: if for the employee table, job column is updated from 'Developer' to 'Manager',following entry will be created in application audit table(image in ordered sequence):
TABLENAME PREIMAGE POSTIMAGE
-----------------------------------------------------------
Employee 1|Clark|Developer 1|Clark|Manager


We may use Oracle audit vault in near future, but right now, this is the approach that has been implemented. And, we also do not want to use triggers as the main functionality i.e. UI application is already working fine. We need to implement this new approach only for business data updates from Procedures/Pro*C batches. For UI, we are using tool generated code, so whenever a new table is modelled, code is automatically generated to select entire row image as PREIMAGE/POSTIMAGE.
i.e. getimage function with following type of SQL is automatically generated:
<< EXEC SQL SELECT EMPLOYEE_ID ||'|'|| EMPLOYEE_NAME ||'|'||JOB INTO :h_Image FROM EMPLOYEE WHERE EMPLOYEE_ID = :h_EMPLOYEE_ID >>

Now, for our current requirement, I can think of following options(after reading your asktom links):
(a) `user-defined aggregate function (using the ODCIAggregate interface) with Analytic function¿ to return the pipe delimited list of column names. This can be used to create dynamic SQL to fetch entire row image.
(b) sys_connect_by_path
(c) Collect Function introduced in Oracle 10g
(d) write a procedure similar to your print_table procedure, which can return pipe delimited string for entire row image of a business table
(e) Create a new reference table. This new table can store TABLE NAME, pipe separated Column string (e.g. EMPLOYEE_ID||'|'|| EMPLOYEE_NAME ||'|'||JOB ) for all the application tables. So, we will be able to create a dynamic SQL by using this ref table.
(f) write separate functions(static SQLs to return row image) for each table..!! this seems a bit difficult ..i.e. to introduce so much of code in our application as we have 300-400 business tables.
(g) Hard-code the column names in procedures/batches. This may result in best performance, but it will not be recommended approach as we get a lot of change requests for our application and tables may be altered as per future requirements.

Which option do you suggest?? Also, are we taking the right approach..???

Some of the stats are:
(in development envt, stats did not differ much)
Option (a): takes 19 msec in Production like envt(less time because of parallel processing??)
SELECT
collist
FROM (
SELECT case when row_number() over (order by COLUMN_ID)=1
then agg_strcat_delim(concat_expr(COLUMN_NAME,'||''|''||'))
over (order by COLUMN_ID
rows between unbounded preceding
and unbounded following)
end collist
FROM user_tab_cols
WHERE table_name='EMPLOYEE'
and data_type NOT IN ('BLOB', 'CLOB','RAW')
and hidden_column<>'YES'
)
where collist is not null


Option (b): takes 94 msec in Production like envt.
WITH
col_data AS
(SELECT column_name, column_id, count(*) over() cnt
FROM user_tab_cols
where table_name = ('EMPLOYEE')
and data_type NOT IN ('BLOB', 'CLOB','RAW')
and hidden_column<>'YES'
)
SELECT ltrim(sys_connect_by_path(column_name, '||''|''||'), '||''|''||') collist
FROM col_data
WHERE column_id = cnt
START WITH column_id = 1
CONNECT BY PRIOR column_id = column_id-1

Tom Kyte
September 14, 2009 - 1:53 pm UTC

... entire row images (pipe delimited string) ...

ugh, why would you do that - just to make it really slow and near impossible to use - not to mention the probable loss of data fidelity (you have to convert everything SAFELY to a string)


... so one audit table has audit entries for multiple business tables (from same functional module). ...

to me that is not a feature, but a serious design flaw and drawback.


.. << EXEC SQL SELECT EMPLOYEE_ID ||'|'|| EMPLOYEE_NAME ||'|'||JOB INTO :h_Image FROM EMPLOYEE WHERE EMPLOYEE_ID = :h_EMPLOYEE_ID >> ...

hah, I bet there are errors rampant in your audit trail - preimages that do not in any way represent the actual preimage - due to a missing "for update", you'd need to definitely lock the row here - if you do not, you are doing it wrong.



Now, for our current requirement, I can think of following options(after reading your asktom links):

ummm, you sort of forgot something vitally important.

"your current requirement" is missing, I don't know what you are trying to do or why - so I cannot comment on your approaches.


Which option do you suggest?? Also, are we taking the right approach..???

that I can answer - no, this is not the right approach to auditing, you are relying on applications to audit. You should have encapsulated the update logic in stored procedures, in a single centralized place and this UI code (which really should just be UI code) would call the procedures.

Need your suggestion .....

Anamika, September 15, 2009 - 2:06 am UTC

Hi Tom,

Thanks for your feedback and suggestions...

Ours is an old application.. and changing the auditing approach completely is in pipeline but it may take 1-2 years..!!

Missing "for update" should not be a concern for UI. I forgot to include the version column in my employee table example. We have implemented optimistic locking and all the business tables have a version column(i think, this method is also mentioned in your book). So, whenever business data is updated, this version check is used. If zero rows are updated, then transaction is rolled back. Also, all this code(version check, getpreimage etc.) is tool generated..so I think, right now, we do not have any major issues from UI..

Now, ok.. I think my actual requirement was lost in my long story..!!
Current requirement is to finalize the Audit approach for stored procedures.
Initially we did not have stored procedures in our application(only a few). But now,for the new funtionality being added to our application, we have also used stored procedures Right now, these procedures do not use standard auditing approach. Whenever audit entries need to be created(e.g. insert into HR_AUD where HR is module name), pipe delimited string is created by concatenating all the column values of a business table(for single row on basis of primary key). So, the column names are hard-coded in all the procedures.
e.g. if one business table is updated from 10 procedures, these 10 procedures will have the code to create preimage or postimage(something like EMPLOYEE_ID ||'|'|| EMPLOYEE_NAME ||'|'||JOB <<<column names hardcoded).
Now, if the table is altered because of some business change request, its difficult to change the code in all the procedures(nobody does actually). So, preimage & postimage in these cases will not be correct as the values for new columns will be missing. Also, if the column position changes, then also the row images will not be correct.
So, we want to use some standard approach to create this preimage/postimage (e.g. whenever we update a business table from stored procedure, we can call something like getpreimage/getpostimage on the basis of Primary key).
Also, we do not want to use triggers..
Options I have mentioned above(options from a to g mentioned above- in my last post) are different options (which I could think of) to meet this requirement and to select pipe delimited pre/post image from business table. Can you please refer to these options and recommend the best approach. Also, is there any better/easy way to meet this requirement??

Thanks again,
Anamika
Tom Kyte
September 15, 2009 - 10:04 am UTC

... Missing "for update" should not be a concern for UI. ...

yes, it is a problem - it is a concern.

if you audit
then you get the version number
then you work on the data
then you update it

you are auditing garbage - so we don't know yet (maybe you do, but I don't) that your approach is sound - I don't know what this "UI" generated code is. And let's not call it "UI code" anymore, this is just "code", if it were UI code, it would be UI code. Right now, it is everything.


... Also, we do not want to use triggers.. ...

why not? Have a flag that the trigger uses:

if ( my_globals_pkg.I_am_a_procedure )
then
do the audit
end if;

and have my_globals_pkg.i_am_a_procedure default to FALSE, the stored procedures would set this value to TRUE. Or the trigger could even look at the call stack (dbms_utility.format_call_stack) to determine if it was being fired by a procedure and do the audit.

This is one valid use of triggers - to perform auditing.


or why not just generate a procedure that "audits" table T. You write a bit of plsql code that generates a "create or replace procedure audit_T" statement - it would read the dictionary to determine the primary key (that would be the inputs to the procedure) and the columns in the table. It would use that information to then generate the body of the procedure (the insert as select statement). Your other stored procedures would simply call the audit routine - if the table changes, you re-generate the code (just like you re-generation your "UI" right now)


Thanks...!!!

Anamika, September 17, 2009 - 1:01 am UTC

Thank You so much.!!
I'll plan to implement "generate a procedure that "audits" table T". Thanks again.

Anamika

Faizan, September 17, 2009 - 11:47 pm UTC

Hi Tom,
I am using bellow code to audit a table.
DBMS_FGA.ADD_POLICY (
OBJECT_SCHEMA => 'TEST',
OBJECT_NAME => 'MY_TABLE',
POLICY_NAME => 'FGA_AUDIT_TEST',
AUDIT_CONDITION => 'PROGRAM NOT LIKE ''PROGRAM1%''
audit_column_opts => DBMS_FGA.ALL_COLUMNS,
statement_types => 'SELECT,INSERT,UPDATE,DELETE');

The procedures completes successfully but when i run a query on audited table it returns error:
ORA-28112: failed to execute policy function

Can u please suggest what is wrong in this ??
Thanks in Advance
Faizan
Tom Kyte
September 18, 2009 - 10:28 am UTC

U isn't available.

now, if YOU provide a COMPLETE test case with create table, insert into, a dbms_fga.add_policy that *could actually execute* (you have at least one missing quote, this is not your code), etc - something to reproduce with

we'd be able to tell you what error you have caused...


Logon trigger stop unauthorized connections -- set a flag in client_identifier --

Bala, October 21, 2010 - 12:00 pm UTC

We have a requirement where we want to boot the connections out if they are not coming from a specific server/IP. We also want to set a flag that will get saved in the audit trail (create session is audited)
We tried to use the DBMS_SESSION.SET_IDENTIFIER to set a flag, but this is not getting set since the session is stoped before even created "RAISE_APPLICATION_ERROR".

Is there any other way to achieve this with out having a custom audit trail table?

Here are the steps we followed (version 11.1.0.7 )

$: sqlplus /

SQL> create user user1 identified by user1;

User created.

SQL> grant create session to user1;

Grant succeeded.


SQL> CREATE OR REPLACE TRIGGER Verify_user_Source AFTER LOGON ON DATABASE
2 DECLARE
3 vMachine VARCHAR2(64);
4 vOSuser VARCHAR2(30);
5
6 BEGIN
7
8
9 IF UPPER(Ora_Login_User) = 'USER1' THEN
10 /* Get the machine name. Only connections coming from specified machines can get in. */
11 SELECT Machine,osuser
12 INTO vMachine,vOSuser
13 FROM V$Session
14 WHERE AudSID = USERENV('SESSIONID');
15 /* If they're not coming from an authorized host, then boot them out! */
16 IF LOWER(vMachine) not in ('server1') THEN
17 /* set the flag in the client_identifier field. */
18 DBMS_SESSION.SET_IDENTIFIER('Policy Violation');
19 RAISE_APPLICATION_ERROR(-20001, 'You are attempting to access a restricted account from a non-authorized host.
20 This action has been logged and notification sent to the DBA Group.');
21 END IF;
22 END IF;
23 END;
24 /

Trigger created.

SQL> exit

-- connect as user1
remote_serer:SQL> sqlplus user1/user1@RL1DB1

ORA-0064: error occurred at recursive SQL level 1

--connect back as dba and check the dba_audit_trail
$: sqlplus /
SQL>

select os_username, username, userhost, action_name, client_id from dba_audit_trail where username='USER1'

kml021 USER1 5N2VPD1 LOGON <null> --> ***the client_id is not set

--Modify the trigger and comment out the RAISE_APPLICATION_ERROR part to let the user connect

SQL> CREATE OR REPLACE TRIGGER Verify_user_Source AFTER LOGON ON DATABASE
2 DECLARE
3 vMachine VARCHAR2(64);
4 vOSuser VARCHAR2(30);
5
6 BEGIN
7
8
9 IF UPPER(Ora_Login_User) = 'USER1' THEN
10 /* Get the machine name. Only connections coming from specified machines can get in. */
11 SELECT Machine,osuser
12 INTO vMachine,vOSuser
13 FROM V$Session
14 WHERE AudSID = USERENV('SESSIONID');
15 /* If they're not coming from an authorized host, then boot them out! */
16 IF LOWER(vMachine) not in ('server1') THEN
17 /* set the flag in the client_identifier field. */
18 DBMS_SESSION.SET_IDENTIFIER('Policy Violation');
19
20 /*RAISE_APPLICATION_ERROR(-20001, 'You are attempting to access a restricted account from a non-authorized host.
21 This action has been logged and notification sent to the DBA Group.');*/
22
23 END IF;
24 END IF;
25 END;
26 /

Trigger created.



SQL> exit

--Now try to connect as user1

remote_server:SQL>sqlplus user1/user1
Connected to:

SQL> exit


--Check the audit trail now
$: sqlplus /
SQL> select os_username, username, userhost, action_name, client_id from dba_audit_trail where username='USER1'

kml021 USER1 5N2VPD1 LOGON <null>
<null> USER1 5N2VPD1 LOGOFF Policy Violation --> the client_id is populated (on the logoff event)





Tom Kyte
October 25, 2010 - 3:27 pm UTC

We have a requirement where we want to boot the connections out if they are not coming from a specific server/IP

configure valid node checking:

http://docs.oracle.com/docs/cd/B19306_01/network.102/b14266/policies.htm#sthref1125

no code necessary.

logon triggers will *never* fail for DBA's - you cannot do it that way.

A reader, January 17, 2011 - 8:37 pm UTC


Auditing all SQL/PL-SQL in a session

Nikhilesh, May 31, 2011 - 5:01 am UTC

Dear Tom,
We have a JAVA application which is totally dependent on a Oracle 9i database. We don't have source code for that application. In fact we are finding descripancies in our data but don't know whats happening inside. Is it possible to track all the database operations being done by that JAVA application. Is using SQL_TRACE the correct solution or Oracle provided any other utility also.

Thanks in advance.

Tom Kyte
May 31, 2011 - 12:53 pm UTC

sql_trace will get everything it does, yes. In 9i, that would be the correct tool to look at.

audit_sys_operations

A reader, March 06, 2012 - 9:26 am UTC

If you set audit_sys_operations to TRUE, how do you protect OS audit files stored in AUDIT_FILE_DEST being tampered with by Oracle admin users?

We're using Oracle 11g R2 and notice that there's even a DBMS_AUDIT_MGMT package which allows you to purge aud$ and OS audit files!
Tom Kyte
March 06, 2012 - 1:54 pm UTC

you have them written to the OS audit trail - which they should not have access to. These will be syslog or the windows event log.

Also, you should typically lock down access to the Oracle software account entirely - your DBA's do not need it day to day and in a truly secure environment, they would have to work with the system administrator to get temporary access to it for upgrades and the like.

In fact, most DBAs do not need access to the machine the database runs on from day to day either.

Actually - hardly any DBA's should have sysdba (you only need sysoper for most of them - to start and stop the database)...

audit_sys_operations

A reader, March 08, 2012 - 2:15 am UTC

We're currently just using the directory pointed to by AUDIT_FILE_DEST, not writing to SYSLOG

Even if DBA or SYS don't have logon to the server where the directory resides, does DBMS_AUDIT_MGMT or indeed something like UTL_FILE can bypass the need for this as they can manipulate the files from the database? Can we prevent this?

If not, is writing to SYSLOG what you recommend?
Tom Kyte
March 08, 2012 - 5:46 am UTC

We're currently just using the directory pointed to by AUDIT_FILE_DEST, not
writing to SYSLOG


therein lies your problem then.

you would want to audit to a location that cannot be manipulated by the person being audited, that would be syslog.

Users audited

A reader, April 27, 2012 - 2:29 pm UTC

Hi Tom,
What is needed to do to know the audited users from the database ?

I checked that this sql should do the answer:
SELECT distinct (USER_NAME) FROM DBA_STMT_AUDIT_OPTS;

But, when i check the dba_audit_trail we have more users than the query above returns.

Using Oracle 10.2.0.5

Thanks
Tom Kyte
April 28, 2012 - 8:16 am UTC

audit connect;

would audit everyone - you'd have one row in dba_stmt_audit_opts - but you'd have audit trail entries for everyone.

Auditing Commit and Rollback

Johann, September 30, 2012 - 11:35 am UTC

Hi Tom;

Thanks for sharing your knowledge.

I have a question concerning COMMIT and ROLLBACK in audit trails.
The problem is, that any transaction issued and than rolled back, appears in the audit trails, however they have physically never been applied. On the other side, the ROLLBACK statement is not visible in the audit trails. So I can't say afterwards, whether the transaction has been commited or rolled back. I tried to check via transaction ID (XID column) however I didn't get it.
Is there any possibility to tell transactions, that have been commited, appart from rolled back transactions?

thanks,
Johann
Tom Kyte
October 08, 2012 - 3:10 pm UTC

you could theoretically in log miner tell - but it would not be practical.

I would say the audit for a rollback and commit is the same though - you are auditing the use of a privilege, they used a privilege regardless of a rollback event. The privilege was used, that fact needs to be recorded and noted. That they rolled back isn't really relevant.

AUDIT FILE MAX SIZE

A reader, October 23, 2012 - 10:37 am UTC

Hello,

At the database level, the audit file max size is set to 100MB.  However, I see very small xml files generated on my audit file destination (size around 2KB).  Why is is this so? Our database is 11.2

select * from dba_audit_mgmt_config_paramsSQL> SQL> SQL> SQL>
  2  ;

PARAMETER_NAME                 PARAMETER_VALUE                AUDIT_TRAIL
------------------------------ ------------------------------ --------------------
DB AUDIT TABLESPACE            SYSAUX                         STANDARD AUDIT TRAIL
DB AUDIT TABLESPACE            SYSAUX                         FGA AUDIT TRAIL
AUDIT FILE MAX SIZE            102400                         OS AUDIT TRAIL
AUDIT FILE MAX SIZE            102400                         XML AUDIT TRAIL

Some of the files in our folder:

-rw-r--r--   1 oracle     dba           2470 Oct 20 23:55 mdcp9p4_ora_991_3.xml
-rw-r--r--   1 oracle     dba           3472 Oct 20 08:12 mdcp9p4_ora_9920_1.xml
-rw-r--r--   1 oracle     dba           2405 Oct 21 08:10 mdcp9p4_ora_9920_2.xml
-rw-r--r--   1 oracle     dba           3472 Oct 21 15:04 mdcp9p4_ora_9920_3.xml
-rw-r-----   1 oracle     dba            734 Oct 22 17:09 mdcp9p4_ora_9921_1.aud
-rw-r--r--   1 oracle     dba           2504 Oct 20 08:12 mdcp9p4_ora_9921_1.xml
-rw-r-----   1 oracle     dba            734 Oct 22 18:18 mdcp9p4_ora_9921_2.aud
-rw-r--r--   1 oracle     dba           2504 Oct 21 02:56 mdcp9p4_ora_9921_2.xml

Thanks,

Tom Kyte
October 23, 2012 - 12:27 pm UTC

those are sysdba logins probably. have you looked at them? what is in them

follow up,

A reader, October 23, 2012 - 2:48 pm UTC

Yes they are from sysdba logins. In those file names, does the number 9921 stands for process ID?

Would the setting of xml file size to 100MB doesn't make sense? Can an XML file wait until it reaches 100MB (for example) and then spawn a new file? We are seeing 10's and 1000's of files generating each day and most of them are under 3KB.

Thanks,


Tom Kyte
October 25, 2012 - 8:41 am UTC

these files are always generated, you cannot stop them.

one would wonder why you have thousands of them being generated - it should be RARE for someone to use sysdba to login - that should be very much protected, it shouldn't happen many times in a day let alone thousands. that would indicate a serious problem security wise in your deployment. sysdba should *hardly* ever be used.


what you need to do is start revoking sysdba from everyone - have they use their OWN accounts to log in, not sysdba. sysdba is so rarely needed.

follow up,

A reader, October 25, 2012 - 1:54 pm UTC

Thanks. Over here, we all login as ourselves on UNIX box and then switch user to oracle. To get into the database, most likely we all do "sqlplus / as sysdba". There shouldn't be thousands of manual access but I wonder why thousands.


About the audit files - if we try the procedure below, I think it still doesn't make sense in terms of the size of the XML file. Right?

BEGIN
DBMS_AUDIT_MGMT.set_audit_trail_property(
audit_trail_type => DBMS_AUDIT_MGMT.AUDIT_TRAIL_XML,
audit_trail_property => DBMS_AUDIT_MGMT.OS_FILE_MAX_SIZE,
audit_trail_property_value => 15000);
END;

Thanks,

Tom Kyte
October 28, 2012 - 10:28 pm UTC

you need to stop doing that - now, right away. seriously.

do your sysadms log in as root to read emails and work?

do not use sysdba like this, sysdba should HARDLY ever be used.

you should not be logging into the Oracle account.

you almost certainly shouldn't even be logging into the unix machine with the server so often.

this is really bad security - I would be revoking sysdba left and right here.



the sysdba audit is going to happen - always.

You probably have a background cron job that wakes up every N seconds and connects as sysdba too - that would account for thousands of tiny files.


stop using sysdba - seriously - it is a really bad idea, a horrible practice.

sysdba

sysdba, October 29, 2012 - 12:25 pm UTC

Tom:

<<stop using sysdba - seriously - it is a really bad idea, a horrible practice. >>

Do you normaly set individual user accounts with DBA ROLE instead for DBAs? There are some features that are not even supported by DBA role and you must use log in as sysdba.

Also, I recall from one of the oracle classes that even though a system admin should not have access to oracle database he can log in as root and maniuplate files. He also has total control over the oracle account or can create other unix accounts. Can you really control that other than auditing O/S actitivites and writing logs to another machine that sysadm does not have control over.
Tom Kyte
October 29, 2012 - 9:03 pm UTC

many of your DBA's don't even need the DBA role, but that would be a first start - yes.

there are very FEW things that need sysdba, please tell me what ones you need to use thousands of times per day.

there are very very FEW things that need sysdba.


root can be limited in power on todays operating systems - it might require an add on, but they can be limited as well. You can easily make it such that it takes two root users to do something and when you make people collude with each other in order to get high privileges, the ability to abuse that privilege goes way way down.

Alexander, October 30, 2012 - 8:40 am UTC

Tom,

You have written many times about "things people think they need SYSDBA for but do not" etc. I would be very interested to read about your thoughts on "things people think they need to log onto a database server for but do not".
Tom Kyte
October 31, 2012 - 3:53 pm UTC

let me turn it around, what do you think you need to log onto the database server for?

people think they need to be "on the server" to tune, to monitor, to change things. they don't.

Alexander, October 31, 2012 - 4:02 pm UTC

How about starting/stopping a listener? Adding instances to the server's tnsnames for database links or what have you.
Tom Kyte
October 31, 2012 - 5:52 pm UTC

stopping can be done remotely, all administration except starting can be done remotely. and starting should be a thing that happens at boot time. once started, it never needs to stop.


ldap, centralized name servers should/could be used instead of the old fashioned tnsnames.ora approach. additionally, you do not need a tnsnames entry for a dblink - create database link .... using '(description=(......)' works and removes any ambiguity as to what the dblink points to.


and tell me this -

how many times per day do you add an instance to the tnsnames.ora? (likely something like 0.01, remember this is a production environment)

how many times per day do you start or stop a listener? (should be zero)


Alexander, November 01, 2012 - 9:06 am UTC

This is kind of the point to my original question, many people may not realize these things.

However, continuing to play Devil's advocate, you're right I might only need to do these things 0.01% of the time. But guess what happens that time the listener stops running (it happens, seen it a handful of times in the last couple of years) and no one can log on to the box to fix it. The downtime then becomes infinity worse, and problem management is going to come looking for me as to why this happened and how to prevent it in the future.
Tom Kyte
November 01, 2012 - 10:20 pm UTC

do you value security? if you do, you won't be letting people log into the server willy nilly. You'll make it so that two people have to work together to get onto the server.


do you know you can run more than one listener? That the listener people connect to doesn't even have to be on the machine where the database is?

and a real fact is that once the application servers are up, you shouldn't be needing the listener anymore, the connection pools will have connected (and you should never let your connection pools "grow" and "shrink", use a fixed size).