Is there a Oracle data dictionary table that associates a trigger with its trigger audit table?
enter image description here
You can check out DBA_DEPENDENCIES
SELECT *
FROM dba_dependencies
WHERE TYPE = 'TRIGGER' AND referenced_type = 'TABLE';
Query user_dependencies.
For example:
SQL> create or replace trigger trg_test
2 before insert on emp
3 for each row
4 begin
5 insert into dept (deptno) values (:new.deptno);
6 insert into owner (id_owner, name) values (:new.empno, :new.ename);
7 end;
8 /
Trigger created.
SQL> select referenced_name, referenced_type
2 from user_dependencies
3 where referenced_owner = user
4 and name = 'TRG_TEST';
REFERENCED_NAME REFERENCED_TYPE
-------------------- ------------------
DEPT TABLE --> trigger line #5
EMP TABLE --> trigger line #2
OWNER TABLE --> trigger line #6
SQL>
Bonus: there's that nice view called dictionary. If you query it, it reveals useful information and shows which tables (views) you could try to query to find information you need. In this very case:
SQL> select table_name, comments
2 from dictionary
3 where lower(comments) like '%dependenc%';
TABLE_NAME COMMENTS
------------------------------ ------------------------------------------------------------
ALL_DEPENDENCIES Dependencies to and from objects accessible to the user
ALL_XSC_SECURITY_CLASS_DEP All security class dependencies in the database
USER_DEPENDENCIES Dependencies to and from a users objects
SQL>
If you could assist with a query that returns number of end-users accessing the application.
The below query returns only the sessions
SQL> select count(*) from v$session where status='ACTIVE';
COUNT(*)
----------
67
SQL> select count(*) from v$session;
COUNT(*)
----------
140
I logged in as SYSTEM in SQL dev and did this:
ALTER SESSION SET "_ORACLE_SCRIPT" = TRUE;
CREATE TABLE Attendance
(
ID INT ,
NAME NVARCHAR2(300),
CONSTRAINT IdPk PRIMARY KEY (ID)
);
CREATE ROLE DataEntry;
GRANT SELECT, INSERT, UPDATE ON Attendance TO DataEntry;
How to find the permissions assigned to the DataEntry role? I've researched for a while, but the answers found didn't work. For example:
select * from ROLE_ROLE_PRIVS;
select * from ROLE_TAB_PRIVS;
select * from ROLE_SYS_PRIVS;
These statements return many many roles such as: dba,sys,.... But i still can't find my 'DataEntry' role. Can someone explain this to me? Thanks alot.
If you created any objects connected as SYSTEM, you'd rather not do that. SYS and SYSTEM are special, don't mess up with them.
As of your question:
SQL> show user
USER is "SCOTT"
SQL> create role dataentry;
Role created.
SQL> grant select, insert, update on emp to dataentry;
Grant succeeded.
SQL> select * From role_tab_privs;
ROLE OWNER TABLE_NAME COLUMN_NAM PRIVILEGE GRA
---------- ---------- ---------- ---------- ---------- ---
DATAENTRY SCOTT EMP INSERT NO
DATAENTRY SCOTT EMP SELECT NO
DATAENTRY SCOTT EMP UPDATE NO
SQL>
If you wanted to do such a query connected as a privileged user, then it is dba_tab_privs:
SQL> show user
USER is "SYS"
SQL> select * From dba_tab_privs where owner = 'SCOTT';
GRANTEE OWNER TABLE_NAME GRANTOR PRIVILEGE GRA HIE
------------ ---------- ---------- ---------- ---------- --- ---
MIKE SCOTT DEPT SCOTT DELETE YES NO
DATAENTRY SCOTT EMP SCOTT INSERT NO NO
DATAENTRY SCOTT EMP SCOTT SELECT NO NO
DATAENTRY SCOTT EMP SCOTT UPDATE NO NO
SQL>
Since you tagged SQLDev...open the View menu, select DBA.
Add your connection. Expand, go to Security, Select Roles, open your Role.
Observe the Object Privs panel.
SQL Developer gets the object privs for a roles using this SQL
SELECT privilege AS "Object Privilege"
, owner AS "Schema"
, table_name AS "Object"
FROM dba_tab_privs
WHERE grantee = :name -- DATAENTRY
ORDER BY 2
, 3
, 1
I read that
USER_TABLES is tables which you own
ALL_TABLES is tables which own, and tables owner by other users, which you have been granted explicit access to
DBA_TABLES is all tables in the database
All three are views of the underlying SYS tables
Based on the above and mention of SYS.TABLES in the Oracle Docs, I tried to
select * from SYS.TABLES;
but it resulted in an error that the table or view does not exist. I tried as both SYS and another username.
Question 1:
Is SYS.TABLES a valid table in Oracle 11g ?
Question 2:
If yes, is SYS.TABLES the underlying table for the view DBA_TABLES ?
Question 3:
If yes, what privileges do I need to select from the SYS.TABLES ?
Question 4:
How do I find the underlying column and the tables for a view such as DBA_TABLES ?
I have edited the question. Sorry about the confusion I caused earlier.
This is 11g (XE, though; never mind that).
As you wonder about SYS-owned objects, connect as such.
SQL> select * from v$version where rownum = 1;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
SQL> connect sys as sysdba
Enter password:
Connected.
1.
Does TABLES exist? Nope.
SQL> desc tables;
ERROR:
ORA-04043: object tables does not exist
But, TAB does:
SQL> desc tab;
Name Null? Type
----------------------------------------- -------- ----------------------------
TNAME NOT NULL VARCHAR2(30)
TABTYPE VARCHAR2(7)
CLUSTERID NUMBER
2.
In order to find what DBA_TABLES really is:
SQL> select owner, object_type from dba_objects where object_name = 'DBA_TABLES';
OWNER OBJECT_TYPE
------------------------------ -------------------
SYS VIEW
PUBLIC SYNONYM
4.
OK, it is a view. Which query is it made of?
SQL> set long 20000
SQL> select text from dba_views where view_name = 'DBA_TABLES';
TEXT
--------------------------------------------------------------------------------
select u.name, o.name,
decode(bitand(t.property,2151678048), 0, ts.name,
decode(t.ts#, 0, null, ts.name)),
decode(bitand(t.property, 1024), 0, null, co.name),
decode((bitand(t.property, 512)+bitand(t.flags, 536870912)),
0, null, co.name),
decode(bitand(t.trigflag, 1073741824), 1073741824, 'UNUSABLE', 'VALID'),
<snip>
from sys.user$ u, sys.ts$ ts, sys.seg$ s, sys.obj$ co, sys.tab$ t, sys.obj$ o,
sys.obj$ cx, sys.user$ cu, x$ksppcv ksppcv, x$ksppi ksppi,
sys.deferred_stg$ ds
where o.owner# = u.user#
and o.obj# = t.obj#
and bitand(t.property, 1) = 0
and bitand(o.flags, 128) = 0
and t.bobj# = co.obj# (+)
and t.ts# = ts.ts#
<snip>
(It is a quite long query so I displayed only some parts of it; now that you know how to do it, do it yourself for more info).
TAB is, on the other hand, quite simpler:
SQL> select text from dba_views where view_name = 'TAB';
TEXT
---------------------------------------------------------------
select o.name,
decode(o.type#, 2, 'TABLE', 3, 'CLUSTER',
4, 'VIEW', 5, 'SYNONYM'), t.tab#
from sys.tab$ t, sys."_CURRENT_EDITION_OBJ" o
where o.owner# = userenv('SCHEMAID')
and o.type# >=2
and o.type# <=5
and o.linkname is null
and o.obj# = t.obj# (+)
You'd use the same principle for "tables" specified in the FROM clause, e.g.
SQL> select owner, object_type from dba_objects where object_name = 'TAB$';
OWNER OBJECT_TYPE
------------------------------ -------------------
SYS TABLE
So - yes, that's the end. TAB$ is the final table, there's nothing behind.
3.
If connected as SYS, you don't need any additional privileges. SYS owns the database, it is the boss, it can do anything.
For other users, owner grants privileges, e.g. (still connected as SYS):
SQL> grant select on tab$ to scott;
Grant succeeded.
SQL> grant select on x$ksppcv to scott;
grant select on x$ksppcv to scott
*
ERROR at line 1:
ORA-02030: can only select from fixed tables/views
SQL>
That should be it, I presume.
Just a note: SYS is, as I said, powerful. Be careful what you do. I hope you have a database to spare like I do; nothing much will happen if I screw something here, there's no important data stored in it. Don't play games on production databases.
Using Oracle VPD, after adding a policy and creating a function, I was able to hide a column from unauthorized users.
But instead of (null) how can i show something like 'xxxxxx'
Also in the function I am validation for the user login, like
if sys_context( 'userenv', 'session_user' ) = 'USER1'
what is the best approach to remove this hard coding in the function?
Thanks in advance.
in order to return text in the place of not null, you'd have to create a view over top of the table to change null into the static literal you wanted, as the only option in VPD would be to hide the rows or set the secret columns to NULL.
for your second part of your question, if you are using that check to determine who has access to the sensitive columns, you can use a role instead and have the VPD function check this like:
return 'exists (select null from session_roles where role = ''XXXXXX'')';
i.e. whomever has the role XXXXXX (just create an appropriate role and grant it to your privileged users) set in their session can see the data. That way you don't need to hard code a bunch of user ids.
e.g:
if we create a role and grant it to a test user:
SQL> create role ACCESS_TABLEA_SEC_COL;
Role created.
SQL> grant ACCESS_TABLEA_SEC_COL to test;
Grant succeeded.
for my set up ive created a simple test table + a policy that stops people reading the your_sec_col column.
SQL> create or replace package pkg_security_control
2 as
3 function apply_access(p_owner in varchar2, p_obj_name in varchar2) return varchar2;
4 end;
5 /
Package created.
SQL> create or replace package body pkg_security_control
2 as
3 function apply_access(p_owner in varchar2, p_obj_name in varchar2)
4 return varchar2
5 is
6 begin
7 return 'exists (select null from session_roles where role = ''ACCESS_TABLEA_SEC_COL'')';
8 end;
9 end;
10 /
Package body created.
SQL> create table TABLEA
2 (
3 id number primary key,
4 your_sec_col varchar2(30)
5 );
Table created.
SQL> insert into tablea values (1, 'secret text1');
1 row created.
SQL> insert into tablea values (2, 'secret text2');
1 row created.
now if we select from that table and we don't have the ACCESS_TABLEA_SEC_COL role, we'd get:
SQL> select *
2 from tablea;
ID YOUR_SEC_COL
---------- ------------------------------
1
2
but you want a string like xxxxx. VPD itself cannot do this, but a view could decode NULL to that string.
SQL> create view v_tablea
2 as
3 select id, case when your_sec_col is null then 'xxxxxx' else your_sec_col end your_sec_col
4 from TABLEA;
View created.
now selecting from the view will , depending on whether the role is set:
SQL> set role none;
Role set.
SQL> select *
2 from tablea;
ID YOUR_SEC_COL
---------- ------------------------------
1
2
SQL> select *
2 from v_tablea;
ID YOUR_SEC_COL
---------- ------------------------------
1 xxxxxx
2 xxxxxx
SQL> set role all;
Role set.
SQL> select *
2 from v_tablea;
ID YOUR_SEC_COL
---------- ------------------------------
1 secret text1
2 secret text2
SQL> select *
2 from tablea;
ID YOUR_SEC_COL
---------- ------------------------------
1 secret text1
2 secret text2
so VPD still protects your table against anyone selecting from it, but you'd have clients select from the view to get the literal string instead. If your protected strings can contain NULL, and you want to differentiate those from no access, you can put the role check in the view instead.
create view v_tablea
as
select id,
case (select 'A' from session_roles where role = 'ACCESS_TABLEA_SEC_COL')
when 'A' then your_sec_col else 'xxxxxxxx' end your_sec_col
from TABLEA;