Preparation As DBA |
Create Demo Users |
conn sys@pdbdev as sysdba
CREATE USER secdemo
IDENTIFIED BY secdemo
DEFAULT TABLESPACE uwdata
TEMPORARY TABLESPACE temp
PROFILE DEFAULT
QUOTA 0 ON system
QUOTA 0 ON sysaux
QUOTA UNLIMITED ON uwdata;
ALTER USER secdemo ENABLE EDITIONS;
GRANT create session TO secdemo;
GRANT create any context TO secdemo;
GRANT create public synonym TO secdemo;
GRANT create table TO secdemo;
GRANT create view TO secdemo;
GRANT create procedure TO secdemo;
GRANT execute on dbms_rls TO secdemo;
GRANT create trigger TO secdemo;
GRANT administer database trigger TO secdemo;
CREATE USER morgan
IDENTIFIED BY dan;
GRANT create session TO morgan;
CREATE USER kyte
IDENTIFIED BY tom;
GRANT create session TO kyte; |
|
Preparation As Application Owner |
Create Demo Tables and constraints |
conn secdemo/secdemo@pdbdev
CREATE TABLE employee (
employee_id NUMBER(4),
last_name VARCHAR2(15),
first_name VARCHAR2(15),
cost_center_id NUMBER(4),
manager_id NUMBER(4));
ALTER TABLE employee
ADD CONSTRAINT pk_employee
PRIMARY KEY (employee_id);
CREATE TABLE cost_center (
cost_center_id NUMBER(4),
manager_id NUMBER(4),
description VARCHAR2(30));
ALTER TABLE cost_center
ADD CONSTRAINT pk_cost_center
PRIMARY KEY (cost_center_id);
CREATE TABLE exp_report (
report_id NUMBER(4),
employee_id NUMBER(4) NOT NULL,
cost_center_id NUMBER(4) NOT NULL,
submission_date DATE,
approval_date DATE,
purpose VARCHAR2(30));
ALTER TABLE exp_report
ADD CONSTRAINT pk_exp_report
PRIMARY KEY (report_id);
CREATE TABLE exp_line (
report_id NUMBER(4),
line_id NUMBER(4),
type_id NUMBER(4),
received_amount NUMBER(7,2),
receipt NUMBER(1),
exp_date DATE,
currency_id NUMBER(4));
ALTER TABLE exp_line
ADD CONSTRAINT pk_exp_line
PRIMARY KEY (report_id, line_id);
CREATE TABLE exp_type (
type_id NUMBER(4),
description VARCHAR2(30));
ALTER TABLE exp_type
ADD CONSTRAINT pk_exp_type
PRIMARY KEY (type_id);
CREATE TABLE exp_currency (
currency_id NUMBER(4),
description VARCHAR2(30),
rate NUMBER(7,2),
symbol VARCHAR2(6));
ALTER TABLE exp_currency
ADD CONSTRAINT pk_exp_currency
PRIMARY KEY (currency_id);
ALTER TABLE employee
ADD CONSTRAINT fk_employee_cost_center_id
FOREIGN KEY (cost_center_id)
REFERENCES cost_center (cost_center_id);
ALTER TABLE employee
ADD CONSTRAINT fk_employee_manager_id
FOREIGN KEY (manager_id)
REFERENCES employee (employee_id);
ALTER TABLE exp_report
ADD CONSTRAINT fk_exp_report_employee_id
FOREIGN KEY (employee_id)
REFERENCES employee (employee_id);
ALTER TABLE exp_report
ADD CONSTRAINT fk_exp_report_cost_center_id
FOREIGN KEY (cost_center_id)
REFERENCES cost_center (cost_center_id);
ALTER TABLE exp_line
ADD CONSTRAINT fk_exp_line_report_id
FOREIGN KEY (report_id)
REFERENCES exp_report (report_id);
ALTER TABLE exp_line
ADD CONSTRAINT fk_exp_line_type_id
FOREIGN KEY (type_id)
REFERENCES exp_type (type_id);
ALTER TABLE exp_line
ADD CONSTRAINT fk_exp_line_currency_id
FOREIGN KEY (currency_id)
REFERENCES exp_currency (currency_id);
SELECT object_name, object_type
FROM user_objects
ORDER BY 2,1;
OBJECT_NAME
OBJECT_TYPE
------------------ -------------
PK_COST_CENTER INDEX
PK_EMPLOYEE INDEX
PK_EXP_CURRENCY INDEX
PK_EXP_LINE INDEX
PK_EXP_REPORT INDEX
PK_EXP_TYPE INDEX
COST_CENTER TABLE
EMPLOYEE TABLE
EXP_CURRENCY TABLE
EXP_LINE TABLE
EXP_REPORT TABLE
EXP_TYPE TABLE
SELECT table_name, constraint_name, constraint_type
FROM user_constraints
ORDER BY 1,3;
TABLE_NAME
CONSTRAINT_NAME
C
------------------ ---------------------------- -
COST_CENTER PK_COST_CENTER
P
EMPLOYEE
PK_EMPLOYEE
P
EMPLOYEE
FK_EMPLOYEE_COST_CENTER_ID R
EMPLOYEE
FK_EMPLOYEE_MANAGER_ID R
EXP_CURRENCY PK_EXP_CURRENCY
P
EXP_LINE
PK_EXP_LINE
P
EXP_LINE
FK_EXP_LINE_REPORT_ID R
EXP_LINE
FK_EXP_LINE_CURRENCY_ID R
EXP_LINE
FK_EXP_LINE_TYPE_ID
R
EXP_REPORT SYS_C008210
C
EXP_REPORT SYS_C008211
C
EXP_REPORT PK_EXP_REPORT
P
EXP_REPORT
FK_EXP_REPORT_EMPLOYEE_ID R
EXP_REPORT
FK_EXP_REPORT_COST_CENTER_ID R
EXP_TYPE
PK_EXP_TYPE
P |
Create Demo View |
CREATE OR REPLACE VIEW exp_report_sum_view AS
SELECT e.employee_id, e.last_name, r.report_id, r.purpose,
SUM(l.received_amount) total_amount, r.cost_center_id,
r.submission_date, r.approval_date
FROM employee e, exp_report r, exp_line l
WHERE e.employee_id = r.employee_id
AND r.report_id = l.report_id
GROUP BY E.employee_id, r.report_id, e.last_name, r.purpose,
r.cost_center_id, r.submission_date, r.approval_date; |
Grant Object Privileges
PUBLIC access not required ... or desired ... this is done this way for demo purposes only. |
GRANT SELECT ON employee TO morgan, kyte;
GRANT SELECT ON cost_center TO kyte, morgan;
GRANT SELECT ON exp_report TO morgan, kyte;
GRANT SELECT ON exp_line TO kyte, morgan;
GRANT SELECT ON exp_type TO morgan, kyte;
GRANT SELECT ON exp_currency TO kyte, morgan;
GRANT SELECT ON exp_report_sum_view TO morgan, kyte;
GRANT UPDATE ON exp_report TO kyte, morgan;
GRANT DELETE ON exp_report TO morgan, kyte;
GRANT INSERT ON exp_report TO kyte, morgan;
GRANT DELETE ON exp_line TO morgan, kyte;
GRANT INSERT ON exp_line TO kyte, morgan; |
Insert Records Into Exp_Currency Table |
INSERT INTO exp_currency
(
VALUES (1, '$ US DOLLAR',2.0,'$');
INSERT INTO exp_currency
VALUES (2, 'FF - FRENCH FRANC',0.2,'FF');
INSERT INTO exp_currency
VALUES (3, '£ - UK POUNDS',1.0,'£');
INSERT INTO exp_currency
VALUES (4, 'DM - DEUTCH MARKS',0.6,'DM');
COMMIT;
SELECT * FROM exp_currency; |
Insert Records Into Exp_Type Table |
INSERT INTO exp_type VALUES (1, 'AIRFARE');
INSERT INTO exp_type VALUES (2, 'TAXI');
INSERT INTO exp_type VALUES (3, 'RENTAL CAR');
INSERT INTO exp_type VALUES (4, 'LIMO/CAR SERVICE');
INSERT INTO exp_type VALUES (5, 'ROOM');
INSERT INTO exp_type VALUES (6, 'FOOD/DRINKS-HOTEL BILL');
INSERT INTO exp_type VALUES (7, 'PHONE/OTHER-HOTEL BILL');
INSERT INTO exp_type VALUES (8, 'BREAKFAST');
INSERT INTO exp_type VALUES (9, 'LUNCH');
INSERT INTO exp_type VALUES (10, 'DINNER');
COMMIT;
SELECT * FROM exp_type; |
Insert Records Into Cost_Center Table |
INSERT INTO cost_center VALUES (692, 7839, 'ADMIN.');
INSERT INTO cost_center VALUES (672, 7839, 'US SALES');
INSERT INTO cost_center VALUES (667, 7506, 'ASIAN SALES');
INSERT INTO cost_center VALUES (670, 7569, 'EURO SALES');
INSERT INTO cost_center VALUES (668, 7507, 'WW SUPPORT');
INSERT INTO cost_center VALUES (671, 7839, 'WW MKTG');
INSERT INTO cost_center VALUES (673, 7505, 'US MKTG');
INSERT INTO cost_center VALUES (674, 7698, 'ASIAN MKTG');
INSERT INTO cost_center VALUES (669, 7566, 'EUROPEAN MKTG');
COMMIT;
SELECT * FROM cost_center; |
Insert Into Employee Table |
INSERT INTO employee VALUES (7839,'KING','FRANCIS',672,NULL);
INSERT INTO employee VALUES (7566,'JONES','TERRY',671,7839);
INSERT INTO employee VALUES (7902,'FORD','JENNIFER',669,7566);
INSERT INTO employee VALUES (7369,'SMITH','JOHN',667,7902);
INSERT INTO employee VALUES (7698,'JURGEN','DIETER',670,7839);
INSERT INTO employee VALUES (7499,'ALLEN','KEVIN',670,7698);
INSERT INTO employee VALUES (7505,'DOYLE','JEAN',671,7839);
INSERT INTO employee VALUES (7506,'DENNIS','LYNN',671,7839);
INSERT INTO employee VALUES (7507,'BAKER','LESLIE',671,7839);
INSERT INTO employee VALUES (7521,'WARD','CYNTHIA',670,7698);
INSERT INTO employee VALUES (7555,'PETERS','DANIEL',670,7505);
INSERT INTO employee VALUES (7557,'SHAW','KAREN',670,7505);
INSERT INTO employee VALUES (7560,'DUNCAN','SARAH',670,7506);
INSERT INTO employee VALUES (7564,'LANGE','GREGORY',670,7506);
INSERT INTO employee VALUES (7569,'MORGAN','DANIEL',670,7839);
INSERT INTO employee VALUES (7600,'PORTER','RAYMOND',670,7505);
INSERT INTO employee VALUES (7609,'LEWIS','RICHARD',668,7507);
INSERT INTO employee VALUES (7654,'MARTIN','KENNETH',670,7698);
INSERT INTO employee VALUES (7676,'SOMMERS','DENISE',668,7507);
INSERT INTO employee VALUES (7782,'CLARK','CAROL',671,7839);
INSERT INTO employee VALUES (7788,'SCOTT','DONALD',669,7566);
INSERT INTO employee VALUES (7789,'WEST','LIVIA',670,7506);
INSERT INTO employee VALUES (7799,'FISHER','MATTHEW',669,7569);
INSERT INTO employee VALUES (7820,'ROSS','PAUL',670,7505);
INSERT INTO employee VALUES (7844,'TURNER','MARY',670,7698);
INSERT INTO employee VALUES (7876,'ADAMS','DIANE',667,7788);
INSERT INTO employee VALUES (7900,'JAMES','FRED',667,7698);
INSERT INTO employee VALUES (7916,'ROBERTS','GRACE',669,7569);
INSERT INTO employee VALUES (7919,'DOUGLAS','MICHAEL',667,7799);
INSERT INTO employee VALUES (7934,'KYTE','TOM',670,7782);
INSERT INTO employee VALUES (7950,'JENSEN','ALICE',667,7505);
INSERT INTO employee VALUES (7954,'MURRAY','JAMES',670,7506);
COMMIT;
SELECT last_name, employee_id, manager_id, LEVEL
FROM employee
START WITH employee_id = 7934
CONNECT BY PRIOR employee_id = manager_id;
LAST_NAME
EMPLOYEE_ID MANAGER_ID LEVEL
--------------- ----------- ---------- ------
KYTE
7934 7782
1
SELECT last_name, employee_id, manager_id,
LEVEL
FROM employee
START WITH employee_id = 7569
CONNECT BY PRIOR employee_id = manager_id
ORDER BY level;
LAST_NAME
EMPLOYEE_ID MANAGER_ID LEVEL
--------------- ----------- ---------- ------
MORGAN
7569 7839
1
ROBERTS
7916 7569
2
FISHER
7799 7569
2
DOUGLAS
7919 7799
3 |
Insert Records Into Exp_Report Table |
INSERT INTO exp_report VALUES (1,7954,667,SYSDATE-3,SYSDATE,'Cust Visit');
INSERT INTO exp_report VALUES (2,7950,670,SYSDATE,NULL,'Cust Visit');
INSERT INTO exp_report VALUES (3,7954,670,SYSDATE,NULL,'Cust Visit');
INSERT INTO exp_report VALUES (4,7954,671,SYSDATE,NULL,'Cust Visit');
INSERT INTO exp_report VALUES (5,7934,670,SYSDATE-1,NULL,'Training');
INSERT INTO exp_report VALUES (6,7698,670,SYSDATE-7,NULL,'Training');
INSERT INTO exp_report VALUES (7,7698,670,SYSDATE-7,NULL,'Cust Visit');
INSERT INTO exp_report VALUES (8,7934,671,SYSDATE-7,NULL,'Training');
INSERT INTO exp_report VALUES (9,7934,670,SYSDATE-7,NULL,'Training');
INSERT INTO exp_report VALUES (10,7954,670,SYSDATE-20,SYSDATE-20,'Cust Visit');
INSERT INTO exp_report VALUES (11,7954,670,SYSDATE-20,SYSDATE-17,'Cust Visit');
INSERT INTO exp_report VALUES (12,7569,670,SYSDATE-22,SYSDATE-19,'Cust Visit');
COMMIT;
SELECT * FROM exp_report; |
Insert Records Into Exp_Line Table |
INSERT INTO exp_line VALUES (1,1,1,500.2,1,SYSDATE-33,1);
INSERT INTO exp_line VALUES (1,2,8,12.2,1,SYSDATE-33,1);
INSERT INTO exp_line VALUES (1,3,9,20.0,1,SYSDATE-33,1);
INSERT INTO exp_line VALUES (2,1,2,21.0,1,SYSDATE-23,1);
INSERT INTO exp_line VALUES (2,2,5,200.0,1,SYSDATE-23,1);
INSERT INTO exp_line VALUES (2,3,9,12.0,1,SYSDATE-23,1);
INSERT INTO exp_line VALUES (2,4,10,20.0,1,SYSDATE-23,1);
INSERT INTO exp_line VALUES (3,1,9,10.2,1,SYSDATE-33,1);
INSERT INTO exp_line VALUES (4,1,5,210.3,1,SYSDATE-31,1);
INSERT INTO exp_line VALUES (4,2,6,21.0,1,SYSDATE-31,1);
INSERT INTO exp_line VALUES (4,3,7,12.1,1,SYSDATE-31,1);
INSERT INTO exp_line VALUES (4,4,8,10.3,1,SYSDATE-31,1);
INSERT INTO exp_line VALUES (5,1,10,53.2,1,SYSDATE-28,1);
INSERT INTO exp_line VALUES (6,1,10,23.2,1,SYSDATE-44,2);
INSERT INTO exp_line VALUES (7,1,5,210.3,1,SYSDATE-28,1);
INSERT INTO exp_line VALUES (7,2,6,21.0,1,SYSDATE-28,1);
INSERT INTO exp_line VALUES (7,3,7,12.1,1,SYSDATE-28,1);
INSERT INTO exp_line VALUES (7,4,8,10.3,1,SYSDATE-28,1);
INSERT INTO exp_line VALUES (8,1,5,1120.3,1,SYSDATE-27,3);
INSERT INTO exp_line VALUES (8,2,6,20.0,1,SYSDATE-27,3);
INSERT INTO exp_line VALUES (8,3,7,17.1,1,SYSDATE-27,3);
INSERT INTO exp_line VALUES (8,4,8,20.3,1,SYSDATE-27,3);
INSERT INTO exp_line VALUES (9,1,5,1120.3,1,SYSDATE-20,3);
INSERT INTO exp_line VALUES (9,2,6,20.0,1,SYSDATE-20,3);
INSERT INTO exp_line VALUES (9,3,7,17.1,1,SYSDATE-20,3);
INSERT INTO exp_line VALUES (9,4,8,20.3,1,SYSDATE-20,3);
INSERT INTO exp_line VALUES (9,5,5,1120.3,1,SYSDATE-20,3);
INSERT INTO exp_line VALUES (9,6,6,20.0,1,SYSDATE-20,3);
INSERT INTO exp_line VALUES (10,1,5,1120.3,1,SYSDATE-45,1);
INSERT INTO exp_line VALUES (11,1,5,1120.3,1,SYSDATE-38,1);
INSERT INTO exp_line VALUES (12,1,5,1120.3,1,SYSDATE-38,2);
INSERT INTO exp_line VALUES (12,2,5,1120.3,1,SYSDATE-38,2);
COMMIT;
SELECT * FROM exp_line;
exec dbms_stats.gather_schema_stats(USER, CASCADE=>TRUE); |
Create The Application Context |
CREATE OR REPLACE CONTEXT exp_rpt USING secdemo.exprep_ctx;
SELECT owner, object_type
FROM all_objects
WHERE object_name = 'EXP_RPT';
no rows selected
CREATE OR REPLACE PUBLIC SYNONYM exprep_ctx FOR secdemo.exprep_ctx;
Synonym created.
SELECT owner, object_type
FROM all_objects
WHERE object_name = 'EXPREP_CTX';
OWNER
OBJECT_TYPE
------------------------- -------------------------
PUBLIC
SYNONYM |
Create the package that implements the context and its audit table |
-- create login audit table
CREATE TABLE ctx_audit (
login_date TIMESTAMP WITH LOCAL TIME ZONE,
user_name VARCHAR2(30),
emp_id VARCHAR2(30),
cc VARCHAR2(30));
-- create context setting package
CREATE OR REPLACE PACKAGE exprep_ctx AUTHID
DEFINER IS
PROCEDURE set_ctx;
END exprep_ctx;
/
CREATE OR REPLACE PACKAGE BODY exprep_ctx IS
PROCEDURE set_ctx IS
empid employee.employee_id%TYPE;
countrec NUMBER;
cc employee.cost_center_id%TYPE;
role VARCHAR2(20);
whoami user_users.username%TYPE;
BEGIN
SELECT sys_context('userenv', 'session_user')
INTO whoami
FROM dual;
IF whoami NOT IN ('SYS', 'SYSTEM', 'SECDEMO') THEN
-- set the employee id
SELECT employee_id
INTO empid
FROM employee
WHERE last_name = whoami;
dbms_session.set_context('exp_rpt', 'emp_number', empid);
SELECT COUNT(*)
INTO countrec
FROM cost_center
WHERE manager_id = empid;
IF (countrec > 0) THEN
dbms_session.set_context('exp_rpt', 'exp_role', 'manager');
ELSE
dbms_session.set_context('exp_rpt', 'exp_role', 'employee');
END IF;
-- seet the cost center number
SELECT cost_center_id
INTO cc
FROM employee
WHERE last_name = sys_context('userenv', 'session_user');
dbms_session.set_context('exp_rpt', 'cc_number', cc);
INSERT INTO ctx_audit VALUES (SYSTIMESTAMP, USER, empid, cc);
COMMIT;
END IF;
END set_ctx;
END exprep_ctx;
/
GRANT EXECUTE ON secdemo.exprep_ctx TO PUBLIC;
GRANT SELECT ON ctx_audit TO morgan, kyte; |
Create The Policy Functions Package |
CREATE OR REPLACE PACKAGE exp_security
AUTHID DEFINER AS
FUNCTION empview_sec(owner VARCHAR2, objname VARCHAR2) RETURN VARCHAR2;
FUNCTION empnum_sec(owner VARCHAR2, objname VARCHAR2) RETURN VARCHAR2;
FUNCTION empnumline_sec(owner VARCHAR2, objname VARCHAR2) RETURN VARCHAR2;
FUNCTION ccid_mgr_sec(owner VARCHAR2, objname VARCHAR2) RETURN VARCHAR2;
END exp_security;
/
CREATE OR REPLACE PACKAGE BODY exp_security AS
FUNCTION empview_sec(owner VARCHAR2, objname VARCHAR2) RETURN VARCHAR2 IS
predicate VARCHAR2(2000);
BEGIN
IF (sys_context('exp_rpt', 'exp_role') = 'manager') THEN
predicate := 'cost_center_id = sys_context(''exp_rpt'', ''cc_number'')';
ELSE
predicate := 'employee_id = sys_context(''exp_rpt'', ''emp_number'')';
END IF;
RETURN predicate;
END empview_sec;
--------------------
FUNCTION empnum_sec(owner VARCHAR2, objname VARCHAR2) RETURN VARCHAR2 IS
predicate VARCHAR2(2000);
BEGIN
predicate := 'employee_id = sys_context(''exp_rpt'',''emp_number'')';
RETURN predicate;
END empnum_sec;
--------------------
FUNCTION empnumline_sec(owner VARCHAR2, objname VARCHAR2)
RETURN VARCHAR2 IS
predicate VARCHAR2(2000);
BEGIN
predicate := 'report_id IN (
SELECT report_id
FROM exp_report
WHERE employee_id = sys_context(''exp_rpt'',''emp_number''))';
RETURN predicate;
END empnumline_sec;
--------------------
FUNCTION ccid_mgr_sec(owner VARCHAR2, objname VARCHAR2) RETURN VARCHAR2 IS
predicate VARCHAR2(2000);
BEGIN
predicate := 'cost_center_id = (
SELECT cost_center_id
FROM cost_center
WHERE manager_id = sys_context(''exp_rpt'',''emp_number''))';
RETURN predicate;
END ccid_mgr_sec;
END exp_security;
/
SELECT object_name, object_type
FROM user_objects
ORDER BY 2,1; |
|
Create Access Policies |
Add a row level security policy to a table or view |
dbms_rls.add_policy(
object_schema IN VARCHAR2 := NULL,
object_name IN VARCHAR2,
policy_name IN VARCHAR2,
function_schema IN VARCHAR2 := NULL,
policy_function IN VARCHAR2,
statement_types IN VARCHAR2 := NULL,
update_check IN BOOLEAN := FALSE,
enable IN BOOLEAN := TRUE,
static_policy IN BOOLEAN := FALSE,
policy_type IN BINARY_INTEGER := NULL,
long_predicate IN BOOLEAN := FALSE,
sec_relevant_cols IN VARCHAR2 := NULL,
sec_relevant_cols_opt IN BINARY_INTEGER := NULL,
namespace IN VARCHAR2 := NULL,
attribute IN VARCHAR2 := NULL); |
Policy #1 |
/* user can select only their reports if they are an employee. They can select their reports and all the reports in their cost center if they are the cost center manager */
exec dbms_rls.add_policy('secdemo', 'exp_report_sum_view', 'exp_rpt_view_policy', 'secdemo', 'exp_security.empview_sec', 'SELECT'); |
Policy #2 |
-- users can delete only their own reports
exec dbms_rls.add_policy(USER, 'exp_report', 'exp_rpt_policy', USER, 'exp_security.empnum_sec', 'DELETE'); |
Policy #3 |
-- user can delete a line in their report only if they are the report owner
exec dbms_rls.add_policy(USER,'exp_line', 'exp_line_policy', USER, 'exp_security.empnumline_sec', 'DELETE'); |
Policy #4 |
-- only a cost center manager can approve (update) a report
exec dbms_rls.add_policy(USER, 'exp_report', 'exp_rpt_approve_policy', USER, 'exp_security.ccid_mgr_sec', 'UPDATE');
SELECT policy_name
FROM user_policies;
POLICY_NAME
----------------------
EXP_RPT_APPROVE_POLICY
EXP_RPT_POLICY
EXP_LINE_POLICY
EXP_RPT_VIEW_POLICY |
Review Policy Metadata |
desc user_policies
col object_name format a20
col policy_group format a12
col policy_name format a22
col pf_owner format a8
col package format a12
col function format a14
col enable format a6
col static_policy format a13
col policy_type format a11
col long_predicate format a14
SELECT object_name, policy_group, policy_name
FROM user_policies;
OBJECT_NAME
POLICY_GROUP POLICY_NAME
-------------------- ------------ -------------------
EXP_REPORT_SUM_VIEW SYS_DEFAULT EXP_RPT_VIEW_POLICY
EXP_REPORT
SYS_DEFAULT EXP_RPT_POLICY
EXP_LINE
SYS_DEFAULT EXP_LINE_POLICY
EXP_REPORT
SYS_DEFAULT EXP_RPT_APPROVE_POLICY
SELECT object_name, policy_name, pf_owner, package, function
FROM user_policies;
OBJECT_NAME
POLICY_NAME
PF_OWNER PACKAGE FUNCTION
-------------------- ---------------------- -------- ------------
--------------
EXP_REPORT_SUM_VIEW EXP_RPT_VIEW_POLICY SECDEMO
EXP_SECURITY EMPVIEW_SEC
EXP_REPORT
EXP_RPT_POLICY SECDEMO
EXP_SECURITY EMPNUM_SEC
EXP_LINE
EXP_LINE_POLICY SECDEMO
EXP_SECURITY EMPNUMLINE_SEC
EXP_REPORT
EXP_RPT_APPROVE_POLICY SECDEMO EXP_SECURITY CCID_MGR_SEC
SELECT policy_name, sel, ins, upd, del, idx, chk_option, enable, static_policy, policy_type
FROM user_policies;
POLICY_NAME
SEL INS UPD DEL IDX CHK ENABLE STATIC_POL POLICY_TYPE
---------------------- --- --- --- --- --- --- ------ ----------
-----------
EXP_RPT_VIEW_POLICY YES NO NO NO NO
NO YES NO
DYNAMIC
EXP_RPT_POLICY NO
NO NO YES NO NO YES NO
DYNAMIC
EXP_LINE_POLICY NO
NO NO YES NO NO YES NO
DYNAMIC
EXP_RPT_APPROVE_POLICY NO NO YES NO NO NO
YES NO
DYNAMIC |
Disable and Re-enable a Policy |
SELECT object_name, policy_group, policy_name, enable
FROM user_policies
WHERE policy_name ='EXP_RPT_VIEW_POLICY';
OBJECT_NAME
POLICY_GROUP POLICY_NAME
ENABLE
-------------------- ------------ ---------------------- ------
EXP_REPORT_SUM_VIEW SYS_DEFAULT EXP_RPT_VIEW_POLICY
YES
exec dbms_rls.enable_policy(USER, 'exp_report_sum_view', 'exp_rpt_view_policy', FALSE);
SELECT object_name, policy_group, policy_name, enable
FROM user_policies
WHERE policy_name ='EXP_RPT_VIEW_POLICY';
OBJECT_NAME
POLICY_GROUP POLICY_NAME
ENABLE
-------------------- ------------ ---------------------- ------
EXP_REPORT_SUM_VIEW SYS_DEFAULT EXP_RPT_VIEW_POLICY
NO
exec dbms_rls.enable_policy(USER, 'exp_report_sum_view', 'exp_rpt_view_policy', TRUE);
SELECT object_name, policy_group, policy_name, enable
FROM user_policies
WHERE policy_name ='EXP_RPT_VIEW_POLICY';
OBJECT_NAME
POLICY_GROUP POLICY_NAME
ENABLE
-------------------- ------------ ---------------------- ------
EXP_REPORT_SUM_VIEW SYS_DEFAULT EXP_RPT_VIEW_POLICY
YES |
Drop Policies |
exec dbms_rls.drop_policy('secdemo', 'exp_report_sum_view', 'exp_rpt_view_policy');
exec dbms_rls.drop_policy('secdemo', 'exp_report', 'exp_rpt_policy');
exec dbms_rls.drop_policy('secdemo', 'exp_line', 'exp_line_policy');
exec dbms_rls.drop_policy('secdemo', 'exp_report', 'exp_rpt_approve_policy');
SELECT policy_name
FROM user_policies;
no rows selected |
|
Create Policy Groups and Access Policies |
Create Policy Groups |
exec dbms_rls.create_policy_group('secdemo', 'exp_report_sum_view', 'demo_group1');
exec dbms_rls.create_policy_group('secdemo', 'exp_report', 'demo_group1');
exec dbms_rls.create_policy_group('secdemo', 'exp_line', 'demo_group2');
SELECT * FROM user_policy_groups;
OBJECT_NAME
POLICY_GROUP COM INH
-------------------- ------------ --- ---
EXP_REPORT_SUM_VIEW DEMO_GROUP1 NO NO
EXP_REPORT
DEMO_GROUP1 NO NO
EXP_LINE
DEMO_GROUP2 NO NO |
Create Grouped Policies |
exec dbms_rls.add_grouped_policy(USER, 'exp_report_sum_view', 'demo_group1', 'policy1', USER, 'exp_security.empview_sec', 'SELECT');
exec dbms_rls.add_grouped_policy(USER, 'exp_report', 'demo_group1', 'policy2', USER, 'exp_security.empnum_sec', 'DELETE');
exec dbms_rls.add_grouped_policy(USER,'exp_line', 'demo_group2', 'policy3', USER, 'exp_security.empnumline_sec', 'DELETE');
exec dbms_rls.add_grouped_policy(USER, 'exp_report', 'demo_group1','policy4', USER, 'exp_security.ccid_mgr_sec', 'UPDATE');
SELECT object_name, policy_group, policy_name, pf_owner, package, function
FROM user_policies;
SELECT policy_name, sel, ins, upd, del, idx, chk_option, enable, static_policy, policy_type, long_predicate
FROM user_policies; |
Disable and Re-enable a Grouped Policy |
SELECT object_name, policy_group, policy_name, enable
FROM user_policies
WHERE policy_name ='POLICY1';
exec dbms_rls.disable_grouped_policy(USER, 'exp_report_sum_view', 'demo_group1', 'policy1');
SELECT object_name, policy_group, policy_name, enable
FROM user_policies
WHERE policy_name ='POLICY1';
exec dbms_rls.enable_grouped_policy(USER, 'exp_report_sum_view', 'demo_group1', 'policy1');
SELECT object_name, policy_group, policy_name, enable
FROM user_policies
WHERE policy_name ='POLICY1'; |
|
Set Context On Logon |
Create Logon Trigger to enable context setting |
conn sys@pdbdev as sysdba
CREATE OR REPLACE TRIGGER secdemo.set_expense_ctx
AFTER LOGON
ON DATABASE
BEGIN
secdemo.exprep_ctx.set_ctx;
END;
/ |
|
Run Demo |
View data as manager Morgan |
conn morgan/dan@pdbdev
col emp_id format a7
col cc format a4
col login_date format a30
SELECT *
FROM secdemo.ctx_audit;
SELECT table_name
FROM all_tables
WHERE owner = 'SECDEMO';
col view_name format a30
SELECT view_name
FROM all_views
WHERE owner = 'SECDEMO';
-- no controlling policy
SELECT * FROM secdemo.employee;
col last_name format a9
col purpose format a10
col submission_date format a20
col approval_date format a20
-- controlled by policy #1
SELECT * FROM secdemo.exp_report_sum_view;
SELECT last_name
FROM secdemo.employee
WHERE employee_id IN (
SELECT manager_id
FROM secdemo.employee
WHERE employee_id IN (
SELECT employee_id FROM secdemo.exp_report_sum_view)); |
View data as employee Kyte |
conn secdemo/secdemo@pdbdev
SELECT * FROM ctx_audit;
exec dbms_rls.disable_grouped_policy(USER, 'exp_report_sum_view', 'demo_group1', 'policy1');
conn kyte/tom@pdbdev
SELECT * FROM secdemo.ctx_audit;
SELECT * FROM secdemo.employee;
SELECT * FROM secdemo.exp_report_sum_view;
EXPLAIN PLAN FOR
SELECT * FROM secdemo.exp_report_sum_view;
SELECT * FROM TABLE(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 32 | 1600 | 22 (10)| 00:00:01 |
| 1 | HASH GROUP BY | | 32 | 1600 | 22 (10)| 00:00:01 |
|* 2 | HASH JOIN | | 32 | 1600 | 21 (5)| 00:00:01 |
| 3 | MERGE JOIN | | 12 | 516 | 12 (9)| 00:00:01 |
| 4 | TABLE ACCESS BY INDEX ROWID| EMPLOYEE | 32 | 352 | 2 (0)| 00:00:01 |
| 5 | INDEX FULL SCAN | PK_EMPLOYEE | 32 | | 1 (0)| 00:00:01 |
|* 6 | SORT JOIN | | 12 | 384 | 10 (10)| 00:00:01 |
| 7 | TABLE ACCESS FULL | EXP_REPORT | 12 | 384 | 9 (0)| 00:00:01 |
| 8 | TABLE ACCESS FULL | EXP_LINE | 32 | 224 | 9 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("R"."REPORT_ID"="L"."REPORT_ID")
6 - access("E"."EMPLOYEE_ID"="R"."EMPLOYEE_ID")
filter("E"."EMPLOYEE_ID"="R"."EMPLOYEE_ID")
Note
-----
- this is an adaptive plan
conn secdemo/secdemo@pdbdev
exec dbms_rls.enable_grouped_policy(USER, 'exp_report_sum_view', 'demo_group1', 'policy1');
conn kyte/tom@pdbdev
-- no controlling policy
SELECT * FROM secdemo.employee;
-- controlled by policy #1
SELECT * FROM secdemo.exp_report_sum_view;
EXPLAIN PLAN FOR
SELECT * FROM secdemo.exp_report_sum_view;
SELECT * FROM TABLE(dbms_xplan.display);
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4 | 200 | 15 (7)| 00:00:01 |
| 1 | HASH GROUP BY | | 4 | 200 | 15 (7)| 00:00:01 |
| 2 | NESTED LOOPS | | 6 | 300 | 14 (0)| 00:00:01 |
| 3 | NESTED LOOPS | | 6 | 300 | 14 (0)| 00:00:01 |
| 4 | NESTED LOOPS | | 2 | 86 | 10 (0)| 00:00:01 |
| 5 | TABLE ACCESS BY INDEX ROWID| EMPLOYEE | 1 | 11 | 1 (0)| 00:00:01 |
|* 6 | INDEX UNIQUE SCAN | PK_EMPLOYEE | 1 | | 0 (0)| 00:00:01 |
|* 7 | TABLE ACCESS FULL | EXP_REPORT | 2 | 64 | 9 (0)| 00:00:01 |
|* 8 | INDEX RANGE SCAN | PK_EXP_LINE | 3 | | 1 (0)| 00:00:01 |
| 9 | TABLE ACCESS BY INDEX ROWID | EXP_LINE | 3 | 21 | 2 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
6 - access("E"."EMPLOYEE_ID"=TO_NUMBER(SYS_CONTEXT('exp_rpt','emp_number')))
7 - filter("R"."EMPLOYEE_ID"=TO_NUMBER(SYS_CONTEXT('exp_rpt','emp_number')))
8 - access("R"."REPORT_ID"="L"."REPORT_ID")
Note
-----
- this is an adaptive plan |
|
Demo Clean-up |
Dismantle the demo infrastructure |
conn secdemo/secdemo@pdbdev
SELECT object_name, policy_group, policy_name, enable
FROM user_policies;
exec dbms_rls.drop_grouped_policy(USER, 'exp_report_sum_view', 'demo_group1', 'policy1');
exec dbms_rls.drop_grouped_policy(USER, 'exp_report', 'demo_group1', 'policy2');
exec dbms_rls.drop_grouped_policy(USER, 'exp_report', 'demo_group2', 'policy3');
exec dbms_rls.drop_grouped_policy(USER, 'exp_report', 'demo_group1', 'policy4');
exec dbms_rls.drop_grouped_policy(USER, 'exp_report', 'demo_group1', 'policy5');
SELECT object_name, policy_group, policy_name, enable
FROM user_policies;
SELECT * FROM user_policy_groups;
exec dbms_rls.delete_policy_group(USER, 'exp_report_sum_view', 'demo_group1');
exec dbms_rls.delete_policy_group(USER, 'exp_report', 'demo_group1');
exec dbms_rls.delete_policy_group(USER, 'exp_line', 'demo_group2');
SELECT * FROM user_policy_groups;
conn sys@pdbdev as sysdba
drop user kyte cascade;
drop user morgan cascade;
drop user secdemo cascade;
col package format a25
col namespace format a25
col schema format a20
SELECT * FROM dba_context ORDER BY 1,2,3;
drop context exp_rpt; |