Oracle dbms_job with invalid owner - oracle

Ok, database at a clients site that has dbms_job entries where the schema_user is invalid. (It appears to be the effect of bringing over a schema from another machine using exp/imp.)
I would like to get rid of these jobs, but standard operating procedure says that you must connect as the owner of the jobs to dbms_job.remove() it.
I thought a workaround might be, to create the user in this instance, and then use it to remove the job.
Thoughts?
Edit:
Or even alternatively making direct edits to the sys.job$ table instead of going through the dbms_job interface?

There's a package owned by SYS called DBMS_IJOB. This offers pretty much the same functionality as DBMS_JOB but it allows us to manipulate jobs owned by other users.
If your rogue job is number 23 then this command should kill it:
SQL> exec dbms_ijob.remove(23)
By default privileges on this package are not granted to other users, so you need to connect as SYS in order to execute it. And remember to commit the change!

Related

temporarily disabling access to a schema in Oracle : lock account vs revoke grant

I have a usecase where I need to block access to all objects in a schema temporarily while I perform some massive changes. I plan to perform the changes as the schema owner. Once I am done I want to enable access back. I am currently exploring two options and would like to know your thoughts as to which one works better :
Lock all accounts that go against the database objects in target schema.
Revoke grants on the database objects and hence preventing external users from using it.
Is there are better way? I want the process to be as smooth as possible and insure that no one is able to get to the target schema while the change is going on
Trigger. This trigger works for everybody except the user with dba role.
CREATE OR REPLACE TRIGGER logon_audit_trigger
AFTER LOGON
ON DATABASE
DECLARE
BEGIN
raise_application_error (-20001, 'You cannot login.');
END;
If you want to know who and where is trying to login. You can get thses information from SYS_CONTEXT.
SELECT SYS_CONTEXT ('USERENV', 'SESSION_USER')
FROM DUAL;
You could consider to quiesce the database. The downsides to locking out users or revoking permissions is that users will receive errors (you don't have access or you can't login, etc...). Quiesceing the database means that active sessions will finish their work, but then will hang until the database is un-quiesced. Then, you perform your modifications and will be guaranteed that nothing can block your exclusive access to the objects you are updating. After your update (or even during your update after you have the lock on the object in question), unquiesce the database.
Of course, the downside to this approach is that this is across the entire database instead of to just one schema. The advantage to this is that your users won't experience any error messages, and if you turn your DML into DDL (as described below) to greatly speed up the downtime window, the majority of your users shouldn't experience much more than a few seconds of inactivity.
There is a good write up on quiesceing the database at Oracle FAQ. You would have to get your DBA's involved to both quiesce the database and to put your changes live as only system or sys can perform this operation.
For DML, you could consider creating a new table with the data that you want before the downtime window starts. Then when the downtime window starts, rename the old table, rename the new table as the old table, recreate the permissions, for a much faster downtime window (since this effectively turns a DML update into DDL). Tom Kyte has a discussion of this approach here.
Also, it goes without saying that proper testing in a testing environment of the above procedures should be done, which will iron out any gotchas in this process and give you a pretty good idea of how long the system will need to be quiesced for.

Why doesn't PL/SQL respect privileges granted by Roles?

When executing a PL/SQL block, any privileges granted to roles are ignored. Instead you must give specific users specific grants to run it. If I want to give DBAs access to a package or a function or a procedure, I can't give the DBA role a grant. I have to give a grant to each user in the DBA role, I have to remove the user's grant if they cease to be a DBA, and I have to add the grant to any new DBA.
I find this very hard to maintain.
My question is why does PL/SQL work this way? What design considerations did Oracle make to decide that this is how Roles and PL/SQL should work together? I've been unable to find an answer that isn't "that's just the way it is".
I think you may be fighting over Invokers rights vs Definers rights.
From Oracle docs:
During a server call, when a DR unit is pushed onto the call stack,
the database stores the currently enabled roles and the current values
of CURRENT_USER and CURRENT_SCHEMA. It then changes both CURRENT_USER
and CURRENT_SCHEMA to the owner of the DR unit, and enables only the
role PUBLIC. (The stored and new roles and values are not necessarily
different.) When the DR unit is popped from the call stack, the
database restores the stored roles and values. In contrast, when an IR
unit is pushed onto, or popped from, the call stack, the values of
CURRENT_USER and CURRENT_SCHEMA, and the currently enabled roles do
not change
So if you want Oracle to "respect the privileges granted by roles", then perhaps you want to use Invokers rights ( AUTHID CURRENT_USER clause)
It's probably a combination of laziness and the SET ROLE command.
I disagree that it's not allowed because of complex dependencies. Oracle already manages complex dependencies. And in 12c it is possible to grant a role to an object.
I think the real reason why objects don't inherit the roles of the user is because of the SET ROLE command. It's possible for a user to be assigned a role but to turn it on and off within a session. That's a silly feature and I've never seen it used. But theoretically it would require recompiling within the same session or transaction, which would be really confusing.
Otherwise if you drop a role then the PL/SQL package would become INVALID in some cases (without having the option to re-compile).
DROP ROLE ... is a DCL (Data Control Language) statement. Looks like Oracle decided: "A PL/SQL package shall not become INVALID by a DCL statement"
Maybe I am not understanding something correctly here, because I have done what you say can't be done. In fact, the Oracle documentation says it can be done. Look at the section on Procedure Security in this document. (#ibre5041)Nothing would have to be recompiled because the procedures run under the owner's privileges. The user's (or his roles') privileges are only checked for whether they are allowed to run the procedure.
What am I missing?
I'm think it is some historical heritage. When changing ROLE's object privs Oracle would have re-compile a lot of PL/SQL stored code. PS: you can also create something called "SCHEMA".
See CREATE SCHEMA statement.

Is it possible to execute a SQL script file stored on the database server using a remote command?

Say I have a SQL script physically stored on the database server. Is there a SQL command I can send Oracle from an application to tell it to execute that script?
(Yes, I know this sounds ridiculous. I'm considering it as part of a work around of a very nasty problem that "shouldn't happen" but does.)
The easiest option would generally be to use the dbms_scheduler package to run an external job. This would let you invoke a shell script that started SQL*Plus, connected to the database, and ran your .sql script.
It would also be possible to create a Java stored procedure that uses Java's ability to call out to the operating system to run the same shell script. That tends to be a bit more of a security issue, though, since you're ending up granting the owner of this procedure privileges to run any command on the database server as the oracle user. That would include things like connecting to the database as SYSDBA or corrupting the database (accidentally or intentionally) so it's something that auditors would generally frown upon.

DBMS_PROFILER - only anonymous

I am trying to get over with DBMS_PROFILER, but I face a problem, that I can't get through.
I followed the tutorial on this page:
http://www.oracleflash.com/44/Write-fast-and-efficient-PLSQL---DBMS_PROFILER.html
and everything was fine till I did not change the user. When I run the profiler as the owner of the code, all the statistics are fine, but when I run those procedures as a different user (that of course has EXECUTE permissions) I can see only "ANONYMOUS" in profiler tables.
I found something looking around in the internet, and performed these actions:
I granted execute permissions for user calling procedures,
I also granted DEBUG permissions,
I compiled procedures for DEBUG,
I have checked that code is "INTERPRETED" and not "NATIVE",
finally, calling user also have CREATE PROCEDURE privilege.
Nevertheless, it still doesn't work. The problem is I want to profile application, that is running code as a different user, so I cannot change that. Any ideas what should I do, and why it is not working?
Problem solved. The doc says (in security section) that you need to have privileges to create objects that you want to monitor. I wanted to monitor package in other schemas, so at first I thought I need CREATE PROCEDURE privilege which didn't help. In fact, you need to have privileges to create specifically object you want to monitor, so you simply need to have CREATE ANY PROCEDURE for user from which you are running other shema packages.
You have tagged this question as Oracle 11g, in which case you are in luck. Oracle added a new profiler package, DBMS_HPROF. This is a hierarchical profiler, which means it can drill down into different schemas. Find out more.

How do I execute a procedure in a package I just created in another schema?

Setup: I have two trees of scripts that run on Oracle 11g - one set ensures the correct instance configuration and that all of the DBA proxy accounts are there to connect to the dbadmin account, and the other set builds and modify our database environments.
Problem: Proxied in to the DBADMIN account, the second set of scripts runs just fine, except for one piece: the data pre-population. The procedures that allow loading of the data create under the appropriate schema just fine, and the script that loads the data runs just fine if ran as SYS AS SYSDBA, but when I try to run it as DBADMIN immediately after creating the procedure it calls I get PLS-00904: insufficient privilege to access object schema.package for every call. I can't even have the script GRANT EXECUTE ON schema.package TO DBADMIN because that (of course) generates the expected ORA-01749: you may not GRANT/REVOKE privileges to/from yourself error.
To put it more simply:
(as DBADMIN:)
...
CREATE OR REPLACE PACKAGE BODY other_schema.package_name IS
...
PROCEDURE add_data(...)
...
(succeeds, and is testably working)
(later, in another script called by the same parent script, still as DBADMIN:)
BEGIN
other_schema.package_name.add_data(...);
...
(raises the PLS-00904 given above - Insufficient privilege)
Any ideas on how I can give the DBADMIN account EXECUTE access to a package that it hasn't created yet, or how DBADMIN can get access itself without stopping the whole script stream, log out and back in as SYS AS SYSDBA to GRANT it? (The whole point here is to have ZERO manual steps beyond the initial "run this script tree", and to only have one time ever up front when the SYS AS SYSDBA is ever used.)
You could grant DBADMIN the EXECUTE ANY PROCEDURE privilege. This will allow it to, er, execute any procedure that is to run programs owned by any other user.
Like the other ANY procedures it is extremely powerful and should not be granted lightly. (In fact it is one of the most powerful ANY privileges there is).

Resources