Managing Multitenant Common and Local Roles

Da mesma forma que temos os local e common users na arquitetura Multitenant, também temos o mesmo conceito para a questão das roles. Neste artigo vamos explorar um pouco sobre sua criação e gerenciamento.

Com a consulta seguinte, listamos todas as common e local roles tanto do container root quanto de seus PDBs:

[oracle@quiasma admin]$ sqlplus / as sysdba
 
SQL*Plus: Release 18.0.0.0.0 - Production on Tue Apr 13 04:16:33 2021
Version 18.13.0.0.0
 
Copyright (c) 1982, 2018, Oracle.  All rights reserved.
 
 
Connected to:
Oracle Database 18c Enterprise Edition Release 18.0.0.0.0 - Production
Version 18.13.0.0.0
 
SQL> col role format a30
SQL> SELECT ROLE, COMMON, CON_ID FROM CDB_ROLES ORDER BY ROLE, CON_ID;
 
ROLE                           COM     CON_ID
------------------------------ --- ----------
ADM_PARALLEL_EXECUTE_TASK      YES          1
ADM_PARALLEL_EXECUTE_TASK      YES          3
APPLICATION_TRACE_VIEWER       YES          1
APPLICATION_TRACE_VIEWER       YES          3
AQ_ADMINISTRATOR_ROLE          YES          1
AQ_ADMINISTRATOR_ROLE          YES          3
 
...
 
XS_NAMESPACE_ADMIN             YES          1
XS_NAMESPACE_ADMIN             YES          3
XS_SESSION_ADMIN               YES          1
XS_SESSION_ADMIN               YES          3
 
172 rows selected.

Listando todas as roles do root container. Lembrando que nele, só podemos criar common roles, pois a local roles só podem ser criadas nos PDBs:

SQL> SELECT ROLE, COMMON FROM DBA_ROLES ORDER BY ROLE;
 
ROLE                           COM
------------------------------ ---
ADM_PARALLEL_EXECUTE_TASK      YES
APPLICATION_TRACE_VIEWER       YES
AQ_ADMINISTRATOR_ROLE          YES
AQ_USER_ROLE                   YES
AUDIT_ADMIN                    YES
AUDIT_VIEWER                   YES
 
...
 
XS_CACHE_ADMIN                 YES
XS_CONNECT                     YES
XS_NAMESPACE_ADMIN             YES
XS_SESSION_ADMIN               YES
 
86 rows selected.

Criando uma common role:

SQL> CREATE ROLE C##ROLE1 CONTAINER=ALL;
 
Role created.

Tentando criar uma Local Role dentro do root container:

SQL> SHOW CON_NAME CON_ID
 
CON_NAME
------------------------------
CDB$ROOT
 
CON_ID
------------------------------
1
SQL> CREATE ROLE AQUINAO CONTAINER=CURRENT;
CREATE ROLE AQUINAO CONTAINER=CURRENT
*
ERROR at line 1:
ORA-65049: Creation of local user or role is not allowed in this container.

Dentro do PDB, listando suas roles:

SQL> ALTER SESSION SET CONTAINER=HIPOFISE1;
 
Session altered.
 
SQL> col role format a30
SQL> SELECT ROLE, COMMON, CON_ID FROM CDB_ROLES ORDER BY 1;
 
ROLE                           COM     CON_ID
------------------------------ --- ----------
ADM_PARALLEL_EXECUTE_TASK      YES          3
APPLICATION_TRACE_VIEWER       YES          3
AQ_ADMINISTRATOR_ROLE          YES          3
 
...
 
XS_CACHE_ADMIN                 YES          3
XS_CONNECT                     YES          3
XS_NAMESPACE_ADMIN             YES          3
XS_SESSION_ADMIN               YES          3
 
87 rows selected.
 
SQL> SELECT ROLE, COMMON FROM DBA_ROLES ORDER BY ROLE;
 
ROLE                           COM
------------------------------ ---
ADM_PARALLEL_EXECUTE_TASK      YES
APPLICATION_TRACE_VIEWER       YES
AQ_ADMINISTRATOR_ROLE          YES
AQ_USER_ROLE                   YES
 
...
 
XS_CACHE_ADMIN                 YES
XS_CONNECT                     YES
XS_NAMESPACE_ADMIN             YES
XS_SESSION_ADMIN               YES
 
87 rows selected.

Criando uma local role dentro do PDB:

SQL> CREATE ROLE LOCALROLE CONTAINER=CURRENT;
 
Role created.
 
SQL> SELECT ROLE FROM DBA_ROLES WHERE COMMON ='NO' ORDER BY ROLE;
 
ROLE
------------------------------
LOCALROLE

Na situação abaixo, vamos conceder a common role para o common user dentro do root container. Este privilégio será aplicado apenas no root:

SQL> ALTER SESSION SET CONTAINER=CDB$ROOT;
 
Session altered.
 
SQL> GRANT C##ROLE1 TO C##BRUNO;
 
Grant succeeded.

Checando através da consulta abaixo que fizemos o grant localmente no root container:

SQL> col grantee format A16
SQL> col granted_role format A16
SQL> SELECT GRANTEE, GRANTED_ROLE, COMMON, CON_ID FROM CDB_ROLE_PRIVS WHERE GRANTEE='C##BRUNO';
 
GRANTEE          GRANTED_ROLE     COM     CON_ID
---------------- ---------------- --- ----------
C##BRUNO         C##ROLE1         NO           1
 
SQL> CONN C##BRUNO/oracle
Connected.
SQL> SHOW USER;
USER is "C##BRUNO"
SQL> SELECT * FROM SESSION_ROLES;
 
ROLE
------------------------------
C##ROLE1

Isso aconteceu pois o parâmetro CONTAINER ficou interpretado como CURRENT. Caso queiramos conceder este mesmo privilégio para todos os PDBs, basta usarmos o exemplo seguinte:

SQL> conn / as sysdba
Connected.
SQL> GRANT C##ROLE1 TO C##BRUNO CONTAINER=ALL;
 
Grant succeeded.
 
SQL> col grantee format A16
SQL> col granted_role format A16
SQL> SELECT GRANTEE, GRANTED_ROLE, COMMON, CON_ID FROM CDB_ROLE_PRIVS WHERE GRANTEE='C##BRUNO';
 
GRANTEE          GRANTED_ROLE     COM     CON_ID
---------------- ---------------- --- ----------
C##BRUNO         C##ROLE1         NO           1
C##BRUNO         C##ROLE1         YES          1
C##BRUNO         C##ROLE1         YES          3
 
SQL> conn C##BRUNO/oracle
Connected.
SQL> SELECT * FROM SESSION_ROLES;
 
ROLE
------------------------------
C##ROLE1

Conectando com o common user em um PDB e checando que a common role foi concedida:

SQL> CONN C##BRUNO/oracle@HIPOFISE1
Connected.
SQL> SELECT * FROM SESSION_ROLES;
 
ROLE
------------------------------
C##ROLE1

Realizando o revoke da common role do common user:

SQL> conn / as sysdba
Connected.
SQL> REVOKE C##ROLE1 FROM C##BRUNO CONTAINER=ALL;
 
Revoke succeeded.

Podemos perceber que apenas o privilégio common foi revogado. O local ainda permanece:

SQL> SELECT GRANTEE, GRANTED_ROLE, COMMON, CON_ID FROM CDB_ROLE_PRIVS WHERE GRANTEE='C##BRUNO';
 
GRANTEE          GRANTED_ROLE     COM     CON_ID
---------------- ---------------- --- ----------
C##BRUNO         C##ROLE1         NO           1

Realizando o local revoke:

SQL> REVOKE C##ROLE1 FROM C##BRUNO;
 
Revoke succeeded.
 
SQL> SELECT GRANTEE, GRANTED_ROLE, COMMON, CON_ID FROM CDB_ROLE_PRIVS WHERE GRANTEE='C##BRUNO';
 
no rows selected

Validando:

SQL> conn C##BRUNO/oracle
Connected.
SQL> SELECT * FROM SESSION_ROLES;
 
no rows selected
 
SQL> conn C##BRUNO/oracle@HIPOFISE1
Connected.
SQL> SELECT * FROM SESSION_ROLES;
 
no rows selected

Agora vamos conceder uma common role para um local user (apenas para aprendizado, pois o ideal é evitarmos essa prática, pois pode trazer muita confusão em um ambiente normal):

SQL> conn system/oracle@HIPOFISE1
Connected.
SQL> GRANT C##ROLE1 TO LOCALUSER;
 
Grant succeeded.
 
SQL> SELECT GRANTEE, GRANTED_ROLE, COMMON, CON_ID FROM CDB_ROLE_PRIVS WHERE GRANTEE='LOCALUSER';
 
GRANTEE          GRANTED_ROLE     COM     CON_ID
---------------- ---------------- --- ----------
LOCALUSER        C##ROLE1         NO           3
 
SQL> CONN LOCALUSER/oracle@HIPOFISE1
Connected.
SQL> SELECT * FROM SESSION_ROLES;
 
ROLE
------------------------------
C##ROLE1

Por último, vamos conceder uma local role para um local user:

SQL> CONNECT SYSTEM/oracle@HIPOFISE1
Connected.
SQL> GRANT LOCALROLE TO LOCALUSER;
 
Grant succeeded.
 
SQL> SELECT GRANTEE, GRANTED_ROLE, COMMON, CON_ID FROM CDB_ROLE_PRIVS WHERE GRANTEE='LOCALUSER';
 
GRANTEE          GRANTED_ROLE     COM     CON_ID
---------------- ---------------- --- ----------
LOCALUSER        C##ROLE1         NO           3
LOCALUSER        LOCALROLE        NO           3
 
SQL> CONNECT LOCALUSER/oracle@HIPOFISE1
Connected.
SQL> SELECT * FROM SESSION_ROLES;
 
ROLE
------------------------------
C##ROLE1
LOCALROLE

Obs: Este procedimento foi criado pelo senhor Ahmed Baraka (www.ahmedbaraka.com) e foi apenas reproduzido por mim em um laboratório pessoal para fins de aprendizado.

Leave a Comment

Your email address will not be published.