Oracle 12c Multitenant: Common User? Local User? – Die totale Verwirrung?

7. April 2014 Aus Von Markus Flechtner

Oracle Database 12c bietet mit der Multitenant Option die Möglichkeit, in einer Container Database (kurz: CDB) 2 – 252 Pluggable Databases (kurz: PDB) zu verwalten. Dies hat einige Implikationen, z.B. auch bei der Verwaltung der User und Rollen. Es gibt nämlich common User (Rollen) und local user (Rollen).

Was sind Common User?

“Common User” sind User, die im root-Container (CDB$ROOT) angelegt werden, und die dann in allen bereits vorhandenen und allen zukünftigen PDBs verfügbar sind. Für diese User gilt:

1. Sie müssen mit dem Prefix “C##” angelegt werden. Ansonsten kommt die Fehlermeldung “ORA-65096: invalid common user or role name”.

2. Das Password ist im root-Container und in allen PDBs gleich. Und wenn man das Password in einer PDB ändern will, kommt der Fehler “ORA-65066: The specified changes must apply to all containers”.

3. Wenn ein Common User gesperrt wird, dann ist er für alle PDBs gesperrt.

4. Die Oracle-Standard-User sind “Common-User” auch wenn sie nicht das Prefix “C##” haben:

SQL> select distinct username from cdb_users where common='YES' and username not like 'C##%' order by username

USERNAME
——————————————————————————–
ANONYMOUS
APEX_040200
APEX_PUBLIC_USER
APPQOSSYS
AUDSYS
CTXSYS
DBSNMP
DIP
DVF
DVSYS
FLOWS_FILES
GSMADMIN_INTERNAL
GSMCATUSER
GSMUSER
LBACSYS
MDDATA
MDSYS
OJVMSYS
OLAPSYS
ORACLE_OCM
ORDDATA
ORDPLUGINS
ORDSYS
OUTLN
SI_INFORMTN_SCHEMA
SPATIAL_CSW_ADMIN_USR
SPATIAL_WFS_ADMIN_USR
SYS
SYSBACKUP
SYSDG
SYSKM
SYSTEM
WMSYS
XDB
XS$NULL

35 rows selected.

Wie wird ein neuer Common User angelegt?

SQL> show con_name

CON_NAME
——————————
CDB$ROOT

SQL> create user C##demo identified by demo container=all;

User created.

SQL> grant resource to c##demo;

Grant succeeded.

SQL> grant dba to c##demo container=all;

Grant succeeded.

SQL> column grantee format a10
SQL> column granted_role format a10
SQL> select * from cdb_role_privs where grantee=’C##DEMO’;

GRANTEE GRANTED_RO ADM DEF COMMON CON_ID
———- ———- — — —— ——
C##DEMO RESOURCE NO YES NO 1
C##DEMO DBA NO YES YES 1
C##DEMO DBA NO YES YES 4
C##DEMO DBA NO YES YES 3

==>
Der erste GRANT hat die Rechte nur für den aktuellen Container (=CDB$ROOT) vergeben, der zweite für alle PDBs (aktuell vorhandene und zukünftig erstellte PDBs).

Die Rechte findet man dann auch auf der PDB-Ebene wieder:

SQL> alter session set container=crm02;

SQL> select * from dba_role_privs where grantee=’C##DEMO’;

GRANTEE GRANTED_RO ADM DEF COMMON
———- ———- — — ——
C##DEMO DBA NO YES YES

Aber Achtung:

SQL> revoke dba from C##demo CONTAINER=CURRENT;

Ergibt:

ERROR at line 1:
ORA-01951: ROLE ‘DBA’ not granted to ‘C##DEMO’

Das ist im ersten Moment verwunderlich, denn wenn man sich als C##DEMO z.B. mit der PDB3 verbindet ergibt eine Abfrage auf SESSION_ROLES, dass der User C##DEMO die Rolle DBA hat.

Warum??

Lösung: Die DBA-Rolle wurde “global” (CONTAINER=ALL) ge-granted, d.h. sie kann auch nur global wieder entfernt werden. Innerhalb einer PDB können nur locally-granted Rechte (Rollen, Privilegien) entzogen werden. Zum Entziehen des DBA-Rechtes muss man sich also wieder mit dem root-Container verbinden:
SQL> connect / as sysdba
Connected.
SQL> revoke dba from C##demo container=all;

Revoke succeeded.
Interessant (und ein bisschen verwirrend) wird es, wenn man die Rechte “doppelt” vergibt:

SQL> grant dba to c##demo container=all;

Grant succeeded.

SQL> alter session set container=crm02;

Session altered.

SQL> grant dba to c##demo container=current;

Grant succeeded.

Das DBA-Recht taucht dann doppelt in der DBA_ROLE_PRIVS-View auf:

SQL> column grantee format a10
SQL> column granted_role format a15
SQL> select * from dba_role_privs where grantee=’C##DEMO’;

GRANTEE GRANTED_ROLE ADM DEF COM
———- ————— — — —
C##DEMO DBA NO YES NO
C##DEMO DBA NO YES YES
Ein Recht kann also doppelt (nämlich “COMMON” und “LOCAL” vergeben werden) – und muss dann auch zweimal entzogen werden.

Auf Ebene einer einzelnen PDB (“local”) kann ein Common-User also durchaus mehr Rechte haben als global (“common”).
Umgekehrt allerdings nicht, sprich: man kann kein GLOBAL vergebenes Recht LOKAL entziehen.

SYSDBA-Rechte auf PDB-Ebene
Auf Ebene einer PDB kann auch das SYSDBA-Recht vergeben werden (für common User und für lokale User):

SQL> alter session set container=crm02;

Session altered.

SQL> grant sysdba to c##demo;

Grant succeeded.

SQL> alter session set container=CDB$ROOT;

Session altered.

SQL> select * from v$pwfile_users;

USERNAME SYSDB SYSOP SYSAS SYSBA SYSDG SYSKM CON_ID
—————————— —– —– —– —– —– —– ———-
SYS TRUE TRUE FALSE FALSE FALSE FALSE 0
SYSDG FALSE FALSE FALSE FALSE TRUE FALSE 1
SYSBACKUP FALSE FALSE FALSE TRUE FALSE FALSE 1
SYSKM FALSE FALSE FALSE FALSE FALSE TRUE 1
C##DEMO TRUE FALSE FALSE FALSE FALSE FALSE 4

SQL> connect c##demo/demo@crm02.markusdba.locals sysdba
Connected.

Aber:

SQL> connect c##demo/demo@crm01.markusdba.local as sysdba
ERROR:
ORA-01017: invalid username/password; logon denied

Warning: You are no longer connected to ORACLE.

Eine weitere Komplexitätsebene kommt hinzu, wenn man für Common User im Root-Container die Rechte auf die sog. “Container Data Objects” einschränkt,
so dass die User nicht die Daten aller Container sehen können (siehe auch meinen
Blog-Eintrag).

Sinngemäß gilt das gleiche, was hier für “common user” gezeigt wurde, auch für “common roles”.

Was sind lokale User?

Ganz einfach: “local user” sind User, die es nur in einer PDB gibt, bzw. (genauer) die innerhalb einer PDB angelegt wurden:

SQL> alter session set container=crm02;

Session altered.

SQL> create user localuser identified by localuser container=current;

User created.

Das Prefix “C##” ist für lokale User nicht erlaubt:

SQL> create user c##local identified by gehtnicht;
create user c##local identified by gehtnicht
*
ERROR at line 1:
ORA-65094: invalid local user or role name

Lokale User können dann aber common roles zugewiesen bekommen:

SQL> grant c##role to localuser;

Grant succeeded.

Im ersten Moment ist das alles irgendwie ziemlich kompliziert .. 🙂

Zusammengefasst:
Die Verwaltung einer Multitenant-Datenbank-Infrastruktur kann deutlich komplexer sein, als die Verwaltung einer “klassischen” Oracle-Architektur.
Gute Rechte-Konzepte (Rollen und User) sind wichtig, bevor man die neue CDB/PDB-Architektur implementiert. Ansonsten landet man als Administrator schnell bei Murphys 7.Gesetz der Computerprogrammierung: “Die Komplexität eines Programms wächst so lange, bis sie die Fähigkeit des Programmierers übertrifft, der es weiterführen muss.”

Weitere Informationen:

Oracle 12c Concepts: Kapitel 18: Overview of the multitenant architecture”