1] Users connexions
1.1 Log users connexions
For User
management purpose, I need to record information from the the last connexion to
the Oracle instance for every users. The information are gathered locally in a
table, in a real simple manner with the SYS_CONTEXT function ( formerly 9i
USERENV ) :
INSTANCE ;
USERNAME ; LAST_LOGin time ; MODULE ; SERVICE_NAME ;
Machine ; OS_USER
INSTANCE_NAME
The name of the instance.MODULE
The application name (module) set through the DBMS_APPLICATION_INFO
package or OCI.SERVICE_NAME
The name of the service to which a given session is connected.HOST
Name of the host machine from which the client has connected.OS_USER
Operating system user name of the client process that initiated
the database session.
Since we
store only the last connexion data, no partitionned table needed.
Goal
|
Log DDLs actions
|
Version
|
10gR2
|
Trigger
|
AFTER LOGON ON DATABASE
BEFORE LOGOFF ON DATABASE
|
Function
|
SYS_CONTEXT to extract session
infomation
|
Log as
|
SYSTEM
|
1.1.1 LOGON
TRIGGER
-- 1/ create monitoring
table
CREATE TABLE USERS_MON
(
INSTANCE VARCHAR2(16 BYTE) NOT NULL,
USERNAME VARCHAR2(30 BYTE) NOT NULL,
LAST_LOG DATE NOT NULL,
MODULE VARCHAR2(64 BYTE),
SERVICE_NAME VARCHAR2(64 BYTE),
machine VARCHAR2 (64 byte),
OSUSER VARCHAR2 (30 byte)
)
TABLESPACE SYSAUX ;
create unique index USERS_MON_PK on USERS_MON (INSTANCE, USERNAME) tablespace SYSAUX ;
ALTER TABLE USERS_MON ADD CONSTRAINT USERS_MON_PK PRIMARY KEY (INSTANCE, USERNAME) using index ;
-- 2/ create on logon
trigger
CREATE OR REPLACE TRIGGER DB_LOGON
after logon on database
DECLARE
session_id number;
instanc VARCHAR2 (16) := sys_context('USERENV', 'INSTANCE_NAME');
service VARCHAR2 (64) := sys_context('USERENV', 'SERVICE_NAME');
moduleU VARCHAR2 (48) := sys_context('USERENV', 'MODULE');
HOST VARCHAR2 (64) := sys_context('USERENV', 'HOST');
OSUS VARCHAR2 (30) := sys_context('USERENV', 'OS_USER');
begin
select sys_context('USERENV','SESSIONID') into session_id from dual;
IF session_id != 0 --ignore
internal connections
then
-- insert logging info,
merge
merge into users_mon using ( SELECT 1 FROM dual ) on (username = user)
WHEN MATCHED THEN
UPDATE SET instance = instanc , last_log = sysdate , service_name = service , module = moduleU , machine = host , osuser =
osus
WHEN NOT MATCHED THEN
INSERT (instance,username,last_log,service_name,module,machine,osuser)
VALUES (instanc,user,sysdate,service,moduleU,host,osus) ;
end if;
end;
/
Query login
table :
select * from users_mon order by 3 desc ;
USERNAME
|
LAST_LOG
|
MODULE
|
SERVICE_NAME
|
MACHINE
|
OSUSER
|
SCOTT
|
28/04/2011 16:42
|
oracle@srv-5 (TNS V1-V3)
|
SYS$USERS
|
srv-5
|
oracle
|
APP1
|
28/04/2011 16:41
|
JDBC Thin Client
|
SCH01.corp.fr
|
srv-prod-11.corp.fr
|
tomcat
|
APP2
|
28/04/2011 16:41
|
frmweb@srv.corp.fr
|
SAP.corp.fr
|
srv.corp.fr
|
oracle
|
USR0
|
28/04/2011 16:41
|
frmweb@srv-as-4.corp.fr
|
SYS$USERS
|
srv-as-4.corp.fr
|
oracle
|
APP3
|
28/04/2011 16:41
|
calcul@srv-6 (TNS V1-V3)
|
SYS$USERS
|
srv-6
|
hrt
|
APP4
|
28/04/2011 16:41
|
httpd@srv-web-4.corp.fr
|
SYS$USERS
|
srv-web-4.corp.fr
|
nobody
|
USR1
|
28/04/2011 16:41
|
java@srv.corp.fr
|
SAP.corp.fr
|
srv.corp.fr
|
oracle
|
APP5
|
28/04/2011 16:40
|
RTSDGN@srv-9 (TNS V1-V3)
|
HHR.corp.fr
|
srv-9
|
hhrv7
|
USR2
|
28/04/2011 16:40
|
frmweb@srv-as-2.corp.fr
|
database.corp.fr
|
srv-as-2.corp.fr
|
oracle
|
APP6
|
28/04/2011 16:40
|
MSACCESS.EXE
|
SYS$USERS
|
ADCORP\PC-07002501-ID
|
kraviola
|
DB_LOGON may
be enhanced to include ‘alter session’ statements for specific needs.
Implied
« grant alter
session to system ; ».
- Get Number of Connections Per Month :
select username
, osuser , LDM , ceil(count(LDM)) CON_PER_MONTH from (
select username
, upper(osuser) osuser , trunc(login_date,'MONTH') LDM
-- , case WHEN UNDO_KB > 100 THEN 'RW' ELSE 'R' END TYPE
from adb.users_mon where lower(module) like '%access%'
and
login_date > sysdate-365/2 -- 6 months
and username
in ('APPNAME_INT','MTB_2_INT')
order by 1,2,3
)
group by username , osuser , LDM order by 1,2,3
USERNAME OSUSER LDM CON_PER_MONTH
APPNAME_INT UTIL1 01/04/2018 4
APPNAME_INT UTIL1 01/05/2018 8
SELECT TRUNC(sysdate, 'YEAR') "New
Year" FROM DUAL -- 01/01/2014
SELECT TRUNC(sysdate, 'MONTH') FROM DUAL -- 01/09/2014
SELECT TRUNC(sysdate) FROM DUAL -- 15/09/2014
- keep only the last_log of users
( several rows, keep the last based on LOGIN_DATE column )
create view SYSTEM.USERS_MON as
select instance,username,login_date
last_log,module,service_name,machine,osuser from ( select instance,username,login_date,module,service_name,machine,osuser,
ROW_NUMBER() OVER(PARTITION BY instance,username order by login_date
desc ) rn
from ADB.USERS_MON order by 3 desc ) where rn=1 ;
1.1.2 LOGOFF
TRIGGER
<UPDATE>
Add a few
columns to the USERS_MON table and get more information like if the Session
used UNDO segments and therefore did Modification in Database :
CREATE TABLE
USERS_MON
(
INSTANCE VARCHAR2(16 BYTE) NOT NULL,
USERNAME
VARCHAR2(30 BYTE) NOT NULL,
LOGIN_DATE
DATE NOT NULL,
MODULE
VARCHAR2(48 BYTE),
SERVICE_NAME
VARCHAR2(64 BYTE),
MACHINE
VARCHAR2(64 BYTE),
OSUSER
VARCHAR2(30 BYTE),
SESS_AUD
NUMBER,
UNDO_KB
INTEGER,
LOGOFF_DATE
DATE,
CLIENT_I
VARCHAR2(64 BYTE)
)
CREATE INDEX
USERS_MON_I01 ON
USERS_MON (SESS_AUD)
CREATE OR REPLACE TRIGGER DB_LOGON
after logon on database
DECLARE
session_id
number;
status_database
VARCHAR2 (32);
instanc VARCHAR2 (16) := sys_context('USERENV', 'INSTANCE_NAME');
service VARCHAR2 (64) := sys_context('USERENV', 'SERVICE_NAME');
moduleU VARCHAR2 (48) := sys_context('USERENV', 'MODULE');
HOST VARCHAR2 (64) := sys_context('USERENV', 'HOST');
OSUS VARCHAR2 (30) := sys_context('USERENV', 'OS_USER');
CLTI VARCHAR2 (64) := sys_context('USERENV', 'CLIENT_INFO');
begin
-- Cas Base avec Standby
select
database_role into
status_database from
v$database;
if
status_database = 'PRIMARY' then
select
sys_context('USERENV','SESSIONID') into session_id from dual;
IF session_id != 0 and ( user not in ('DBSNMP') ) -- ignore internal connections and DBSNMP
then
--
A/ insert logging info
INSERT into ADB.USERS_MON
(instance,username,login_date,service_name,module,machine,osuser,sess_aud,undo_kb,client_i)
VALUES (instanc,user,sysdate,service,moduleU,host,osus,session_id,0,clti) ;
end if;
end;
/
CREATE OR REPLACE TRIGGER
DB_LOGOFF
before logoff on database
DECLARE
session_id
number;
undo_used_kb
integer ;
begin
select sys_context('USERENV','SESSIONID') into session_id from dual;
IF session_id != 0 and ( user not in ('DBSNMP') ) -- ignore internal connections and DBSNMP
then
--
insert loggoff info
select round(to_number(b.value)/1024,1) "KB_Undo" into undo_used_kb
from v$statname a inner join v$sesstat b on a.statistic# = b.statistic#
inner join v$mystat
c on b.sid = c.sid
where a.name = 'undo change
vector size' and c.statistic# = 0 ;
UPDATE APP.USERS_MON set UNDO_KB = undo_used_kb ,
logoff_date = sysdate where sess_aud =
session_id ;
end if;
end;
/
INSTANCE
|
USERNAME
|
LOGIN_DATE
|
MODULE
|
SERVICE_NAME
|
DB
|
USER
|
15/12/2015 11:45
|
kslstart.exe
|
APP
|
DB
|
USER
|
15/12/2015 11:44
|
java@srv.corp (TNS V1-V3)
|
APP
|
DB
|
USER
|
15/12/2015 11:43
|
httpd@srv.corp (TNS V1-V3)
|
APP
|
DB
|
USER
|
15/12/2015 11:43
|
java@srv.corp (TNS V1-V3)
|
APP
|
DB
|
USER
|
15/12/2015 11:43
|
kslstart.exe
|
APP
|
DB
|
USER
|
15/12/2015 11:43
|
frmweb@srv.corp (TNS V1-V3)
|
APP
|
DB
|
USER
|
15/12/2015 11:43
|
w3wp.exe
|
APP
|
MACHINE
|
OSUSER
|
SESS_AUD
|
UNDO_KB
|
LOGOFF_DATE
|
CLIENT_I
|
PC
|
user
|
542132333
|
0
|
15/12/2015 11:45
|
|
srv.corp
|
oracle
|
542132299
|
5
|
15/12/2015 11:44
|
|
srv.corp
|
oracle
|
542132277
|
18
|
15/12/2015 11:43
|
|
srv.corp
|
oracle
|
542132275
|
14
|
15/12/2015 11:43
|
|
PC2
|
user2
|
542132276
|
0
|
15/12/2015 11:43
|
|
srv.corp
|
Oracle
|
542132274
|
0
|
|
|
IIS APPPOOL
|
user3
|
542132270
|
0
|
|
|
1.1.3 Every
2 Hours, update the Consumed UNDO Per Session column
- When a
session is using a graphical tool, such as « TOAD » or « SQL
Developper » and may modify Data outside of the scope of an
« official » application.
- To store
the data, even if the session stops abruptely and doesn’t trigger the LOGOFF code
above.
Create a
procedure
CREATE OR REPLACE procedure ADB.CD13_ORA_CHK_UNDO_SESS AUTHID CURRENT_USER AS
-- select to_char(trunc(sysdate,'HH24'), 'HH24:MI') into
cur_hour from dual ;
-- job every hours, check undo_kb from
« out-of-applications » sessions
-- context : session_id == v$session : audsid
CURSOR c1 is
WITH SSIIDD AS
( select sid , audsid , username from
v$session where audsid in ( select sess_aud from adb.users_mon where -- username = 'SYSTEM' and (
( lower(MODULE) like '%sqlplus%' and lower(machine) like '%novea%' ) OR lower(MODULE) like '%toad%' OR lower(MODULE) like '%developer%' OR lower(MODULE) like '%excel%' OR lower(MODULE) like '%access%' )
-- )
)
select round(to_number(s.value)/1024,1) KB_UNDO , i.AUDSID
from v$sesstat s,
v$statname n , SSIIDD i
where name = 'undo change
vector size' and s.statistic#=n.statistic# and s.sid = i.sid
order by 2 ;
BEGIN
-- avoid update on old rows ( > SYSDATE-1 )
For Cur IN C1 Loop
UPDATE ADB.USERS_MON set UNDO_KB = Cur.KB_UNDO , UNDO_I = SYSDATE where sess_aud = Cur.AUDSID and
LOGIN_DATE > SYSDATE-1 ;
commit ;
END LOOP;
END ;
/
Use
Scheduler
BEGIN
SYS.DBMS_SCHEDULER.CREATE_JOB
(
job_name => 'CD13_ORA_CHK_UNDO_SESS'
,start_date =>
TO_TIMESTAMP_TZ('2015/12/15
05:00:00.000000 +01:00','yyyy/mm/dd
hh24:mi:ss.ff tzh:tzm')
,repeat_interval
=> 'FREQ=DAILY;BYHOUR=00,02,04,06,08,10,12,14,16,18,20,22;BYMINUTE=0;'
,end_date => NULL
,job_class => 'DEFAULT_JOB_CLASS'
,job_type => 'PLSQL_BLOCK'
,job_action => 'DECLARE
BEGIN ADB.CD13_ORA_CHK_UNDO_SESS; END;'
,comments => 'AUC
15/12/2015: Calcul UNDO Sess'
);
Get results
1.2 Log failed user connection
Goal
|
Log Failed connections
|
Version
|
10gR2
|
Audit
|
create session [ Default ]
|
Log as
|
SYSTEM
|
SQL> alter
system set audit_trail=DB scope=spfile ;
SQL> audit create session whenever not
successful;
Audit succeeded.
Check ,
return codes are
0 : OK
1017 : invalid
username/password
28000 : the account is locked
select
os_username , terminal , username , userhost
, timestamp , action_name ,
returncode from
dba_audit_trail where
action_name = 'LOGON' and username = '<SCHEMA_USER>' order by timestamp desc
OS_USERNAME
|
TERMINAL
|
USERNAME
|
USERHOST
|
TIMESTAMP
|
ACTION_NAME
|
RETURNCODE
|
09/04/2013
|
|
|
|
|
|
|
oracle
|
unknown
|
<SCHEMA_USER>
|
sr-pprod-1.corp.fr
|
08/04/2013 17:25
|
LOGON
|
28000
|
oracle
|
unknown
|
<SCHEMA_USER>
|
sr-pprod-1.corp.fr
|
08/04/2013 17:25
|
LOGON
|
28000
|
oracle
|
unknown
|
<SCHEMA_USER>
|
sr-pprod-1.corp.fr
|
08/04/2013 17:25
|
LOGON
|
1017
|
oracle
|
unknown
|
<SCHEMA_USER>
|
sr-pprod-1.corp.fr
|
08/04/2013 17:25
|
LOGON
|
1017
|
oracle
|
unknown
|
<SCHEMA_USER>
|
sr-pprod-1.corp.fr
|
08/04/2013 17:25
|
LOGON
|
1017
|
oracle
|
unknown
|
<SCHEMA_USER>
|
sr-pprod-1.corp.fr
|
08/04/2013 17:25
|
LOGON
|
1017
|
oracle
|
unknown
|
<SCHEMA_USER>
|
sr-pprod-1.corp.fr
|
08/04/2013 17:25
|
LOGON
|
1017
|
oracle
|
unknown
|
<SCHEMA_USER>
|
sr-pprod-1.corp.fr
|
08/04/2013 17:25
|
LOGON
|
1017
|
oracle
|
unknown
|
<SCHEMA_USER>
|
sr-pprod-1.corp.fr
|
08/04/2013 17:25
|
LOGON
|
1017
|
oracle
|
unknown
|
<SCHEMA_USER>
|
sr-pprod-1.corp.fr
|
08/04/2013 17:25
|
LOGON
|
1017
|
oracle
|
unknown
|
<SCHEMA_USER>
|
sr-pprod-1.corp.fr
|
08/04/2013 17:25
|
LOGON
|
1017
|
oracle
|
unknown
|
<SCHEMA_USER>
|
sr-pprod-1.corp.fr
|
08/04/2013 17:25
|
LOGON
|
1017
|
BI_USER
|
unknown
|
<SCHEMA_USER>
|
PC-08013808-ID
|
08/04/2013 17:24
|
LOGON
|
0
|
oracle
|
unknown
|
<SCHEMA_USER>
|
sr-pprod-1.corp.fr
|
08/04/2013 17:24
|
LOGON
|
1017
|
oracle
|
unknown
|
<SCHEMA_USER>
|
sr-pprod-1.corp.fr
|
08/04/2013 17:24
|
LOGON
|
1017
|
oracle
|
unknown
|
<SCHEMA_USER>
|
sr-pprod-1.corp.fr
|
08/04/2013 17:24
|
LOGON
|
1017
|
oracle
|
unknown
|
<SCHEMA_USER>
|
sr-pprod-1.corp.fr
|
08/04/2013 17:24
|
LOGON
|
1017
|
oracle
|
unknown
|
<SCHEMA_USER>
|
sr-pprod-1.corp.fr
|
08/04/2013 17:24
|
LOGON
|
1017
|
BI_USER
|
unknown
|
<SCHEMA_USER>
|
PC-08013808-ID
|
08/04/2013 17:23
|
LOGON
|
0
|
BI_USER
|
unknown
|
<SCHEMA_USER>
|
PC-08013808-ID
|
08/04/2013 17:21
|
LOGON
|
0
|
BI_USER
|
unknown
|
<SCHEMA_USER>
|
PC-08013808-ID
|
08/04/2013 17:20
|
LOGON
|
0
|
BI_USER
|
unknown
|
<SCHEMA_USER>
|
PC-08013808-ID
|
08/04/2013 17:14
|
LOGON
|
0
|
BI_USER
|
unknown
|
<SCHEMA_USER>
|
PC-08013808-ID
|
08/04/2013 17:11
|
LOGON
|
0
|
2] Log every DDL orders
Who drop my
table ?
Easier than log mining, I may audit every DDLs on my database from now
on and find out what’s going on :
Goal
|
Log DDLs actions
|
Version
|
10gR2
|
Trigger
|
AFTER DDL ON DATABASE
|
Log as
|
SYSTEM
|
I log every DDL except 'CREATE','COMMENT','ANALYZE'
CREATE TABLE ddl_log (
user_name VARCHAR2(30),
ddl_date DATE,
ddl_type VARCHAR2(30),
object_type VARCHAR2(18),
owner VARCHAR2(30),
object_name VARCHAR2(128))
TABLESPACE SCH_DAT ;
CREATE OR REPLACE TRIGGER ddl_trig
AFTER DDL ON DATABASE
DECLARE
oper ddl_log.ddl_type%TYPE;
BEGIN
SELECT
ora_sysevent INTO oper FROM dual;
IF oper NOT IN ('CREATE','COMMENT','ANALYZE') THEN
INSERT INTO ddl_log
(user_name, ddl_date, ddl_type,
object_type, owner, object_name)
VALUES
(ora_login_user, SYSDATE, ora_sysevent,ora_dict_obj_type, ora_dict_obj_owner,ora_dict_obj_name);
END IF;
END ddl_trig;
/
Who did
it ? Well, I
did !!
select * from ddl_log order by ddl_date desc ;
-- select ddl_type , count(1) from ddl_log group by ddl_type ;
USER_NAME
|
DDL_DATE
|
DDL_TYPE
|
OBJECT_TYPE
|
OWNER
|
OBJECT_NAME
|
SYSTEM
|
27/04/2011 06:00
|
DROP
|
TABLE
|
IUS
|
BIN$od...+g==$0
|
SYSTEM
|
27/04/2011 06:00
|
DROP
|
VIEW
|
IUS
|
APP_SDI_DR_OS
|
SYSTEM
|
27/04/2011 06:00
|
DROP
|
TABLE
|
IUS
|
AD_MACHINE
|
SYSTEM
|
27/04/2011 06:00
|
ALTER
|
TABLE
|
IUS
|
AD_USER
|
More
complete :
CREATE TABLE DDL_LOG
(
OS_USER
VARCHAR2(255 BYTE),
HOST
VARCHAR2(255 BYTE),
MODULE
VARCHAR2(64 BYTE),
SERVICE_NAME
VARCHAR2(64 BYTE),
USER_NAME
VARCHAR2(30 BYTE),
DDL_DATE
DATE,
DDL_TYPE
VARCHAR2(30 BYTE),
OBJECT_TYPE
VARCHAR2(18 BYTE),
OWNER
VARCHAR2(30 BYTE),
OBJECT_NAME
VARCHAR2(128 BYTE)
) ;
CREATE OR REPLACE TRIGGER DDL_TRIG
AFTER DDL ON DATABASE
DECLARE
oper SCHEMA.ddl_log.ddl_type%TYPE;
obje SCHEMA.ddl_log.object_name%TYPE;
moduleU VARCHAR2 (64) := sys_context('USERENV', 'MODULE');
service VARCHAR2 (64) := sys_context('USERENV', 'SERVICE_NAME');
BEGIN
SELECT
ora_sysevent INTO oper FROM dual;
SELECT
ora_dict_obj_name INTO obje FROM dual;
IF oper NOT IN ('CREATE','COMMENT','ANALYZE') AND obje not like 'SYS_EXPORT_SCHEMA%' and obje not like 'ORA_TEMP_1_DS_%' THEN
INSERT INTO DDL_LOG
(os_user, host, module , service_name ,
user_name, ddl_date, ddl_type,
object_type, owner, object_name)
VALUES
(sys_context('USERENV','OS_USER'), sys_context('USERENV','HOST'), moduleU , service ,
ora_login_user, SYSDATE, ora_sysevent,
ora_dict_obj_type,
ora_dict_obj_owner,
ora_dict_obj_name);
END IF;
END DDL_TRIG;
/
3] Audit on object level
3.1 Pre-requisite
Why is the
inserted record missing in this table ??
Some Examples About Auditing And Output Of Auditing [ID 167293.1]
BY SESSION/BY ACCESS
BY SESSION causes Oracle Database to write a single record for
all SQL statements of the same type issued in the same session.
BY ACCESS causes Oracle to
write one record for each access.
- Pre-requisite
alter system set audit_trail = 'DB_EXTENDED' scope = spfile ;
SQL>
sho parameter audit_trail
NAME TYPE VALUE
------------------------------------
----------- ------------------------------
audit_trail string DB
NAME TYPE VALUE
------------------------------------
----------- ------------------------------
audit_trail string DB_EXTENDED
3.2 By Session
- Options
SQL> select * from all_def_audit_opts;
ALT AUD COM DEL GRA IND INS LOC REN SEL UPD REF EXE FBK REA
ALT AUD COM DEL GRA IND INS LOC REN SEL UPD REF EXE FBK REA
These correspond to the following object options:
alter audit comment delete grant index insert lock rename select update reference execute
alter audit comment delete grant index insert lock rename select update reference execute
- Audit ALL
connect smh
SQL>
audit all on SMH.DOSSIER by session ;
SQL> connect SYSTEM
audit select,delete,insert,update on APP01.T01 ;
Default :
BY SESSION
SQL> select * from
dba_obj_audit_opts where owner='APP01' and object_name='T01';
OWNER OBJECT_NAME OBJECT_TYPE
------------------------------
------------------------------ -----------------
ALT AUD COM DEL GRA IND INS
LOC REN SEL UPD REF EXE CRE REA WRI FBK
--- --- --- --- --- --- ---
--- --- --- --- --- --- --- --- --- ---
APP01 BIN_DOCS TABLE
-/- -/- -/- S/S -/- -/- S/S
-/- -/- S/S S/S -/- -/- -/- -/- -/- -/-
OWNER
|
OBJECT_NAME
|
OBJECT_TYPE
|
ALT
|
AUD
|
COM
|
DEL
|
GRA
|
IND
|
INS
|
LOC
|
REN
|
SEL
|
UPD
|
REF
|
EXE
|
CRE
|
REA
|
WRI
|
FBK
|
IAN
|
ITBU_SITE
|
TABLE
|
S/S
|
S/S
|
S/S
|
S/S
|
S/S
|
S/S
|
S/S
|
S/S
|
S/S
|
S/S
|
S/S
|
-/-
|
-/-
|
-/-
|
-/-
|
-/-
|
S/S
|
IUS
|
ADCORP_MACHINES_SITES
|
VIEW
|
-/-
|
S/S
|
S/S
|
S/S
|
S/S
|
-/-
|
S/S
|
S/S
|
S/S
|
S/S
|
S/S
|
-/-
|
-/-
|
-/-
|
-/-
|
-/-
|
S/S
|
IUS
|
ADCORP_DEPLOY_APP_SITES
|
VIEW
|
-/-
|
S/S
|
S/S
|
S/S
|
S/S
|
-/-
|
S/S
|
S/S
|
S/S
|
S/S
|
S/S
|
-/-
|
-/-
|
-/-
|
-/-
|
-/-
|
S/S
|
- Reset
connect
smh
SQL>
NOAUDIT ALL on SMH.DOSSIER ;
Noaudit
succeeded.
SQL> connect SYSTEM
noaudit select,delete,insert,update on
dgc.bin_docs ;
§
See results
select userid,ntimestamp#,ses$actions,sqltext,sqlbind from sys.aud$ ;
select count(1) from dgc.bin_docs ;
delete APP01.T01 where 1=2 ;
commit ;
SQL>
connect SYSTEM
select timestamp, username, priv_used, ses_actions from dba_audit_object where obj_name='T01' and owner='APP01';
TIMESTAMP
|
USERNAME
|
PRIV_USED
|
SES_ACTIONS
|
10/09/2012 10:36
|
SYSTEM
|
SELECT ANY TABLE
|
---------S------
|
10/09/2012 10:41
|
SYSTEM
|
DELETE ANY TABLE
|
---S------------
|
The characters are:
- for none
S for success
F for failure
B for both
More
information :
select timestamp, username, owner , obj_name, priv_used , decode(ses_actions,
'---S------------','DELETE',
'------S---------','INSERT',
'---------S------','SELECT',
'----------S-----','UPDATE',
'---S--S--S------','DELETE/INSERT/SELECT',
'---S--S--SS-----','DELETE/INSERT/SELECT/UPDATE',
'------S--S------','INSERT/SELECT',
'------S--SS-----','INSERT/SELECT/UPDATE',
'---------SS-----','SELECT/UPDATE',
'UNKNOWN') ACTION
--ses_actions
from dba_audit_object where obj_name in ('ITBU_SITE','ADCORP_DEPLOY_APP_SITES','ADCORP_MACHINES_SITES')
order by timestamp desc
TIMESTAMP
|
USERNAME
|
OWNER
|
OBJ_NAME
|
PRIV_USED
|
ACTION
|
16/04/2014 10:55
|
APEX_PUBLIC_USER
|
IAN
|
ITBU_SITE
|
|
SELECT
|
16/04/2014 09:44
|
APEX_PUBLIC_USER
|
IAN
|
ITBU_SITE
|
|
SELECT
|
16/04/2014 09:28
|
DI
|
IAN
|
ITBU_SITE
|
|
SELECT
|
3.3 By Access
SQL>
audit delete,insert,update on APP.CITY by access ;
SQL> col
obj_name for a20
SQL> col
SES_ACTIONS for a30
SQL> select
timestamp, obj_name, username, action_name, ses_actions, returncode from
dba_audit_object where obj_name='CITY' and owner='APP';
TIMESTAMP OBJ_NAME USERNAME
ACTION_NAME SES_ACTIONS RETURNCODE
--------------------
-------------------- ------------------------------ ---------
04-DEC-2012
09:57:13 CITY SMITH UPDATE
0
04-DEC-2012
09:57:37 CITY SMITH INSERT
0
04-DEC-2012
09:57:42 CITY SMITH DELETE 0
If audit is set by SESSION, the column DBA_AUDIT_OBJECT.SES_ACTIONS
contains a value that explains if any of the DML action succeeded or not
within the session .
Refer NOTE:1019326.102
'SES_ACTIONS in DBA_AUDIT_OBJECT' for more details on the possible values.
If audit is set by ACCESS, the column DBA_AUDIT_OBJECT.SES_ACTIONS is
empty.
select timestamp, sql_text , sql_bind
from
dba_audit_object where owner = 'USER' and action_name = 'DELETE' order by 1 desc
TIMESTAMP
|
SQL_TEXT
|
SQL_BIND
|
PRIJA
|
|
Variables
|
30/01/2015 11:18
|
delete from t1 where t1_id=:1
|
#1(6):103784
|
30/01/2015 11:18
|
delete from t2 where t2_id=:1
|
#1(6):103784
|
30/01/2015 11:18
|
delete from t3 where t3_id=:1 and name=:2
|
#1(6):103755 #2(36): Revues_2012 TRAV
SOC.xls
|
3.4 11G+
Starting with Oracle 11g the BY SESSION clause is obsolete. This is
documented in the Database Security Guide :
" The BY SESSION clause of the AUDIT statement now writes one
audit record for every audited event. In previous releases, BY SESSION wrote
one audit record for all SQL statements or operations of the same type that
were executed on the same schema objects in the same user session. Now, both BY
SESSION and BY ACCESS write one audit record for each audit operation. In addition,
there are separate audit records for LOGON and LOGOFF events. "
When AUD$
becomes very Huge :
truncate
table aud$;
CAUTION: SYS.AUD$ is the only SYS object that should ever be directly
modified
Watch for
item in the audit trail :
select USERNAME, action,
action_name, count(*) from
dba_audit_trail
group by USERNAME, action,
action_name order by USERNAME, action;
Execute
Monthly truncate :
-- AUDIT TABLE 7 GB
select sum(bytes/1024/1024) from
dba_segments where owner = 'SYS' and segment_name = 'AUD$' -- 7766 MB
-- execute a single Delete every Month
-- as SYS : truncate table aud$
BEGIN
DBMS_SCHEDULER.CREATE_JOB (
job_name => 'TRUNC_AUDIT_TRAIL',
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN
EXECUTE IMMEDIATE ''TRUNCATE TABLE aud$'' ; END;',
start_date =>
to_timestamp('09/12/2014
10:15:00', 'dd/mm/yyyy
hh24:mi:ss'),
repeat_interval => 'FREQ=MONTHLY;BYDAY=WED;BYHOUR=10;BYMINUTE=00;',
enabled => TRUE,
comments
=> 'SCH 091214:
truncate table aud$;');
END;
/
EXEC dbms_scheduler.run_job('TRUNC_AUDIT_TRAIL');
select sum(bytes/1024/1024) from dba_segments where owner = 'SYS' and segment_name = 'AUD$' -- 0,06 MB
4] Audit Oracle Schemas to find out if they are used
Goal
|
Find last Access on Tables
|
Version
|
10gR2
|
SELECT
uses
|
SYS.col_usage$, dba_objects,
dba_tab_columns
|
DML uses
|
|
Log as
|
SYSTEM
|
4.1 READ Access
Last Access
was more than 6 Months :
-- 1/ READ
-- Tables most recent
SELECT access
-- More than 6 Months
-- create table SCH.APP_NOT_READ_AFTER
( OWNER varchar2(32) , WAS_NOT_READ_AFTER date ) ;
insert into SCH.APP_NOT_READ_AFTER
select owner , Most_Recent_Select_Access_Date from (
SELECT distinct b.owner, max(a.timestamp) over ( partition by b.owner )
Most_Recent_Select_Access_Date
--
dba_tab_columns.table_name, --
dba_tab_columns.column_name, --SYS.col_usage$.*
FROM SYS.col_usage$
a, dba_objects, dba_tab_columns b
WHERE obj# = dba_objects.object_id
AND b.owner = dba_objects.owner
AND b.table_name
= dba_objects.object_name
AND intcol# = b.column_id
AND dba_objects.owner not in ('APEX_030200','APPQOSSYS','CTXSYS','DBSNMP','EXFSYS','FLOWS_FILES','MDSYS','OLAPSYS','ORACLE_OCM','ORDDATA','ORDPLUGINS','ORDSYS','OUTLN','OWBSYS','SCOTT','SYS','SYSMAN','SYSTEM','WMSYS','XDB')
-- AND object_name = 'T'
)
where
Most_Recent_Select_Access_Date < sysdate-(31*6)
ORDER BY owner -- intcol#
commit ;
OWNER WAS_NOT_READ_AFTER
APP1 19/03/2015 14:51:01
APP2 18/03/2015 10:37:01
APP3 13/02/2015 08:53:26
APP4 16/01/2015 15:34:12
4.2 WRITE Access
--select owner ,
sum(bytes/1024/1024) from dba_segments group by owner order by 2 desc
-- 2/ WRITE
-- Tables most recent
WRITE access
-- QUERY = select
min(first_time) WAS_NOT_Modified_AFTER from v$log_history where first_change#
>= ( select max(ora_rowscn) from HGS.AGENT ) ;
-- create table SCH.APP_NOT_MODIFIED_AFTER
( OWNER varchar2(32) , TABLE_NAME varchar2(32) , WAS_NOT_MODIFIED_AFTER date )
;
truncate table SCH.APP_NOT_MODIFIED_AFTER
;
-- select min(first_time)
WAS_NOT_Modified_AFTER from v$log_history -- where first_change# >= ( select
max(ora_rowscn) from ACT.MAIL_LIGNES )
-- 24/06/2015 23:48:44
// 4 MONTHS
set
serveroutput on
DECLARE
OWNER varchar2(32) ;
TABLE_NAME varchar2(32) ;
lmdwb date ;
begin
dbms_output.disable; -- *** Line added ***
dbms_output.enable(100000); -- *** Line added ***
for i in ( select owner ,
table_name from dba_tables where table_name not like 'QTSF_CHAIN%' and -- owner = 'SSD' and
owner not in
('APEX_030200','APEX_040000','APPQOSSYS','CTXSYS','DBSNMP','EXFSYS','FLOWS_FILES','MDSYS','OLAPSYS','ORACLE_OCM','ORDDATA','ORDPLUGINS','ORDSYS','OUTLN','OWBSYS','SCOTT','SYS','SYSMAN','SYSTEM','WMSYS','XDB')
order by 1,2 )
loop
BEGIN
-- DBMS_OUTPUT.PUT_LINE( '
'||i.owner||'.'||i.table_name||' ' ) ;
execute immediate 'select
min(first_time) from v$log_history where first_change# >= ( select
max(ora_rowscn) from "'||i.owner||'"."'||i.table_name||'" )' into lmdwb ;
-- DBMS_OUTPUT.PUT_LINE( ' '||i.owner||'.'||i.table_name||'
: '||lmdwb ) ;
if lmdwb is not null -- Table has zero row
then
execute immediate 'insert into SCH.APP_NOT_MODIFIED_AFTER
values ( '''||i.owner||''' , '''||i.table_name||''' , '''||lmdwb||''' )' ;
--
DBMS_OUTPUT.PUT_LINE( 'insert into SCH.WAS_NOT_MODIFIED_AFTER values (
'''||i.owner||''' , '''||i.table_name||''' , '''||lmdwb||''' )' ) ;
end if ;
END;
commit ;
end loop;
end;
/
4.3 Concat the Results
Into a table