Trigger Oracle connect database - sql

How I can make a trigger that a user connect to database check if user System is connected in this moment. Is correct? Then error message and user no connect to database.
Thanks guys.

First, I want to point out that it sounds like you're trying to recreate the functionality of the command ALTER SYSTEM ENABLE RESTRICTED SESSION. You might consider just using that instead.
On the topic of your question, there's an easy answer, but it isn't very good.
CREATE OR REPLACE TRIGGER logon_system_maintenance
AFTER LOGON on DATABASE
IS
system_is_connected varchar2(1) := 'N';
BEGIN
select 'Y' into system_is_connected
from v$session
where username = 'SYSTEM' and status = 'ACTIVE';
-- this will not prevent users with ADMINISTER DATABASE TRIGGER privilege from connecting
RAISE_APPLICATION_ERROR (-20001, 'SYSTEM user is performing maintenance, please try again later');
EXCEPTION
WHEN NO_DATA_FOUND THEN
null; -- system not connected, OK
WHEN OTHERS THEN
null; -- probably the user doesn't have permission to view V$SESSION!
-- should they be able to connect, or not?
END;
/
The problem here is that in order to check if SYSTEM is connected, the user connecting has to be able to view the V$SESSION view, which means they need the SELECT_CATALOG_ROLE role. Probably most of your users don't have this role, which means they don't have permission to even check if SYSTEM is connected or not!
In my experience, what most applications do is create a table to hold various system parameters (e.g. MY_PARAM_TABLE), and add a parameter which controls whether users can log in or not (e.g. SYSTEM_MAINTENANCE = 'N'). Then when you log on as SYSTEM, you set that flag to Y, and the trigger checks that table (which all users should be able to access) and denies access until you set it back to N.
Also keep in mind that you can't prevent DBA users from logging in this way.

Related

How to kill own Oracle SQL sessions without DBA privileges?

Is there a way for a user to terminate one's own session/connections, given an Oracle SID, without DBA rights?
Specifically, I can run this in my DB without admin rights:
SELECT SID, "SERIAL#", STATUS, USERNAME
FROM V$SESSION
WHERE
(USERNAME = 'LastF')
AND
(STATUS = 'INACTIVE');
But when I go to kill my orphaned session (from another session to which I still have access),
ALTER SYSTEM KILL SESSION "12, 123"
I get the following:
JDBC ERROR: ORA-01031: insufficient privileges
Note: I am connecting with JDBC through R/Rstudio using the RJDBC package.
Motivation:
It doesn't appear too difficult to kill sessions in Oracle SQL:
https://docs.oracle.com/cd/B28359_01/server.111/b28310/manproc008.htm#ADMIN11192
How can I kill all sessions connecting to my oracle database?
However, for non-DBA users who have orphaned connections (i.e. internet outage, 3rd party client that manages connections errors out, etc), it can be really frustrating to get:
ORA-02391 exceeded simultaneous SESSIONS_PER_USER limit
and have to wait for timeout.
To successfully run an ALTER SYSTEM command, you don't need to be the DBA, but you do need the ALTER SYSTEM privilege to be granted to you (or to the "user" owning the application through which you connect to the database - which may be different from "you" as the "user" of RStudio).
You have a few options:
ask the DBA to kill the session
ask to be granted the ALTER SYSTEM privilege (which is a very poor practice)
have a "supervisor" (however defined - responsible specifically for these situations) be granted the ALTER SYSTEM privilege, who will be in charge of killing such sessions
(perhaps the best option) create a packaged
procedure whose only task is to kill orphaned sessions. Grant ALTER SYSTEM to the package owner, and grant execute privilege on that
package to individual users (as needed). The procedure should be
written to only kill specific kinds of sessions.
You can use the below to cancel whatever is running in the session
DECLARE
l_status v$session.status%TYPE;
BEGIN
dbms_system.set_ev( &sid, &serial, 10237, 1, '');
LOOP
SELECT status INTO l_status FROM v$session
WHERE sid = &sid and serial# = &serial;
EXIT WHEN l_status='INACTIVE';
END LOOP;
dbms_system.set_ev( &sid, &serial, 10237, 0, '');
END;
you will have to create a direct select grant on sys.v_$session
grant select on v_$session to
Where is the schema that owns the above procedure. This has to be a direct grant and not through a role.
Check the link for more details and given by Donald Burleson
we can kill the oracle session with pid ,
if you are unable to identify the operating system process identifier (spid) from the query , you can issue the following query to help identify the correct session:
SELECT s.sid, s.serial#, p.spid
FROM v$process p, v$session s
WHERE p.addr = s.paddr
AND s.username = '<username>';
At the operating system prompt, issue the kill command and supply the operating system process identifier (spid):
kill <spid>

Revoking right for user to DROP table

I am a big fan of PostgreSQL but can't figure out one aspects of it's built in user management.
My problem is that I have set up pgAdmin and will have some non-developers manually update data in some specific tables. For this reason I have created a new user called "admin" and are looking to restrict this users rights.
I have tried to delete all rights for the user with the following query (from another user):
REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA public FROM admin;
REVOKE ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public FROM admin;
REVOKE ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public FROM admin;
The above did lead to the following error when I wrote a simple SELECT statement from the user admin on a table called "crap": ERROR: permission denied for relation crap.
But what I was able to do with the user admin which by now shouldn't have any rights was the following: DROP TABLE crap; which worked!?
I am really surprised by this. This user is not a Postgres superuser. How can I remove this right to drop tables for a specific user?
You're one level off in hierarchy for the permissions.
REVOKE ALL PRIVILEGES FROM SCHEMA public FROM <role_name>;
You were affecting permissions within the table. You must also go one level up to the schema as well to protect create/drop access. You may also want to revoke access at the database level as well to protect the schema.
REVOKE ALL PRIVILEGES FROM DATABASE <database_name> FROM <role_name>;
You could also simply remove the user. Alternatively you could simply disable that user's ability to login.
ALTER ROLE <role_name> SET NOLOGIN;
If these don't work for you, you can go down a somewhat more complicated route and make an event trigger that watches for DROP TABLE events, compares against the role, and either allows it to continue or aborts the transaction.
CREATE OR REPLACE FUNCTION no_admin_drop()
RETURNS event_trigger LANGUAGE plpgsql AS $$
BEGIN
IF CURRENT_USER = 'admin'::regrole THEN
RAISE EXCEPTION 'command is disabled';
END IF;
END;
$$;
CREATE EVENT TRIGGER no_admin_drop ON sql_drop
EXECUTE FUNCTION no_admin_drop();

GRANT EXECUTE for "sp_delete_database_backuphistory" for group of users

I have a group login which has the Server Role "dbcreator". Users of this login has been granted execute on "sp_delete_database_backuphistory" so that they can delete each others databases. The problem now is that it is possible for these users to delete databases created by other logins. Is there a solution for this? Can permissionĀ“s be set, so that these users ONLY can delete databases created with this login?
You can't do this directly, but you can wrap the system sp_delete_database_backuphistory into your own usp_delete_database_backuphistory
that can call sp_delete_database_backuphistory or return immediately depending on a result of the check you want to perform.
I cannot ask you in a comment what do you mean saying 'databases created by other users', first of all only login (not user) can create a database but this information (db creator) you cannot extract from any system metadata, all you can get is the current database owner and this can differ from database creator.
I mean, when you create a database you can explicitly assign other login to own the database, or you can do this later for certain purposes

Oracle running script

I am using Oracle Sql Developer
I have a huge script that creates tables, indexes, primary key constraints and such.
my DB name is: dbo_other
I logged into this dbo_other as sysdba.
If I run my script then tables do not show up on left panel under 'Tables'
However, if I append the script by adding 'dbo_other.' in front of every table name then the tables show up.
This is very tedious and time consuming.
Is there a way to avoid this? why wont they show up in dbo_other without adding dbo_other. in front of every table name?? When I run the query on the upper right corner the drop down has dbo_other selected!!
I can even do a select * from the table created (but dont see it in left sidebar) Furthermore, I can see the table in pl/sql developer.
Why does oracle sql developer want me to create it with dbo_other.??
Also, is there a way to avoid adding it for each table? maybe something can be done on top of the script so it takes effect on everything that follows?
Why are you logging in to your database using the SYSDBA account? This is very powerful, and it will allow you to do terrible damage to your database if you don't know what you're doing. In a development environment there's a limit to the harm you can do but it's best to get into good habits before doing things in Production.
The interesting thing about AS SYSDBA is that it overrides the username part of the login: if your OS user has the privileges, you're in. As SYS. Check it out:
SQL> conn apc
Enter password:
Connected.
SQL> show user
USER is "APC"
SQL> conn apc as sysdba
Enter password:
Connected.
SQL> show user
USER is "SYS"
SQL>
So, when you ran that script you created all those objects in the SYS schema. Which will prove to be a massive pain in the neck. I hope you have an equal and opposite reversion script.
To run the script properly, all you need to do is connect as DBO_OTHER (normal - i.e. without SYSDBA or SYSOPER which is the default after all). Your script will create tables in the current schema.
If you need to create objects in several schemas, you don't need to log out and in again. The schema is distinct from the user and it is possible to switch schema by executing alter session set current schema = WHOEVR;. This is quite a handy trick and I blogged it up some time back. Find out more.
Note that your user will not acquire any additional privileges by changing the current schema: they will only be able to do what they currently can do. So for something like creating objects in multiple schemas the executing user should be a power user, somebody with CREATE ANY privileges such as a DBA (but still not SYSDBA).
I just stumbled upon this little jem which lets you perform actions on a schema/user by default for which you are not logged in as. That is, by default your select statements, etc will operate on this new schema instead of your own.
alter session set current_schema =
Example:
Myself
+ table1
+ table2
SomeoneElse
+ SuperTable1
+ SuperTable2
log in as "Myself"
select * from SuperTable1
Error: ORA-00942: table or view does not exist
alter session set current_schema = SomeoneElse
select * from SuperTable1 <This will work.>
The "Tables" tree on the left-hand panel only includes tables the logged-in user owns in Oracle SQL Developer. If your script creates tables in another user's schema, you need to click the + next to "Other Users", find the appropriate user, and click the + on their tables.
As others have said, you shouldn't use SYSDBA unless you need to, and it sounds very much like your script should be executed as a normal user based on its rough description.

Error when creating assembly in SQL: MSG 33009

I'm attempting to load a dll into MSSQL with:
USE dbname
GO
CREATE ASSEMBLY foo
FROM 'C:\foo\foo.dll'
WITH PERMISSION_SET = UNSAFE
GO
And I'm getting an error that states:
Msg 33009, Level 16, State 2, Line 2
The database owner SID recorded in the master database differs from the database owner
SID recorded in database 'dbname'. You should correct this situation by resetting the
owner of database 'dbname' using the ALTER AUTHORIZATION statement.
MSDN really isn't telling me any more about the error than the error tells itself.
I've looked all over the internet and have come to the conclusion that only thing anyone has ever done to avoid this is to:
use dbname
go
EXEC dbo.sp_changedbowner #loginame = N'sa', #map = false
But is changing the owner really the only way to avoid this error? Why do I have to do this, is there another way? I'd like some more information about this error before I go in and blindly change the owner.
I have had exactly the same problem and only solution for me was to change the owner, then change it back again.
The problem is that users are both per-database and per-server. What's happened is that the per-database user has a username that is the same as a per-server user, however they SIDs don't match, so it thinks it could be a different person.
Something you might want to check: If the user that you are logged in as (and are creating the database as) is also mapped to the "model" database, then that user will be created under the users tab for the new database. This means that there are credentials under the Security tab for the instance AND for the local users for the database. To immediately solve the issue, drop the user from the local database - you can then set them back as the owner (from the instance credentials):
drop user [MyUser];
exec sp_changedbowner [MyUser]
To solve this problem long term, unmap the user from the "model" database (Security/Logins/[MyUser] Properties - User Mapping).