سلام. یکی از موردهایی که به عنوان 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