proxy user oracle

Hello. One of the issues we often deal with as DBAs is the number of developers working on the main database schema. One way to track what each of them is doing and to monitor their activities is by using a proxy user. Apart from providing auditing capabilities, this method offers the benefit that if someone leaves the team, there’s no need to change passwords—just locking the user is enough. To clarify, I’ll walk you through an example:

The first step is to create a user who owns the main schema and then create a table, a sequence, and a procedure within that schema. We’ll also grant it the create session privilege:

SQL> show pdbs

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED

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

         2 PDB$SEED                       READ ONLY  NO

         3 ORCLPDB                        READ WRITE NO

SQL> alter session set container=orclpdb;

Session altered.

SQL> create user owneruser identified by securepass;

User created.

SQL> grant create table to owneruser;

Grant succeeded.

SQL> grant create procedure to owneruser;

Grant succeeded.

SQL> grant unlimited tablespace to owneruser;

Grant succeeded.

SQL> grant create sequence to owneruser;

Grant succeeded.

SQL> grant create session to owneruser;

Grant succeeded.

Now we connect to this user and create a table, a procedure, and a sequence.

[oracle@oracle9-19 ~]$ sqlplus owneruser@orclpdb

SQL*Plus: Release 19.0.0.0.0 - Production on Sun Sep 29 04:42:23 2024

Version 19.23.0.0.0

Copyright (c) 1982, 2023, Oracle.  All rights reserved.

Enter password:

Connected to:

Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production

Version 19.23.0.0.0

SQL> show user;

USER is "OWNERUSER"

SQL> CREATE TABLE my_table (

    id NUMBER, 

    created_date DATE 

);  

Table created.

SQL> CREATE SEQUENCE my_seq

 START WITH     1000

 INCREMENT BY   1

 NOCACHE

 NOCYCLE;

Sequence created.

SQL> CREATE OR REPLACE PROCEDURE insert_into_my_table IS

    new_id NUMBER;

BEGIN

    new_id := my_seq.NEXTVAL;

    INSERT INTO my_table (id, created_date)

    VALUES (new_id, SYSDATE);

    COMMIT;

END;

/

Procedure created.

To be sure, let’s call the procedure and select data from the table:

SQL> exec insert_into_my_table;

PL/SQL procedure successfully completed.

SQL> select * from my_table;

        ID CREATED_D

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

      1000 29-SEP-24

That was just the introduction. Now, let’s move to the main topic. Suppose we have multiple users who need to work on the owneruser schema simultaneously. We create a user named user1 and grant it the create session privilege and the ability to connect via the owneruser.

SQL> create user user1 identified by passworduser1;

User created.

SQL> grant create session to user1;

Grant succeeded.

SQL> alter user owneruser grant connect through user1;

User altered.

Now, we’ll connect to the database as a proxy user using this account:

[oracle@oracle9-19 ~]$ sqlplus user1[owneruser]@orclpdb

SQL*Plus: Release 19.0.0.0.0 - Production on Sun Sep 29 04:59:51 2024

Version 19.23.0.0.0

Copyright (c) 1982, 2023, Oracle.  All rights reserved.

Enter password:

Last Successful login time: Sun Sep 29 2024 04:42:35 -04:00

Connected to:

Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production

Version 19.23.0.0.0

 

SQL> show user;

USER is "OWNERUSER"

As we can see, although we connected using user1 and its password, the user displayed and the one we have access to is owneruser.

Let’s see the session details:

select sys_context('userenv','session_user') as session_user,

       sys_context('userenv','session_schema') as session_schema,

       sys_context('userenv','current_schema') as current_schema,

       sys_context('userenv','proxy_user') as proxy_user

from dual;

SESSION_USER         SESSION_SCHEMA       CURRENT_SCHEMA       PROXY_USER

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

OWNERUSER            OWNERUSER            OWNERUSER            USER1

As shown, owneruser is connected, but through user1, which is displayed in the proxy_user field.

Let’s check the permissions:

SQL> exec insert_into_my_table;

PL/SQL procedure successfully completed.

SQL> select * from my_table;

        ID CREATED_D

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

      1000 29-SEP-24

      1001 29-SEP-24

Now, let’s move to how we can audit this user. I suggest the following script to activate in the database. Please share your thoughts if you have any suggestions for improvement:

CREATE AUDIT POLICY proxy_user_audit

  ACTIONS ALL

  WHEN 'SYS_CONTEXT(''USERENV'', ''PROXY_USER'') = ''USER1'''

  EVALUATE PER SESSION;

AUDIT POLICY proxy_user_audit;

And its result:

SQL> select OS_USERNAME,DBUSERNAME,DBPROXY_USERNAME,UNIFIED_AUDIT_POLICIES,sql_text  

       from unified_audit_trail  

       where EVENT_TIMESTAMP>sysdate-1/48 AND UNIFIED_AUDIT_POLICIES='PROXY_USER_AUDIT';

OS_USERNAME     DBUSERNAME      DBPROXY_USERNAM UNIFIED_AUDIT_POLICI SQL_TEXT

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

oracle          OWNERUSER       USER1           PROXY_USER_AUDIT

oracle          OWNERUSER       USER1           PROXY_USER_AUDIT     SELECT MY_SEQ.NEXTVAL FROM "SYS"."DUAL"

oracle          OWNERUSER       USER1           PROXY_USER_AUDIT     INSERT INTO MY_TABLE (ID, CREATED_DATE) VALUES (:B1, SYSDATE)

oracle          OWNERUSER       USER1           PROXY_USER_AUDIT     COMMIT

oracle          OWNERUSER       USER1           PROXY_USER_AUDIT     BEGIN insert_into_my_table; END;