I'm trying to create an authorization scheme that creates users based on a table in my database named DJELATNIK that has attributes name, surename, korisnicko_ime, lozinka. korisnicko_ime is the username for the employee and lozika it's the employees password. I created a Authentication Scheme with the following Authentication Function:
CREATE OR REPLACE FUNCTION
prijava_custom(p_username IN VARCHAR2, p_password IN VARCHAR2)
RETURN BOOLEAN
AS
v_korisnicko varchar2(100);
v_lozinka varchar2(100);
BEGIN
SELECT KORISNICKO_IME, LOZINKA
INTO v_korisnicko, v_lozinka
FROM DJELATNIK
WHERE UPPER(KORISNICKO_IME) = UPPER(p_username)
AND LOZINKA = p_password;
RETURN TRUE;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN FALSE;
END;
Everything works, all the employees now have an "account" created but i still need to manually assign them a role before they can actually login.
What i want is to set all roles of the accounts generated from this scheme to be a contributor.
And somehow set my account to be administrator.
Is that even possible ?
I understand that i could add a new column in my DJELATNIK table to select role in the form for DJELATNIK but i don't know how to write the code needed to actually make it work.
It is not clear from your question if you are using your own roles or the native "Application Access Control".
If you're using "Application Access Control" then there is an API available to grant a user a specific role.
There are 2 options:
Grant the user the "Contributor role" when the account is created.
Have an after authentication application process that checks if the current user has the Contributor role and if not, then grant the user the role
Update: an alternative solution is to modify the authorisation scheme for contributor so it just checks if the user is logged on.
Related
I try to create user and grant for them some privileges. I try to create without using procedure:
CREATE USER User1 IDENTIFIED BY password;
It works fine.
But for example, i have thousands of users. So I created a procedure to do it:
CREATE OR REPLACE PROCEDURE CreateUser AS
BEGIN
FOR u IN ( SELECT id FROM User )
LOOP
EXECUTE IMMEDIATE 'CREATE USER User_'||d.id || ' IDENTIFIED BY password';
EXECUTE IMMEDIATE 'GRANT SELECT ON UserInfo_'||d.id||' TO User_'||d.id;
END LOOP;
END
But it throws an error:
ORA-01031: insufficient privileges
How can I handle this problem? Thanks for helping in advance
You need to make sure the user running the procedure has the privileges to create users.
Assuming the user that will run the procedure is MyUser, you need to run :
GRANT CREATE USER to MyUser;
if your SQL is directly (i.e not in a procedure ) but not working from a procedure/function it means that you have the Grants through a role. For a statement to work in a procedure or a function we need direct Grants and not through the role.
You can check that you have the Create user by a role by doing the following and trying your SQL, if it fails it means you have access through a role.
SET role none;
CREATE USER User1 IDENTIFIED BY password;
I have created a procedure as shown below. This procedure is present in schema1 and trying to modify the password of another schema/user let's say schema2.
To achieve this the user schema1 must have altered user privilege but I cannot provide the alter user privilege to schema1 due to some restrictions on the application level.
I tried to query using ALTER SESSION in the procedure but it is not working.
Can someone help me with the solution?
code:
Procedure p_demo(p_schema in varchar, p_pswd in varchar2)
is
begin
execute immediate 'alter session set current_schema ='||p_schema;
execute immediate 'alter user '||p_schema||' identified by '||p_pswd;
end;
Changing the current_schema has no impact on permissions or what user is currently logged in. It merely changes how object name resolution works. If you query an object foo when current_schema is set to schema1, Oracle looks in the schema1 schema rather than in the current user's schema. It does nothing to give you access to the schema1.foo table.
I'm not quite sure that I understand the goal. If you are trying to ensure that only the schema2 user can change the schema2 user's password, you can define the procedure to use invoker's rights rather than definer's rights.
create or replace procedure change_my_password( p_username in varchar2,
p_password in varchar2 )
authid current_user
is
begin
execute immediate 'alter user '||p_username||' identified by '||p_password;
end;
/
If the goal is to have the procedure owned by schema1 and to give users other than the schema2 user permission to change schema2's password (i.e. to allow an application user or a helpdesk user to reset the user's password), schema1 would likely need to have the alter user permission. Otherwise, it's probably not doable.
If you're really desperate, you could potentially use the undocumented (and I emphasize undocumented here, subject to change at any time, may have weird side effects, may tend to make Oracle Support unhappy) dbms_sys_sql package. That's the package that APEX uses internally to run code as other users. I don't imagine that a sane DBA would consider giving an application user execute access on that package rather than the much (much, much) safer alter user permission but if you're trying to work around some corporate policy and you're not much concerned about actual security...
There are 3 users involved in this example:
scott, who is trying to change someone else's password (that's your schema1)
mike, whose password should be changed (your schema2)
mydba, who is granted DBA role in my database (if you don't have such an user, SYS would do, but - you'd rather have your own "DBA" user, don't mess up with SYS if you don't have to)
Connected as scott, I can't modify mike's password:
SQL> alter user mike identified by lion;
alter user mike identified by lion
*
ERROR at line 1:
ORA-01031: insufficient privileges
I'm going to connect as mydba and create a stored procedure which looks like yours:
SQL> connect mydba/mypwd#c11gt
Connected.
SQL> create or replace procedure p_demo (p_schema in varchar2, p_pswd in varchar2) is
2 begin
3 execute immediate 'alter user ' || p_schema || ' identified by ' || p_pswd;
4 end;
5 /
Procedure created.
SQL> exec p_demo('mike', 'lion');
PL/SQL procedure successfully completed.
OK; it works. I'll grant execute privilege on it to scott:
SQL> grant execute on p_demo to scott;
Grant succeeded.
Back to scott; see what he can do now:
SQL> connect scott/tiger#c11gt
Connected.
SQL> exec mydba.p_demo('mike', 'friday');
PL/SQL procedure successfully completed.
Do mike's credentials work?
SQL> connect mike/friday#c11gt
Connected.
SQL>
Yes, everything's fine.
So: you don't have to grant alter user to schema1; let it use procedure owned by a privileged user who can change someone else's password.
Cant we do as shown below: Tried doing this but it didn't work.
What i am trying to do is basically give alter user privileges to one role and assign that role to my oracle procedure.
Create role role_name;
GRANT ALTER USER TO role_name
grant all on role_name to procedure
I would like to know how I can create a role to a procedure in oracle. This procedure should (not globally) allow the user to Change the roles and delete them.
create or replace PROCEDUR MY_ROLE(Name VARCHAR2) IS
BEGIN
DBMS_Output.put_line('You've got the right ' || Name );
--EXECUTE IMMEDIATE CONCAT('grant some_role to Username' , Name);
INSERT INTO FG7.ROLE values(Name);
END MY_ROLE;
THanks!
I think the proper approach is to create a role, grant the role to user and then SET the ROLE:
EXECUTE IMMEDIATE 'SET ROLE '||some_role;
Use
EXECUTE IMMEDIATE 'SET ROLE NONE';
to unset the role again. Of course when you grant the role to user it must not set as DEFAULT ROLE.
The issue with GRANT some_role TO ... is, it takes effect only after the user have been logged in again.
You can also use DBMS_SESSION.SET_ROLE('some_role'); and DBMS_SESSION.IS_ROLE_ENABLED('some_role') to check whether a role is enabled. See DBMS_SESSION.SET_ROLE
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
I am sorry for a newbie question. I am creating a readonly user in oracle. I want to limit him just to view and execute a function or procedure. I dont want him to modify those func or proc. Please help me on how to achieve this.
Thanks a lot
-- As sysdba:
-- 1) create an user account
create user <username> identified by <password>;
-- 2) allow user to log in
grant create session to <username>;
-- 3) allow user to execute a single procedure in other schema
grant execute on <other_schema.procedure_name> to <username>;
From SYSDBA user login (from where you created the user), give the following grant :
GRANT EXECUTE ANY PROCEDURE TO user;
GRANT SELECT ANY TABLE TO user;
where user = the username you just created.
Then ,to ensure the user has only read priviledges, check from session_privs that he doesnot have any other priviledge, specifically any "CREATE" prviledge. To do this , run :
select * from session_privs;
from the user you just created.