Day: August 6, 2018

  • Oracle Label Security

    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
    – สร้างระดับไว้ 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

    sqlplus, ols_test/password
    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
    – โดยกำหนด 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 สุดท้ายที่ได้จากข้อกำหนดที่กล่าวมาข้างต้น

    sqlplus, ols_test/password
    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
    – 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 ได้อย่างเดียว

    sqlplus, / as sysdba, (sales_manager, sales_nort, sales_south, sales_east, sales_west, ols_test)/password
    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

  • WordPress new editor

    อีกไม่นาน WordPress เวอร์ชั่นถัดไป จะใช้ Editor ชื่อ Gutenberg เป็น default editor แทน โดยขยับให้ editor แบบเดิมไปเป็น plugin ชื่อ Classic editor ครับ

    วันนี้ก็ลองใช้ editor ใหม่นี้ และโพสต์เพจนี้ดูว่าใช้ยากมั้ย

    เมื่อ upgrade WordPress เป็น 4.9.8 ก็จะพบเพจเชิญชวน และ คำแนะนำ

    หน้าตา editor ก็ ประมาณนี้ 

    ตัวเลือกก็เป็น ปุ่มเปิด/ปิด ด้วยเครื่องหมาย สามเหลี่ยม เพื่อเปิดรายการมาให้เลือก เช่น categories ที่ต้องการ เมื่ออยู่ที่แท็บ document แต่ถ้า cursor วางอยู่ในข้อความ จะย้ายไปที่แท็บ Block จะเห็น ตัวเลือกอีกชุด

    น่าจะใช้งานได้ดีกว่าแบบเดิม