SP的调用者权限

今天整理以前的笔记,发现还有一些用E文写的笔记。在外企混了几年,E文还是这个德行。这里做个留念


        SP的调用者权限


What is invoker's right subprogram? According to Oracle document, the answer is
'use the AUTHID clause, which makes stored procedures and SQL methods execute with the privileges and schema context of the calling user. '

That is to say, we can create a invoker's right standalone procedure named SP (or function or package) in schema A, let it access some objects without schema name, such as table T. In this way, when a caller name B calls SP, the table B.T will be accessed, instead of A.T

In order to understand this mechanism better, I'll demonstrate some examples to make some pitfall clear.

Question 1: Who is the runner?

When a definer's right subprogram is running, the owner of it is the runner. What about invoker's right one? We can check this information from the USER_USERS view, which describes the current user. Caution: it's not always the same as built-in function USER which shows the session user.

In a nutshell, when a invoker's right subprogram is called directly, the current user is the session user. Let's jump into the case 1 and 2 below.
-----------------------------------------------------------------------------------------
----- Case 1:
-- user a
drop user auth_a cascade;
create user auth_a identified by test;
grant connect,resource to auth_a;

create or replace procedure auth_a.invoker_sp authid current_user is
l_su varchar2(30);
l_cu varchar2(30);
begin
  select user, username into l_su,l_cu from user_users;
  dbms_output.put_line(' SessionUser='||l_su||' CurrentUser='||l_cu);
end;
/

create or replace procedure auth_a.definer_sp authid definer is
l_su varchar2(30);
l_cu varchar2(30);
begin
  select user, username into l_su,l_cu from user_users;
  dbms_output.put_line(' SessionUser='||l_su||' CurrentUser='||l_cu);
end;
/

-- user b
drop user auth_b cascade;
create user auth_b identified by test;
grant connect,resource to auth_b;
grant execute on auth_a.invoker_sp to auth_b;
grant execute on auth_a.definer_sp to auth_b;

SQL> conn auth_b/****@data97
Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0
Connected as auth_b
 
SQL> set serveroutput on
SQL> exec auth_a.invoker_sp
 
 SessionUser=AUTH_B CurrentUser=AUTH_B (within the invoker's right sp,the current user is the session user B, although the owner is A)
 
PL/SQL procedure successfully completed
 
SQL> exec auth_a.definer_sp
 
 SessionUser=AUTH_B CurrentUser=AUTH_A (within definer's right sp, the current user is always the owner of subprogram)
 
PL/SQL procedure successfully completed
 
-----------------------------------------------------------------------------------------
Okay, case 1 shows the case when a invoker's right subprogram is directly. And now we'd like to see what happens when it is call indirectly.

Here we add an extra user T2 who calls invoker's right subprogram in schema A thru another user B.  From experiment result, we know that the current user will be the runner of it's direct caller.

---- Case 2:
-- user b
drop user auth_b cascade;
create user auth_b identified by test;
grant connect,resource to auth_b;
grant execute on auth_a.invoker_sp to auth_b;
grant execute on auth_a.definer_sp to auth_b;

create or replace procedure auth_b.invoker_caller authid current_user is
l_su varchar2(30);
l_cu varchar2(30);
begin
  dbms_output.put_line('invoker call invoker');
  auth_a.invoker_sp();
  dbms_output.put_line('invoker call definer');
  auth_a.definer_sp();
end;
/

create or replace procedure auth_b.definer_caller authid definer is
l_su varchar2(30);
l_cu varchar2(30);
begin
  dbms_output.put_line('definer call invoker');
  auth_a.invoker_sp();
  dbms_output.put_line('definer call definer'); 
  auth_a.definer_sp();
end;
/

SQL> conn T2/****@data97
Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0
Connected as T2
 
SQL> set serveroutput on
SQL> exec auth_b.invoker_caller
 
invoker call invoker
 SessionUser=T2 CurrentUser=T2 (call path: T2 --> B.invoker's --> A.invoker's, and CU=SU=T2)
invoker call definer
 SessionUser=T2 CurrentUser=AUTH_A
 
PL/SQL procedure successfully completed
 
SQL> exec auth_b.definer_caller
 
definer call invoker
 SessionUser=T2 CurrentUser=AUTH_B (call path: T2 --> B.definer's --> A.invoker's, and CU=definer's Owner=B)
definer call definer
 SessionUser=T2 CurrentUser=AUTH_A
 
PL/SQL procedure successfully completed


Question 2: Can I use role in procedure?

As we all know, role is disabled in common subprogram (definer's right). But when we talk about invoker's right subprogram, there's a different story. The privilege checking is postponed till run time, and the role is enabled at this moment. Let me get it straight, if a caller does have some certain privilege NOT thru the explicit grant statement, BUT just thru a role, he still can use this privilege when calling an invoker's right subprogram.
这里说的disabled并不是role本身不可用,而是通过role获得的privilege不可用。可以理解问,在privilege checking的过程中,通过role获得的privilege被disabled。
-----------------------------------------------------------------------------------------
First of all, let's see what happens if B calls invoker's right subprogram when being without a role or explicit privilege.

---- Case 3:
drop table auth_a.t;
create table auth_a.t (x int);
create or replace procedure auth_a.invoker_role authid current_user is
begin
  insert into auth_a.t(x) values(1);
  rollback;
end;
/

grant execute on auth_a.invoker_role to auth_b;

-- B has no privilige to access A.t
SQL> conn auth_b/****@data97
Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0
Connected as auth_b
 
SQL> exec auth_a.invoker_role
 
begin auth_a.invoker_role; end;
 
ORA-01031: insufficient privileges
ORA-06512: at "AUTH_A.INVOKER_ROLE", line 3
ORA-06512: at line 2

(B has no privilige to access A.t, even thought he can access invoker's right procedure residents in schema A)

-----------------------------------------------------------------------------------------
Now, we create a role, give it the necessary priviliege and grant it to user B. What'll happen then?

---- Case 4:
-- 
drop role auth_role;
create role auth_role;
grant all on auth_a.t to auth_role;

grant auth_role to auth_b;


SQL> conn auth_b/****@data97
Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0
Connected as auth_b
 
SQL> exec auth_a.invoker_role
 
PL/SQL procedure successfully completed
(with role,  B can do it. The role is enabled)


-----------------------------------------------------------------------------------------
The case 4 show the directly calling, and now we try some indiretly calls. We grant role to both user T2 and B, and use T2 to indirectly call A.invoker_role thru B.invoker and B.definer.

---- Case 5:
create or replace procedure auth_b.invoker_call_role authid current_user is
l_su varchar2(30);
l_cu varchar2(30);
begin
  auth_a.invoker_role();
end;
/

create or replace procedure auth_b.definer_call_role authid definer is
l_su varchar2(30);
l_cu varchar2(30);
begin
  auth_a.invoker_role();
end;
/

----------------------------------------
SQL> -- T2 has role to access A.t
SQL> exec auth_a.invoker_role (call path: T2 --> A.invoker's, success)
 
PL/SQL procedure successfully completed

----------------------------------------
SQL> -- T2 and B both have role
SQL> exec auth_b.invoker_call_role (call path: T2 --> B.invoker's --> A.invoker's, success)
 
PL/SQL procedure successfully completed
 
----------------------------------------
SQL> exec auth_b.definer_call_role (call path: T2 --> B.definer's --> A.invoker's, fail)
 
begin auth_b.definer_call_role; end;
 
ORA-01031: insufficient privileges
ORA-06512: at "AUTH_A.INVOKER_ROLE", line 3
ORA-06512: at "AUTH_B.DEFINER_CALL_ROLE", line 5
ORA-06512: at line 2

---------------------------------------
SQL> revoke auth_role from auth_b;
Revoke succeeded
 
SQL> -- only T2 has role
SQL> exec auth_b.invoker_call_role (call path: T2 --> B.invoker's --> A.invoker's, success)

PL/SQL procedure successfully completed

(from above result, we can see that in a sequence of procedure calling, whenever a definer's right subprogram is called, the role is disabled from this point.)

-----------------------------------------------------------------------------------------

Below Case 5 shows that role is enabled in invoker's right subprogram, and now let's dig it deeper to see which roles are there.

-- Case 6:
create or replace procedure auth_a.invoker_check_role authid current_user is
begin
  for x in (select granted_role from user_role_privs order by granted_role) loop
    dbms_output.put_line(x.granted_role);
  end loop;
end;
/

grant execute on auth_a.invoker_check_role to auth_b;

create or replace procedure auth_b.invoker_call_check_role authid current_user is
l_su varchar2(30);
l_cu varchar2(30);
begin
  auth_a.invoker_check_role();
end;
/

create or replace procedure auth_b.definer_call_check_role authid definer is
l_su varchar2(30);
l_cu varchar2(30);
begin
  auth_a.invoker_check_role();
end;
/

SQL> conn T2/****@data97
Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0
Connected as T2
 
SQL> set serveroutput on

SQL> exec auth_b.invoker_call_check_role (call path: T2 --> B.invoker's --> A.invoker's, current user has all roles from T2. All roles of T2 are enabled in B.involer and A.invoker)
 
AUTH_ROLE
CONNECT
DBA
JAVAUSERPRIV
RESOURCE
 
PL/SQL procedure successfully completed
 
SQL> exec auth_b.definer_call_check_role (call path: T2 --> B.definer's --> A.invoker's, current user only has roles from B. It means roles of T2 are disabled when T2 called B.definer, and only roles form B can be used in A.invoker)
 
CONNECT
RESOURCE
 
PL/SQL procedure successfully completed

原文地址:https://www.cnblogs.com/wait4friend/p/2334568.html