How to see what privileges are granted to schema of another user - oracle

Consider the case : In a database , I have two users A and B and their corresponding schema.
I want to know , How can I get the information : what permissions are there for USER A in Schema B .
Consider the case : We have two users and their associated scehmas. We have user A and user B. In A, say we have TB1 TB2, in B,say we have TBa, TBb. Now I want to know how can I find what privileges User A has on Schema B.
For example : User A is writing : select * from B.TBb This means USER A is accessing User B's table so , it shows he has SELECT Privilege. I want to know what all privileges User A has on Schema B.
Which query shall be executed to get the list of privileges that User A has on Schema B.

You can use these queries:
select * from all_tab_privs;
select * from dba_sys_privs;
select * from dba_role_privs;
Each of these tables have a grantee column, you can filter on that in the where criteria:
where grantee = 'A'
To query privileges on objects (e.g. tables) in other schema I propose first of all all_tab_privs, it also has a table_schema column.
If you are logged in with the same user whose privileges you want to query, you can use user_tab_privs, user_sys_privs, user_role_privs. They can be queried by a normal non-dba user.

Use example with from the post of Szilágyi Donát.
I use two querys, one to know what roles I have, excluding connect grant:
SELECT * FROM USER_ROLE_PRIVS WHERE GRANTED_ROLE != 'CONNECT'; -- Roles of the actual Oracle Schema
Know I like to find what privileges/roles my schema/user have; examples of my roles ROLE_VIEW_PAYMENTS & ROLE_OPS_CUSTOMERS. But to find the tables/objecst of an specific role I used:
SELECT * FROM ALL_TAB_PRIVS WHERE GRANTEE='ROLE_OPS_CUSTOMERS'; -- Objects granted at role.
The owner schema for this example could be PRD_CUSTOMERS_OWNER (or the role/schema inself).
Regards.

Login into the database. then run the below query
select * from dba_role_privs where grantee = 'SCHEMA_NAME';
All the role granted to the schema will be listed.
Thanks Szilagyi Donat for the answer. This one is taken from same and just where clause added.

Related

Is it possible to see a sequence in all_sequences without having the SELECT right on the sequence?

I need to retrieve the list of available sequences of a certain database schema in an Oracle 10g database (10.2.0.3).
With the schema owner, I can simply do something like the following to achieve this:
SELECT sequence_name FROM all_sequences WHERE sequence_owner = 'ABCDEF';
However, If I use a user which has a custom "read-only" role assigned, that user does not get any rows when executing that query.
I've played around a bit and found out that granting the SELECT option on the sequences to the read-only role makes those sequences appear in the all_sequences view when connected with the read-only user.
However this means that the read-only user is able to do
SELECT my_sequence.NEXTVAL FROM DUAL;
which is a no-go for our situation (after all, the read-only user shall not be able to modify anything, not even sequences).
Is there another way for retrieving the sequences which does not allow selecting NEXTVAL?
[Edit:]
If I do
SELECT DISTINCT sequence_owner FROM all_sequences;
I get the following list:
SEQUENCE_OWNER
------------------------------
MDSYS
DMSYS
OLAPSYS
XDB
SYS
5 rows selected
After using the system user to do
GRANT SELECT ANY DICTIONARY TO MY_USER;
the result stays the same (revoke does not change anything either).
Granting the SELECT_CATALOG_ROLE instead does not work either.
Granting SELECT on at least one of the sequences however changes the result to include my own schema owner.
You can try to grant SELECT ANY DICTIONARY privilege, but it's very bad for the security reasons, so, I guess, your DBA will deny it.
Good decision is to create table function publishes required data. By default this function will work with AUTHID DEFINER rights, so you should just grant it to read-only user and it would receive sequences info without any chance to change them.
The best solution I can come up with is to grant the user SELECT ANY DICTIONARY. This will give them access to DBA_SEQUENCES (as well as all of the other DBA_ views) without needing permissions on the objects.

How can I ensure a grant has been performed?

In Oracle, when I run:
GRANT SELECT on MYSCHEMA.ORDERS to APP_USER;
What query can I run in Oracle to check if this grant exists? I would like to validate that this grant is correctly created in our development, QA, and production databases.
You can get that from the all_tab_privs performance view, or the user_ or dba_ equivalents depending on your situation and privileges:
select *
from all_tab_privs
where table_schema = 'MYSCHEMA'
and table_name = 'ORDERS'
and grantee = 'APP_USER';
To see everyone who has access, leave off the grantee filter. Note though that the grantee may be (and quite probably should be) a role, not an individual user. In that case you'd need to see who has that role granted to get the full picture, and roles can be granted to roles, so that can get a bit recursive.
Execute the following (if you are logged in as app_user) :-
select owner from user_tab_privs where table_name='Order' and grantee='App_user' and owner='MySchema';
If you are logged in as dba, then execute following :-
select owner from dba_tab_privs where table_name='Order' and grantee='App_user' and owner='MySchema';
If the grant was successful, then the above sql statements should have non-null output.

Oracle : check for read/write privileges, automated testing

I have a question about Oracle and checking privileges.
Some background Info
I wrote some php scripts that will 'test' various things in our environment. One of those tasks is checking that a user has execute privileges on a procedure and that the procedure is valid/compiled.
Here is the query
select ao.object_name, utp.grantee, ao.status, utp.privilege
from all_objects ao, user_tab_privs utp
where utp.owner = ao.owner and
ao.object_name = utp.table_name and
upper( ao.object_name ) = :object_name and
ao.object_type = 'PACKAGE' and
utp.privilege = 'EXECUTE' and
ao.status = 'VALID'
This has worked well and has saved us time on procedure privileges; I do realize now that I can also double check the all_tab_privs to check execute access as well.
The problem
Now my question is, how do I do something similar with tables? We ran into an issue where a certain user had SELECT privs on a table but not UPDATE/INSERT privs. How can I check for each of these privileges individually. I've looked into all_tab_privs but haven't found it shows me what I want. It has procedures I can execute but when I check to see if a known table is there it isn't. For example, I'll run the following
select * from all_tab_privs
where table_name = 'KNOWN_TABLE' and
grantee = 'CURRENT_USER'
and privilege in ( 'SELECT', 'UPDATE', 'INSERT' );
but instead of getting back 3 rows for a table I know 100% that I can already select/insert/update it returns nothing.
Any ideas? Thank you.
Disclaimer
I am aware that I could just try inserting/updating data and then deleting it but I'd rather not do this. I'd rather not leave any trace since these scripts will run periodically, should be repeatable, and shouldn't alter the state of any piece of data, even if it's just a sequence on the table.
Also, if you could provide a 'list' of possible queries that I can use to determine privileges that would be fine. For example, to determine if i have select access run query 1, 2 and 3. If either returns data then you have select privs and so on for insert/update.
This looks rather optimistic to me, as the role issue could get really complex, particularly if roles ever get password protected, and I'd never really trust the method 100% without actually trying the DML.
It might be more simple to try queries such as:
select count(*)
from schema_name.table_name
where 1=0;
insert into schema_name.table_name
select *
from schema_name.table_name
where 1=0;
delete from schema_name.table_name
where 1=0;
update schema_name.table_name
set column_name = column_name
where 1=0;
I believe that such queries would fail if no privileges were granted (no database handy to check it), and they would never modify any data.
By the way, the ANY privileges are generally regarded as a security problem, so you might like to fail the system if any user is granted them.
If you have privileges granted via roles, you need a more complicated check. The link in comments gives some queries to use to look at the wider picture, but if you want to check what the current user can see - as one of your queries suggests - then you can query the session_roles view to see what object privileges are currently available to your session via roles, in addition to directly-granted object privileges:
select atp.table_schema, atp.table_name, atp.privilege, atp.grantee,
'Direct' as grant_type
from all_tab_privs atp
where atp.grantee = user
union all
select atp.table_schema, atp.table_name, atp.privilege, atp.grantee,
'Via role' as grant_type
from session_roles sr
join all_tab_privs atp on atp.grantee = sr.role;
You can obviously add filters if you want to look at a specific object or privilege, and the grant_type pseudo-column is just for info - not really that useful since you can compare grantee with user to get the same info I suppose.
You might want to look at session_privs as well, to check your user has any system privileges you expect.
But if you want a single query to check the privileges for another user or several users at once, you'll need something more like the linked queries, and the privileges necessary to run them.
I ended up solving this problem using a multi-step approach based around different queries and the results they brought back. I'm executing all the queries with some PHP code so it wasn't 100% necessary that I only have big query to solve it all.
Additionally, our databases are split up physically and they are linked together through database links so I had to do some additional work to make sure that this privilege checking worked across database links.
Currently I'm only checking for SELECT, DELETE, UPDATE, and INSERT privileges; that is all I need really for now.
The procedure
Here is the general procedure in a nut-list.
Get a list of all the database links available to the user.
For the following steps, start with the current database we are logged into and then check each database link retrieved from step 1.
2a. Check to see if the table is visible using a database query.
2b. If the table is visible, check to see if any of the permission queries return that this user has access to the table.
The queries
Here are the queries for each of the steps above.
1 Database links
select db_link from all_db_links
2a Table Visibility
select * from all_tables%DB_LINK% where table_name = :table_name and owner = :owner
The %DB_LINK% above is replaced by #db_link where applicable. If we are checking the current connection then I remove it entirely. Remember, the queries are being executed by a PHP script so I can do some string manipulation on the string to either remove the %DB_LINK% for the current database or replace it with one of the database links we got from step 1.
2b. Users, Roles, Tables
There are 4 queries all together here.
/*****/
/* 1 */
/*****/
select *
from user_tab_privs%DB_LINK%
where
owner = :owner
and
table_name = :table_name
and
privilege = :privilege
/*****/
/* 2 */
/*****/
select * from user_sys_privs%DB_LINK% where privilege = :privilege
/*****/
/* 3 */
/*****/
select * from
(
select distinct granted_role from
(
select null linker, granted_role
from user_role_privs%DB_LINK%
union all
select role linker, granted_role
from role_role_privs%DB_LINK%
)
start with linker is null
connect by prior granted_role = linker
) user_roles join role_tab_privs%DB_LINK% rtab on user_roles.granted_role = rtab.role
where
owner = :owner
and
table_name = :table_name
and
rtab.privilege = :privilege
/*****/
/* 4 */
/*****/
select * from
(
select distinct granted_role from
(
select null linker, granted_role
from user_role_privs%DB_LINK%
union all
select role linker, granted_role
from role_role_privs%DB_LINK%
)
start with linker is null
connect by prior granted_role = linker
) user_roles join role_sys_privs%DB_LINK% rtab on user_roles.granted_role = rtab.role
where rtab.privilege = :privilege
Explanations
Database links
In the phpunit tests I pass in two things : table name and schema name ( owner ). However, because of the database links we have to explicitly check the other databases by using the #db_link in the queries. Otherwise I might report a table as being inaccessible when in reality it is accessible via the database link.
Table visibility
If the user can't see the table then there is no point in checking for privileges. Checking for privileges also prevents the case where a user has been given 'SELECT ANY TABLE' privileges but the table itself doesn't actually exist from causing an unwanted failure.
The band of 4 queries
As shown by other posters, a user can be given access to a table in many ways. Specifically, they can be given roles, and those roles can be given roles, and then those roles can be assigned access. Or the user can be given explicit access or generic access through system privileges.
Query 1
The first of the four queries checks to see if the user has been given explicit SELECT, DELETE, etc, privileges on the table. It's easy to understand and would ideally be all that's necessary
Query 2
The second checks to see if the user has been granted any system privileges like DELETE ANY TABLE, SELECT ANY TABLE, INSERT ANY TABLE, etc. These are not granted explicitly on a table but the user can perform any of the referenced actions on any table they have visibility.
Query 3
The third query will see if any of the roles that user has, either directly or indirectly, has been given explicit SELECT, DELETE, etc, privileges on the table. This is similar to query 1 except it's based on the roles given to the user, not the user.
Query 4
The fourth checks to see if any of the roles that user has, either directly or indirectly, has been given any system privileges like DELETE ANY TABLE, SELECT ANY TABLE, INSERT ANY TABLE, etc. This one is similar to query 2.
That's it! I chain these together and use the results returned from each to determine whether a user has the desired privileges or not.
Details worth mentioning
If a user has any privileges across db_link_1 it does NOT mean that they have the same privileges on tables they access across db_link_2. Most should know this but I wanted to make sure I stated it explicitly. For example, select privs on table 1 across db_link_1 does not imply select privs on table 2 across db_link_2.
I check each db_link one at a time. So first I start of with the database I'm connected to directly, no database link required for this. Then, if I can't find the table or don't have the privs on the table I move on to the next database link.
In queries 2 and 4, I use 'SELECT ANY TABLE', 'DELETE ANY TABLE', etc in place of the :privilege variable.
In queries 1 and 3, I use 'SELECT', 'DELETE', 'UPDATE', 'INSERT' in place of the :privilege variable.

how can i display the specific users of a database

How can I display specific usernames of a database on oracle 10g using the sql*plus on console?
I have been looking for a link column on the following tables v$database, all_users, dba_users, v$session.
To query users which are defined in the database, you can use the all_users view. For example, to select all users who start with a or A, use
SELECT *
FROM all_users
WHERE NLS_UPPER(username) LIKE 'A%';
To query current sessions for a particular user, you can use the v$session view. For example, to select all current sessions which are established for a user who starts with a or A, use
SELECT *
FROM v$session
WHERE NLS_UPPER(username) LIKE 'A%';
To link V$SESSION and DBA_USERS, use "Usernanme" column from both the views. It'll return details on user session.
select D.USERNAME, D.USER_ID, V.SID, V.STATUS
from v$session v, dba_users d
where V.USERNAME=D.USERNAME;
If you need details about sessions created for background processes also, then join by "User#" from V$SESSION and "User_ID" from DBA_USERS.
select D.USERNAME, D.USER_ID, V.SID, V.STATUS
from v$session v, dba_users d
where V.USER#=D.USER_ID;
select username from all_users;
or
select username from all_users where ...;
There are 3 different sets of views ALL_, DBA_, and USER_.
ALL_ views display all the information accessible to the current user, i.e. it can looks at all the shcemas the user has permissions to, DBA_ views display infor for the entire database and is intended only for admins. Then USER_ views display info from the schema of the current user.
Sounds like you need ALL_USERS

User access issue in Oracle 11G

In my oracle DB, i have a user named test this user has DML_ROLE in the DB. And, i have provided insert/update/delete/select access to DML_ROLE on a table named hdr_detail.
But, when user test execute an update query on hdr_detail table its getting error message as Returned error: ORA-01031: insufficient privileges. It works fine when i provide the access directly to the user.
I'm confused why this error shows up only when i provide the access through role.
Table structure:
COLUMN NAME DATA TYPE
PERIOD NUMBER
HDR_ID VARCHAR2(50)
Query i use to update:
update test_sch.hdr_detail set period=201108 where hdr_id = 'check';
Statement i use to grant:
grant insert,select,update,delete on test_sch.hdr_detail to dml_role;
select * from dba_role_privs where grantee like 'TEST' returns the following result
GRANTEE GRANTED_ROLE ADMIN_OPTION DEFAULT_ROLE
TEST DML_ROLE NO NO
select * from dba_tab_privs where table_name like 'HDR_DETAIL' returns the following result
GRANTEE OWNER TABLE_NAME GRANTOR PRIVILEGE GRANTABLE HIERARCHY
DML_ROLE TEST_SCH HDR_DETAIL TEST_SCH DELETE NO NO
DML_ROLE TEST_SCH HDR_DETAIL TEST_SCH INSERT NO NO
DML_ROLE TEST_SCH HDR_DETAIL TEST_SCH SELECT NO NO
DML_ROLE TEST_SCH HDR_DETAIL TEST_SCH UPDATE NO NO
Please help me in resolving this issue. Reply in comment if any more information is needed about this issue.
Try setting the role as the users default role:
ALTER USER test DEFAULT ROLE dml_role;
It could be an issue with how you are accessing the databse object HDR_DETAIL.
From Don burleson (http://www.dba-oracle.com/concepts/roles_security.htm):
Oracle roles have some limitations. In particular object privileges are granted through Oracle roles can not be used when writing PL/SQL code. When writing PL/SQL code, you must have direct grants to the objects in the database that your code is accessing.
If your user is issuing the UPDATE through an application or PL/SQL block then it will not use the role-based permissions. If this is the case you will have to grant the permissions directly.
That seems impossible.
Are you sure that your user connect to correct DB, schema, and query the right table?
I'm stunned.
Pls try
select * from test_sch.hdr_detail
wiht test user.

Resources