ساخت کاربر proxy در دیتابیس

سلام. یکی از موردهایی که به عنوان dba خیلی باهاش درگیر هستیم، تعداد کاربران developer هست که در حال کار بر روی اسکیمای اصلی دیتابیس هستند. یکی از روشهایی که می تونیم بفهمیم هر کدوم در حال انجام چه کارهایی هستند و اگر بخواهیم اونها رو مانیتور کنیم، استفاده از proxy user هست. این روش جدا از امکان audit این مزیت رو بهمون میده که در صورتی که فردی از تیم جدا بشه، نیاز نیست که پسورد ها رو عوض کنیم و فقط کافیه که اون کاربر رو lock کنیم. برای اینکه این موضوع جا بیفته، با مثال براتون شرح میدم:

قدم اول ساخت کاربری هست که صاحب ساختار اصلی باشه و یک جدول و و یک sequence و یک پروسیجر بعلاوه هم در اون ایجاد می کنیم. مجوز create session هم بهش میدیم:

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.

حالا بهش متصل میشیم و یک جدول و یک پروسیجر و یک 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.

 

محض اطمینان پروسیجر رو فراخوانی میکنیم و سپس از جدول select  می گیریم.

SQL> exec insert_into_my_table;

PL/SQL procedure successfully completed.

SQL> select * from my_table;

        ID CREATED_D

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

      1000 29-SEP-24

تا اینجاش شد فقط مقدمه. حالا بریم سر اصل مطلب فرض کنیم چند کاربر داریم که باید همزمان روی کاربر owneruser کار کنند. یک کاربر می سازیم به اسم user1 و بهش اجازه create session و اتصال از طریق کاربر 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.

حالا میخوایم به دیتابیس بصورت proxy user با این کاربر متصل بشیم:

[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"

همانطور که می بینیم با اینکه با کاربر user1 و رمز عبور مربوط به اون متصل شدیم، اما کاربری که نمایش داده میشه و دسترسی بهش داریم، کاربر owneruser هست.

ببینیم که مشخصات session چی هست:

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

بله. تمام مشخصات نشون میده که owneruser وصله اما از طریق user1 که در قسمت proxy_user نمایش داده شده.

ببینیم که دسترسی ها چطوره:

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

حالا بریم به سراغ اینکه چطور این کاربر رو audit کنیم. من اسکریپت زیر رو پیشنهاد میکنم که در دیتابیس فعال کنید. لطفا اگر نظری در این مورد دارید، بفرمائید که بهبود بدم.

CREATE AUDIT POLICY proxy_user_audit

  ACTIONS ALL

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

  EVALUATE PER SESSION;

  

  AUDIT POLICY proxy_user_audit;

و نتیجه اون:

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     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;

oracle          OWNERUSER       USER1           PROXY_USER_AUDIT     select * from my_table

oracle          OWNERUSER       USER1           PROXY_USER_AUDIT

oracle          OWNERUSER       USER1           PROXY_USER_AUDIT     ALTER SESSION SET TIME_ZONE='-04:00'

oracle          OWNERUSER       USER1           PROXY_USER_AUDIT     SELECT DECODE(USER, 'XS$NULL',  XS_SYS_CONTEXT('XS$SESSION','USERNAME'), USER) F

oracle          OWNERUSER       USER1           PROXY_USER_AUDIT     BEGIN DBMS_APPLICATION_INFO.SET_MODULE(:1,NULL); END;

oracle          OWNERUSER       USER1           PROXY_USER_AUDIT