Oracle Label Security (OLS) เป็นส่วนขยายของเทคโนโลยี Virtual Private Database (VPD) ซึ่งเริ่มนำมาใช้ตั้งแต่ Oracle 8i OLS อนุญาตให้มีการควบคุมการเข้าถึงลงในแถวต่างๆ ตามป้ายกำกับที่ระบุ ฟังก์ชันการทำงานที่คล้ายคลึงกันสามารถทำซ้ำโดยใช้ Fine Grained Access Control (FGAC) แต่ OLS ให้โซลูชันที่ง่ายกว่าสำหรับการรักษาความปลอดภัยระดับแถว (row-level security) ในบทความนี้ฉันจะนำเสนอตัวอย่างง่ายๆของการกำหนดค่า OLS
ตั้งค่าฐานข้อมูล
- หากไม่ได้เลือกตัวเลือก Label Security เมื่อครั้งติดตั้ง Oracle Database สามารถเรียกตัวติดตั้งและเลือกตัวเลือก Label Security เพิ่มเติมได้ภายหลัง
- เข้าระบบด้วยบัญชีผู้ใช้ Oracle เปิด terminal พิมพ์ dbca (Database Server เป็น Linux)
- เมื่อได้ Welcome Screen คลิก Next
- ที่หน้า Operation คลิก Configure Database Options แล้วคลิก Next
- หน้า Database เลือกฐานข้อมูลที่ต้องการ คลิก Next
- ที่หน้า Database Features คลิกเลือก Label Security คลิก Next
- คลิก Finish
- เมื่อจบการตั้งค่าให้ restart database
สร้างผู้ใช้ทดสอบ
คำสั่งทั้งหมดทำภายใน sqlplus สร้างผู้ใช้ ols_test มีรหัสผ่านว่า password โดยให้สิทธิ์ CONNECT, RESOURCE, SELECT_CATALOG_ROLE
sqlplus, / as sysdba
CONN / AS SYSDBA
CREATE USER ols_test IDENTIFIED BY password
DEFAULT TABLESPACE users TEMPORARY TABLESPACE temp
GRANT CONNECT, RESOURCE, SELECT_CATALOG_ROLE TO ols_test;
ต่อไปเป็นการให้สิทธิ์ในแพ็คเกจ OLS แก่ผู้ใช้ ols_test จำเป็นต้อง unlock ผู้ใช้ lbacsys และตั้งรหัสผ่านว่า lbacsys เพื่อใช้เป็นคนกำหนดสิทธิ์ต่างๆ ให้ ols_test ได้แก่สิทธิ์ execute บน sa_components, sa_user_admin, sa_label_admin, sa_policy_admin, sa_audit_admin, sa_sysdba, to_lbac_data_label และให้ ols_test เป็น lbac_dba
sqlplus, / as sysdba, lbacsys/lbacsys
ALTER USER lbacsys IDENTIFIED BY lbacsys ACCOUNT UNLOCK;
CONN lbacsys/lbacsys
GRANT EXECUTE ON sa_components TO ols_test WITH GRANT OPTION;
GRANT EXECUTE ON sa_user_admin TO ols_test WITH GRANT OPTION;
GRANT EXECUTE ON sa_user_admin TO ols_test WITH GRANT OPTION;
GRANT EXECUTE ON sa_label_admin TO ols_test WITH GRANT OPTION;
GRANT EXECUTE ON sa_policy_admin TO ols_test WITH GRANT OPTION;
GRANT EXECUTE ON sa_audit_admin TO ols_test WITH GRANT OPTION;
GRANT LBAC_DBA TO ols_test;
GRANT EXECUTE ON sa_sysdba TO ols_test;
GRANT EXECUTE ON to_lbac_data_label TO ols_test;
สร้าง Policy
ต่อไปจะสร้าง policy ชื่อ region_policy ด้วยผู้ใช้ ols_test และระบุชื่อของ column ที่จะเป็นที่เก็บ label ว่า region_label
sqlplus, ols_test/password
CONN ols_test/password
BEGIN
SA_SYSDBA.CREATE_POLICY(
policy_name => 'region_policy',
column_name => 'region_label');
END;
/
GRANT region_policy_DBA TO ols_test;
กำหนด component ของ label
สร้าง component ของ label เพื่อใช้สำหรับ policy ที่สร้างไว้ตอนต้น region_policy
sqlplus, ols_test/password
– สร้างระดับไว้ 3 ระดับ คือ 20, 40 และ 60 มีชื่อเรียกสั้น ๆ ว่า L1, L2 และ L3 ชื่อเรียกยาว ๆ ว่า Level 1, Level 2 และ Level 3 ตามลำดับ
– สร้างสิทธิ์การใช้งานไว้ 2 ชนิดประกอบด้วย 100, 120 มีชื่อเรียกอย่างย่อว่า M และ E และชื่อเรียกยาวว่า Manage และ Employee ตามลำดับ
– สร้างกลุ่มของ policy ไว้ 4 กลุ่ม 20, 40, 60 และ 80 ชื่อย่อ R20, R40, R60 และ R80 ชื่อยาว Region North, Region South, Region East และ Region West ตามลำดับ
สุดท้ายกำหนดให้ ols_test เป็นผู้มีสิทธิ์สูงสุดใน policy region_policy
EXECUTE SA_COMPONENTS.CREATE_LEVEL('region_policy',20,'L1','Level 1');
EXECUTE SA_COMPONENTS.CREATE_LEVEL('region_policy',40,'L2','Level 2');
EXECUTE SA_COMPONENTS.CREATE_LEVEL('region_policy',60,'L3','Level 3');
EXECUTE SA_COMPONENTS.CREATE_COMPARTMENT('region_policy',100,'M','MANAGEMENT');
EXECUTE SA_COMPONENTS.CREATE_COMPARTMENT('region_policy',120,'E','EMPLOYEE');
EXECUTE SA_COMPONENTS.CREATE_GROUP('region_policy',20,'R20','REGION NORTH');
EXECUTE SA_COMPONENTS.CREATE_GROUP('region_policy',40,'R40','REGION SOUTH');
EXECUTE SA_COMPONENTS.CREATE_GROUP('region_policy',60,'R60','REGION EAST');
EXECUTE SA_COMPONENTS.CREATE_GROUP('region_policy',80,'R80','REGION WEST');
EXECUTE SA_USER_ADMIN.SET_USER_PRIVS('region_policy','ols_test','FULL,PROFILE_ACCESS');
สร้าง Table ทดสอบ
สร้าง table พร้อมข้อมูลทดสอบใน schema ols_test โดย table ชื่อ customers มีฟิลด์ id, cust_type, first_name, last_name, region, credit กำหนดให้ id เป็น Primary key และ insert ข้อมูลลง table ด้วย
sqlplus, ols_test/password
CONN ols_test/password
CREATE TABLE customers (
id NUMBER(10) NOT NULL,
cust_type VARCHAR2(10),
first_name VARCHAR2(30),
last_name VARCHAR2(30),
region VARCHAR2(5),
credit NUMBER(10,2),
CONSTRAINT customer_pk PRIMARY KEY (id));
GRANT SELECT, INSERT, UPDATE, DELETE ON customers TO PUBLIC;
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES ( 1, 'SILVER', 'Harry', 'Hill', 'NORTH', 11000.00);
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES ( 2, 'SILVER', 'Vic', 'Reeves', 'NORTH', 2000.00);
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES ( 3, 'SILVER', 'Bob', 'Mortimer', 'WEST', 500.00);
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES ( 4, 'SILVER', 'Paul', 'Whitehouse', 'SOUTH', 1000.00);
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES ( 5, 'SILVER', 'Harry', 'Enfield', 'EAST', 20000.00);
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES ( 6, 'GOLD', 'Jenifer', 'Lopez', 'WEST', 500.00);
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES ( 7, 'GOLD', 'Kylie', 'Minogue', 'NORTH', 1000.00);
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES ( 8, 'GOLD', 'Maria', 'Carey', 'WEST', 1000.00);
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES ( 9, 'GOLD', 'Dani', 'Minogue', 'SOUTH', 20000.00);
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES (10, 'GOLD', 'Whitney', 'Houston', 'EAST', 500.00);
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES (11, 'PLATINUM', 'Robbie', 'Williams', 'SOUTH', 500.00);
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES (12, 'PLATINUM', 'Thom', 'Yorke', 'NORTH', 2000.00);
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES (13, 'PLATINUM', 'Gareth', 'Gates', 'WEST', 10000.00);
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES (14, 'PLATINUM', 'Darius', 'Dinesh', 'EAST', 2000.00);
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES (15, 'PLATINUM', 'Will', 'Young', 'EAST', 100.00);
COMMIT;
สร้าง label function
เป็นการสร้าง function ชื่อ get_customer_label สำหรับสร้าง label ประกอบด้วย p_cust_type, p_region, p_credit
sqlplus, ols_test/password
– โดยกำหนด policy ระดับด้วย p_credit >2000 ก็จะมี v_label ว่า L3 ถ้า p_credit > 500 v_label คือ L2 และ p_credit < 500 v_label คือ L1
– กำหนด p_cust_type เป็น platinum หรือไม่ถ้าเป็นก็จะอยู่ในจะมีิสิทธิ์ M ถ้าไม่ก็จะเป็น E โดยเอาค่าที่ได้มาต่อกับ v_label ข้อที่แล้ว
– กำหนด p_region ถ้าเป็น north จะอยู่กลุ่ม R20 เป็นต้น และจะเอาค่าที่ได้ไปต่อกับ v_label ที่ได้จากข้อที่แล้ว
– ค่าที่ return จา function นี้จะเป็นชื่อ policy และ v_label สุดท้ายที่ได้จากข้อกำหนดที่กล่าวมาข้างต้น
CREATE OR REPLACE FUNCTION get_customer_label (
p_cust_type IN VARCHAR2,
p_region IN VARCHAR2,
p_credit IN NUMBER)
RETURN LBACSYS.LBAC_LABEL AS
v_label VARCHAR2(80);
BEGIN
IF p_credit > 2000 THEN
v_label := 'L3:';
ELSIF p_credit > 500 THEN
v_label := 'L2:';
ELSE
v_label := 'L1:';
END IF;
IF p_cust_type = 'PLATINUM' THEN
v_label := v_label || 'M:';
ELSE
v_label := v_label || 'E:';
END IF;
IF p_region = 'NORTH' THEN
v_label := v_label || 'R20';
ELSIF p_region = 'SOUTH' THEN
v_label := v_label || 'R40';
ELSIF p_region = 'EAST' THEN
v_label := v_label || 'R60';
ELSIF p_region = 'WEST' THEN
v_label := v_label || 'R80';
END IF;
RETURN TO_LBAC_DATA_LABEL('region_policy',v_label);
END get_customer_label;
/
SHOW ERRORS
สั่งให้ Policy ทำงานกับ table ที่สร้าง
เมื่อสั่งให้ Policy ทำงานจะเป็นการเพิ่ม column ที่เก็บ label ใน table เป้าหมาย
sqlplus, ols_test/password
CONN ols_test/password
BEGIN
SA_POLICY_ADMIN.APPLY_TABLE_POLICY(
policy_name => 'REGION_POLICY',
schema_name => 'OLS_TEST',
table_name => 'CUSTOMERS',
table_options => 'NO_CONTROL');
END;
/
เริ่มสร้าง label
เป็นการกำหนดค่าเริ่มต้นสำหรับ region_label ลงไปใน table ซึ่งถ้าไม่มีข้อมูลในฟิลด์นี้จะไม่มีใครสามารถเข้าถึงได้
sqlplus, ols_test/password
UPDATE customers
SET region_label = CHAR_TO_LABEL('REGION_POLICY','L1');
COMMIT;
สั่งให้ Policy ทำงานอีกครั้ง
ต่อไปจะเป็นการสั่งให้ policy ทำงานอีกครั้งใน table customers เพื่อเปลี่ยนค่าเป็นค่าที่ได้จะเป็นค่าจาก function ที่สร้างไว้
sqlplus, ols_test/password
BEGIN
SA_POLICY_ADMIN.REMOVE_TABLE_POLICY('REGION_POLICY','OLS_TEST','CUSTOMERS');
SA_POLICY_ADMIN.APPLY_TABLE_POLICY (
policy_name => 'REGION_POLICY',
schema_name => 'OLS_TEST',
table_name => 'CUSTOMERS',
table_options => 'READ_CONTROL,WRITE_CONTROL,CHECK_CONTROL',
label_function => 'ols_test.get_customer_label(:new.cust_type,:new.region,:new.credit)',
predicate => NULL);
END;
/
สั่งให้ label ทำงานกับข้อมูลในแต่ละแถว
ปรับปรุงข้อมูลให้เป็นตามฟังก์ชันที่สร้างไว้กับข้อมูลแต่ละแถว
sqlplus, ols_test/password
UPDATE customers
SET first_name = first_name;
COMMIT;
สร้าง user ทดสอบ
สร้าง user อื่นๆ เพื่อทดสอบ label ได้แก่ sales_manager, sales_north, sales_south, sales_east, sales_west
sqlplus, / as sysdba, (sales_manager, sales_nort, sales_south, sales_east, sales_west, ols_test)/password
– sales_manager มี label ว่า L3:M,E:R20,R40,R60,R80 แปลว่า sales_manager สามารถอ่านและเขียนข้อมูลได้ทุก Region
– sales_north มี label ว่า L3:E:R20,R40 แปลว่า sales_north สามารถอ่านข้อมูลที่อยู่ใน Region North และ South
– sales_south มี label ว่า L3:E:R20,R40,R60,R80 แปลว่า sales_south อ่านข้อมูลได้ทุก Region
– sales_east มี label ว่า L3:E:R60 แปลว่า sales_east อ่านข้อมูล Region East ได้อย่างเดียว
– sales_west มี label ว่า L3:E:R80 แปลว่า sales_west อ่านข้อมูล Region West ได้อย่างเดียว
CONN / AS SYSDBA;
CREATE USER sales_manager IDENTIFIED BY password;
CREATE USER sales_north IDENTIFIED BY password;
CREATE USER sales_south IDENTIFIED BY password;
CREATE USER sales_east IDENTIFIED BY password;
CREATE USER sales_west IDENTIFIED BY password;
GRANT CONNECT TO sales_manager, sales_north, sales_south, sales_east, sales_west;
CONN ols_test/password
BEGIN
SA_USER_ADMIN.SET_USER_LABELS('region_policy','sales_manager','L3:M,E:R20,R40,R60,R80');
SA_USER_ADMIN.SET_USER_LABELS('region_policy','sales_north','L3:E:R20,R40');
SA_USER_ADMIN.SET_USER_LABELS('region_policy','sales_south','L3:E:R20,R40,R60,R80');
SA_USER_ADMIN.SET_USER_LABELS('region_policy','sales_east','L3:E:R60');
SA_USER_ADMIN.SET_USER_LABELS('region_policy','sales_west','L3:E:R80');
END;
/
ทดสอบ Label Security
เข้าระบบผ่าน sqlplus ด้วย user ต่างๆ ที่สร้างในข้อที่แล้วเพื่อดูข้อมูลว่าถูกต้องหรือไม่ เพื่อความสะดวกจึงเข้าผ่านโปรแกรมสำเร็จรูปอื่นเพื่อให้ดูง่าย ได้ผลดังรูปต่อไปนี้นี้
sqlplus, sales_manager, sales_north, sales_south, sales_east, sales_west
จบขอให้สนุก
ที่มา https://oracle-base.com/articles/9i/oracle-label-security-9i#Installation