Oracle 12c View that shows all running processes - oracle

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

Related

Oracle kill inactive sessions stored procedure

I would like to write kill_inactive sessions stored procedure for Oracle.
something like
create or replace procedure kill_inactive_sessions as
begin
for rec in (select sid, serial# from sys.v_$session where status = 'INACTIVE')
loop
execute immediate 'alter system kill session '''|| rec.sid || ',' || rec.serial# || ''' IMMEDIATE';
end loop;
end kill_inactive_sessions;
Previous doesn't work (table or view does not exists).
But next select is working perfectly for the same user:
select sid, serial# from sys.v_$session where status = 'INACTIVE';
What I'm missing?
The ORA-00942: table or view does not exist error almost certainly indicates that your access to the v$session view is via a role rather than a direct grant.
If you want to write a definer's rights stored procedure, the owner of the procedure must have the necessary privileges granted directly to the user, not via a role (and remember that DBA is just another role). Most likely, if you disabled roles in your session, the SELECT statement outside of the procedure would not work. In SQL*Plus, for example
SQL> set role none;
SQL> select sid, serial# from sys.v_$session where status = 'INACTIVE';
will likely throw the same ORA-00942 error. Assuming it does, you need to grant the user that owns the stored procedure privileges directly. For example
GRANT SELECT ANY DICTIONARY
TO user_that_owns_the_procedure;
The same thing will also apply to the ALTER SYSTEM command that you are building and running. The owner of the stored procedure will need to have privileges to run that command via a direct grant not via a role.
All that said, a procedure that kills all inactive sessions is highly problematic. The vast majority of sessions are going to be inactive the vast majority of the time. That doesn't mean that they should be killed. Even if you're cleaning up after an application server crash, you really ought to be applying some additional predicates (for example, looking for sessions from a particular machine that are logged in as a particular user that were established before the application server crashed). Long-term, though, I'd suggest enabling dead connection detection so that the database can automatically take care of closing sessions when the client process dies unexpectedly.

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.

In oracle, can I associate a default Schema with my USER ID where SCHEMA <> USERID?

I would like to connect to an Oracle database with UserId "MY_SCHEMA" and then be able to perform queries where the table name was not qualified with the schema name:
SELECT * FROM TABLE1
When executing SQL, I would like my unqualified queries to go against a different schema other than my own. In other words, I would like this to be equivalent to
SELECT * FROM SCHEMA_OTHER.TABLE1
instead of
SELECT * FROM MY_SCHEMA.TABLE1
I know it seems a little weird and so I expect that this is not possible.
I do not have any sort of admin rights to the database to see if I can associate a default schema with a login.
After you login, you can run the following:
ALTER SESSION SET CURRENT_SCHEMA=schema_other;
If you really want this to happen automatically, you can create a system trigger for the logon action that looks for your username and uses execute immediate to run the alter session command:
CREATE OR REPLACE TRIGGER my_schema_logon
AFTER LOGON
ON DATABASE
BEGIN
IF SYS_CONTEXT ('USERENV', 'CURRENT_USER') = 'MY_SCHEMA' THEN
EXECUTE IMMEDIATE 'ALTER SESSION SET CURRENT_SCHEMA=schema_other';
END IF;
END my_schema_logon;
/

Can GRANT be used inside an Oracle Store Procedure?

When trying to place a GRANT statement in an Oracle 11 stored procedure, it reports that GRANT is an unexpected symbol. Does GRANT need to be prefaced by something, or does Oracle simply disallow running GRANTS inside SPs?
It's a bad idea to use DDL (like GRANT) inside stored procedures.
You will have to use dynamic SQL (EXECUTE IMMEDIATE) to do this, but, honestly, I don't see why would you want to do this inside a stored proc.
Here's a PL/SQL stored procedure that grants object privileges (SELECT, UPDATE, etc.) on all tables owned by the current user to another user, e.g. - "appuser".
CREATE OR REPLACE PROCEDURE grant_privs
IS
CURSOR ut_cur IS SELECT table_name from user_tables;
ut_rec ut_cur%rowtype;
BEGIN
FOR ut_rec IN ut_cur
LOOP
EXECUTE IMMEDIATE 'GRANT ALL ON ' || ut_rec.table_name || ' TO appuser';
END LOOP;
END;
/
It was executed automatically after deploying database changes for a web application. The current user owns the database tables. After deploying any database changes, the stored procedure was executed to ensure that "appuser" could run SQL statements on all of the tables. The web application connected as "appuser", which had only limited system privileges, for security reasons.
This is both a solution to the problem and a solid use case for the solution.

Correct way to give users access to additional schemas in 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;

Resources