{
  "date": "2016-03-16T10:51:38",
  "slug": "the-privileges-to-connect-to-a-container",
  "link": "https://www.dbi-services.com/blog/the-privileges-to-connect-to-a-container/",
  "title": {
    "rendered": "The privileges to connect to a container"
  },
  "content": {
    "rendered": "<h2>By Franck Pachot</h2>\n<p>.<br />\nIn Multitenant, there are two ways to connect to a pluggable database. This means that if you want to prevent access to a pluggable database you need to revoke two privileges.<br />\n<!--more--></p>\n<h3>Privilege Analysis</h3>\n<p>Rather than trying with different combination of privileges there is a clever way to do it in 12c with privilege analysis (remember it&#8217;s an option).<br />\nThe idea is to grant all privileges:</p>\n<pre><code>\nSQL&gt; create user C##USER1 identified by oracle container=all;\nUser created.\nSQL&gt; grant DBA to C##USER1 container=all;\nGrant succeeded.\n</code></pre>\n<p>and then start privilege capture to know which privileges are actually used:</p>\n<pre><code>\nSQL&gt; exec dbms_privilege_capture.create_capture (name=&gt;'demo',type =&gt;dbms_privilege_capture.g_role,roles=&gt;role_name_list('DBA'));\nPL/SQL procedure successfully completed.\nSQL&gt; exec dbms_privilege_capture.enable_capture (name=&gt;'demo');\nPL/SQL procedure successfully completed.\n</code></pre>\n<p>Note that privilege capture is done per container, so I activate it also in my pluggable database:</p>\n<pre><code>\nSQL&gt; alter session set container=PDB001;\nSession altered.\nSQL&gt; exec dbms_privilege_capture.create_capture (name=&gt;'demo',type =&gt;dbms_privilege_capture.g_role,roles=&gt;role_name_list('DBA'));\nPL/SQL procedure successfully completed.\nSQL&gt; exec dbms_privilege_capture.enable_capture (name=&gt;'demo');\nPL/SQL procedure successfully completed.\n</code></pre>\n<p>At the end of each operation, I will get the result running this from each container:</p>\n<pre><code>\nSQL&gt; exec dbms_privilege_capture.disable_capture(name=&gt;'demo');\nPL/SQL procedure successfully completed.\nSQL&gt; exec dbms_privilege_capture.generate_result(name=&gt;'demo');\nPL/SQL procedure successfully completed.\nSQL&gt; select con_id,username,sys_priv from cdb_used_sysprivs_path;\n</code></pre>\n<h3>CONNECT</h3>\n<p>The first way to connect to a pluggable database is to connect directly to its service:</p>\n<pre><code>\nSQL&gt; connect C##USER1@//localhost/PDB001.pachot.oraclecloud.internal\nConnected.\n</code></pre>\n<p>And, as you expected, the privilege used is the CREATE SESSION in the pluggable database (PDB001 is CON_ID=4) and no privilege at all is needed in CDB$ROOT:</p>\n<pre><code>\n    CON_ID USERNAME   SYS_PRIV\n---------- ---------- ----------------------------------------\n         4 C##USER1   CREATE SESSION\n</code></pre>\n<h3>SET CONTAINER</h3>\n<p>The second way available to common users only is to connect to CDB$ROOT and then switch to the pluggable database container:</p>\n<pre><code>\nSQL&gt; connect C##USER1\nConnected.\nSQL&gt; alter session set container=PDB001;\nSession altered.\n</code></pre>\n<p>Of course, we see the CREATE SESSION when connecting to the CDB$ROOT&gt;</p>\n<pre><code>\n    CON_ID USERNAME   SYS_PRIV\n---------- ---------- ----------------------------------------\n         1 C##USER1   CREATE SESSION\n</code></pre>\n<p>and here is the SET CONTAINER privilege which is used on the pluggable database only.</p>\n<pre><code>\n    CON_ID USERNAME   SYS_PRIV\n---------- ---------- ----------------------------------------\n         4 C##USER1   SET CONTAINER\n</code></pre>\n<h3>Conclusion</h3>\n<p>If you want to prevent access to a pluggable database from a common user, you need to revoke both SET CONTAINER and CREATE SESSION in that container. Same idea if you want to set some session environment through logon trigger, you may also do it in an AFTER SET CONTAINER trigger.<br />\nNow, do you think that revoking system privileges is sufficient to prevent C##USER1 from seeing PDB001 data? You should remember that there is another way to see what happens in another container, through the V$ or CDB_ views. Not all data, but lot of information are exposed. The ALTER USER &#8230; SET CONTAINER_DATA is there to control that. But that&#8217;s for a future post.<br />\nRemember that a common user can be very powerful in a public or private cloud. You can control what he has access to, but then think of all ways of access.</p>\n",
    "protected": false
  }
}
