Correct way to give users access to additional schemas in Oracle - oracle

I have two users Bob and Alice in Oracle, both created by running the following commands as sysdba from sqlplus:
create user $blah identified by $password;
grant resource, connect, create view to $blah;
I want Bob to have complete access to Alice's schema (that is, all tables), but I'm not sure what grant to run, and whether to run it as sysdba or as Alice.
Happy to hear about any good pointers to reference material as well -- don't seem to be able to get a good answer to this from either the Internet or "Oracle Database 10g The Complete Reference", which is sitting on my desk.

AFAIK you need to do the grants object one at a time.
Typically you'd use a script to do this, something along the lines of:
SELECT 'GRANT ALL ON '||table_name||' TO BOB;'
FROM ALL_TABLES
WHERE OWNER = 'ALICE';
And similar for other db objects.
You could put a package in each schema that you need to issue the grant from which will go through all call each GRANT statement via an EXECUTE IMMEDIATE.
e.g.
PROCEDURE GRANT_TABLES
IS
BEGIN
FOR tab IN (SELECT table_name
FROM all_tables
WHERE owner = this_user) LOOP
EXECUTE IMMEDIATE 'GRANT SELECT, INSERT, UPDATE, DELETE ON '||tab.table_name||' TO other_user';
END LOOP;
END;

There are many things to consider. When you say access, do you want to prefix the tables with the other users name? You can use public synonyms so that you can hide the original owner, if that is an issue. And then grant privs on the synonym.
You also want to plan ahead as best you can. Later, will you want Frank to be able to access Alice's schema as well? You don't want to have to regrant privileges on N number of tables. Using a database role would be a better solution. Grant the select to role "ALICE_TABLES" for example and when another user needs access, just grant them privilege to the role. This helps to organize the grants you make inside the DB.

Another solution if you have different owner:
BEGIN
FOR x IN (SELECT owner||'.'||table_name ownertab
FROM all_tables
WHERE owner IN ('A', 'B', 'C', 'D'))
LOOP
EXECUTE IMMEDIATE 'GRANT SELECT ON '||x.ownertab||' TO other_user';
END LOOP;
END;

Related

Oracle 12c View that shows all running processes

Disclaimer: I do not venture into the realm of database administration often, and usually stick to data analytics. However, I am trying to educate myself and build my DBA skillset on a small sample database I've created. I am NOT trying to edit anything in production.
This is an extension of this question:
How do I show running processes in Oracle DB?
I would like to create a view for my users that shows a read-only copy of all processes running on my database (similar to what you can do in the terminal of a linux operating system).
I do NOT want to give my users the ability to alter or kill processes that do not belong to them, I just want to give them the ability to easily see how busy the database server is at any given time (I.E.-"read-only" access).
I know to run the below command and allow users to access the view, I need to modify the database permissions. Is there a permission I can enable on the user accounts that will allow them to "select * from WHAT_IS_RUNNING_ON_DB", but not alter/kill processes that they don't own?
CREATE VIEW WHAT_IS_RUNNING_ON_DB AS
SELECT
sess.process, sess.status, sess.username, sess.schemaname,
sql.sql_text
FROM v$session sess,
v$sql sql
WHERE sql.sql_id(+) = sess.sql_id
AND sess.type = 'USER'
AND sess.status = 'ACTIVE'
If you only want them to view what is running, simply:
grant select on v$session to USER1;
grant select on v$sql to USER1;
Then create the view in their schemas. Alternatively, if you don't want them querying on these v$ views directly (because you want to hide the other columns or you only want to keep the code for the view all in one place), you can create a user, grant the above to this new user, create the view in that schema, then grant whoever select against the view.
I do NOT want to give my users the ability to alter or kill processes
that do not belong to them
Although you didn't explicitly ask for it, I interpret this as, you may want to grant users the ability to kill processes that they do own.
Asktom has a good article how to do this:
Create the following procedure in that high privileged user's schema:
create or replace procedure kill_session( p_sid in varchar2,
p_serial# in varchar2)
is
cursor_name pls_integer default dbms_sql.open_cursor;
ignore pls_integer;
BEGIN
select count(*) into ignore
from V$session
where username = USER
and sid = p_sid
and serial# = p_serial# ;
if ( ignore = 1 )
then
dbms_sql.parse(cursor_name,
'alter system kill session '''
||p_sid||','||p_serial#||'''',
dbms_sql.native);
ignore := dbms_sql.execute(cursor_name);
else
raise_application_error( -20001,
'You do not own session ''' ||
p_sid || ',' || p_serial# ||
'''' );
end if;
END;
/
The owner of this procedure needs to have
o SELECT on v_$session granted to them by SYS. This grant must be
directly to them, not via a role.
o ALTER SYSTEM granted directly to them -- not via a role.
You would then grant execute on this procedure to anyone you want. It
would allow them to kill any session they own (running under their
username). You would probably want to "grant select on v_$session"
when connected as SYS to these people as well so they can 'see' the
v$session dynamic performance view to get their sid/serial# pairs

Automate the rights

I use the SQL Developer to connect with Oracle.
I try to "automate" the rights, that means that I do not need all the time to type in every GRANT comment for every table and every user. So my idea was to make three tables. One owns the table names which exists in the database, and a tablegroup. One owns all the users and one the rights with rightgroups.
Now I try to automate it, to put it in one grant. Like:
GRANT (Select rights from DB_Rights where rightgroup = 1)
ON (Select tables from DB_Tables where Tablegroup = 1) to (User)
But it didn't work. Where is my mistake? Or isn't this possible? Is there another option to "automate" it?
The solution could be similar to this. You still have to write the right SELECT query but you should get an idea how it works.
BEGIN
FOR aGRANT IN (
Select rights, tables, User_NAME
from DB_Rights
CROSS JOIN DB_Tables
where Tablegroup = 1 AND rightgroup = 1 AND Tablegroup = 1)
LOOP
EXECUTE IMMEDIATE 'GRANT '||aGRANT.rights||' ON '||aGRANT.tables||' TO '||aGRANT.User_NAME;
END LOOP;
END;
In order to verify your command replace EXECUTE IMMEDIATE ... by DBMS_OUTPUT.PUT_LINE(...);
In general consider the usage of ROLES as suggested by tbone. However, there are situations where ROLES are not applicable or end up in "automate grants for ROLES" instead of "automate grants for USERS"

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.

grant update on table in different scheme

I have 3 schema's in my database:
Colldesk - Main account
Local_it - Local account for developments
User - User account
Now I am writing a procedure to grant people access based on their job. Depending on their job, they need select, or select, update, insert and delete privileges on certain tables.
I know that usually you create roles for this, but I can't (DBA's are external, and they don't like roles.......)
When running the procure, I am inserting the new user, and which department they belong to. If the department is IT_SUPPORT for example, they will need to be able to update tables in the account account and the local_it account. My procedure is located in the local_it account.
Now, when I am trying to run a script like:
for x in (select *
from all_objects
where owner in ('COLLDESK','LOCAL_IT')
and object_type in ('TABLE','VIEW')
and object_name not in ('IFM_letter_data','IFM_letter_data_V2')
order by owner asc)
loop
execute immediate 'grant update on ' || x.owner || '.' || x.object_name || ' to ' || v_user;
end loop;
I am getting an error, saying that I have insufficient privileges. Is it possible to grant update privileges on a table in a different schema? I am able to grant select privileges.
Thanks a lot in advance
Look at this: You have a friend that you trust and you gave him a key to your appartment.
Are you OK if your friend will give a copy of your key to his friend?
It might be NO, it might be YES.
When you want to grant permissions to a user you may say that it is OK for that user to share access with the others.
So, in your case:
User with tables should grant you access to her tables, with permissions to share:
grant update on my_table to you with grant option
Then you can manage access to that table.

Oracle 9i: Synonymed Table Does Not Exist?

I've created a package that contains a stored procedure that I plan to invoke from a separate application. The stored procedure will return a sorted list of all the views and tables in the schema. To do that, it performs a simple select on the DBA_TABLES and DBA_VIEWS synonyms, as shown below:
CREATE OR REPLACE
PACKAGE BODY TITAN_ENTITY AS
PROCEDURE GETSCHEMAOBJECTS (RESULTS IN OUT T_CURSOR)
IS
V_CURSOR T_CURSOR;
BEGIN
OPEN V_CURSOR FOR
SELECT 'T' OBJECTTYPE, TABLE_NAME OBJECTNAME
FROM DBA_TABLES
WHERE OWNER = 'SONAR5'
UNION ALL
SELECT 'V' OBJECTTYPE, VIEW_NAME OBJECTNAME
FROM DBA_VIEWS
WHERE OWNER = 'SONAR5'
ORDER BY OBJECTNAME;
RESULTS := V_CURSOR;
END GETSCHEMAOBJECTS;
END TITAN_ENTITY;
I have verified that the synonyms in question exist, and are public:
CREATE PUBLIC SYNONYM "DBA_TABLES" FOR "SYS"."DBA_TABLES"
CREATE PUBLIC SYNONYM "DBA_VIEWS" FOR "SYS"."DBA_VIEWS"
My understanding is that, because they are public, I don't need any further permissions to get to them. If that understanding is incorrect, I wish someone would disabuse me of the notion and point me to more accurate data.
Now here's my problem: I can open a worksheet in Oracle SQL Developer and select from these tables just fine. I get meaningful data just fine (567 rows, as a matter of fact). But when I try to execute the stored procedure, Oracle complains with a compilation error, as shown below:
Error(9,8): PL/SQL: SQL Statement ignored
Error(10,16): PL/SQL: ORA-00942: table or view does not exist
When I double-click on that second error message, SQL Developer takes me to the first FROM clause ("FROM DBA_TABLES").
So I'm fairly stumped. I know SQL Server pretty well, and I'm new to Oracle, so please bear with me. If you could provide some clues, or point me in the right direction, I'd really appreciate it.
Thanks in advance!
Use ALL_TABLES and ALL_VIEWS instead of DBA_TABLES and DBA_VIEWS. ALL_% views should be accessible to all users.
If you select from a table or a view in a stored PL/SQL-procedure or a stored PL/SQL-function you need a direct grant. A grant via a database role isn't enough.
You probably need a direct grant on view dba_tables. (public) synonyms are just (public) synonyms. You need directly granted select rights.
See here: http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:48704116042682#48798240264807
Edit: Sorry, I glossed over the part where you seem to say that you can select from DBA_TABLES directly. Most likely the issue is that your privileges are granted through a role as someone else answered. But it's still worth explaining that your understanding of PUBLIC synonyms is incomplete, and that using ALL_TABLES would be better if it accomplishes what you need.
The synonym being PUBLIC only means that all users can reference the synonym; it does not grant them any access to the object that the synonym refers to.
What you would do to most directly solve this error is grant SELECT privilege on the SYS views to the user(s) that will run this procedure. However, I think that is a very bad idea.
As suggested by Raimonds, consider whether you can get what you need from USER_TABLES or ALL_TABLES instead. What user is calling this procedure, and what access does that user have to SONAR5's tables?
Generally, if your application is interested in a table, presumably it has some privileges on it, in which case is should be listed in ALL_TABLES.

Resources