ในโลกของการจัดการข้อมูล (Data Management) ข้อมูลถือเป็นสินทรัพย์ที่มีค่าสูงสุด การเข้าถึงข้อมูลที่เกินขอบเขต (Over-access) ไม่ว่าจะเป็นการเปิดเผยข้อมูลส่วนตัว หรือการแก้ไขข้อมูลที่ไม่ได้รับอนุญาต ล้วนนำมาซึ่งความเสี่ยงด้านความปลอดภัยและกฎหมาย การกำหนดขอบเขตข้อมูล (Data Boundaries) จึงเป็นหลักการสำคัญที่สถาปนิกระบบทุกคนต้องให้ความสำคัญ
ในบริบทของ PostgreSQL แนวคิดนี้ถูกนำมาประยุกต์ใช้อย่างทรงพลังผ่านคุณสมบัติที่เรียกว่า Row-Level Security (RLS) ซึ่งเป็นกลไกที่ช่วยให้เราสามารถกำหนดนโยบายการเข้าถึงข้อมูลในระดับแถว (Row) ได้อย่างแม่นยำ ทำให้มั่นใจได้ว่าผู้ใช้แต่ละคนจะเห็นเฉพาะข้อมูลที่ตนเองมีสิทธิ์เท่านั้น นี่คือการสร้าง ‘ขอบเขต’ ทางดิจิทัลที่สมบูรณ์แบบ
🛡️ Boundaries & Self-Protection ในระดับฐานข้อมูล
การทำความเข้าใจ RLS คือการเรียนรู้ที่จะให้สิทธิ์การเข้าถึง (Granting Access) อย่างจำกัด ไม่ใช่แค่การให้สิทธิ์แบบกว้างๆ (Wildcard Access) ซึ่งเป็นแนวคิดที่ผิดพลาดที่ทำให้เกิดช่องโหว่ การกำหนดขอบเขตที่สมดุล (Boundaries & Balance) ในที่นี้หมายถึงการสร้างนโยบายที่เคารพทั้งหลักการทางธุรกิจ (Business Logic) และความปลอดภัยของข้อมูล (Data Integrity) โดยไม่ขัดขวางการทำงานที่จำเป็น
Self-Protection ในทางเทคนิคคือการที่เราไม่ยอมให้ใครมาใช้ประโยชน์จากจุดอ่อนของระบบ (เช่น การที่ผู้ใช้ที่ควรเห็นข้อมูลแผนก A กลับสามารถ Query ข้อมูลของแผนก B ได้) RLS เข้ามาทำหน้าที่เป็นกำแพงป้องกันที่มองไม่เห็น โดยการบังคับใช้เงื่อนไข (Policy) ก่อนที่คำสั่ง SELECT ใดๆ จะถูกประมวลผล
⚙️ การใช้งาน PostgreSQL Row-Level Security (RLS)
เราจะสาธิตการสร้างขอบเขตข้อมูลโดยสมมติว่าเรามีตารางข้อมูลพนักงานที่เก็บข้อมูลของหลายแผนก และเราต้องการให้ผู้ใช้สามารถเห็นข้อมูลของแผนกตัวเองเท่านั้น
- สร้างตารางข้อมูล:
เราเริ่มต้นด้วยการสร้างตารางที่เก็บข้อมูลพนักงาน โดยมีคอลัมน์ที่ระบุแผนก (department_id) เพื่อใช้เป็นตัวกำหนดขอบเขต
- เปิดใช้งาน RLS:
คำสั่งนี้จะเปิดใช้งานกลไกการตรวจสอบขอบเขตสำหรับตารางนั้นๆ
- สร้าง Policy:
เราสร้างนโยบายที่ระบุว่าผู้ใช้ที่กำลัง Query ข้อมูล จะต้องมี
department_idตรงกับค่าที่กำหนดไว้ในเงื่อนไขเท่านั้น
SQL
SQL
-- 1. สร้างตารางข้อมูลพนักงาน (Employee Data Table)
SQL
SQL
CREATE TABLE employees (
SQL
SQL
employee_id INT PRIMARY KEY,
SQL
SQL
name VARCHAR(100),
SQL
SQL
department_id INT,
SQL
SQL
salary NUMERIC
SQL
SQL
);
SQL
SQL
INSERT INTO employees (employee_id, name, department_id, salary) VALUES
SQL
SQL
(1, 'Alice', 10, 60000), -- Dept 10
SQL
SQL
(2, 'Bob', 20, 75000), -- Dept 20
SQL
SQL
(3, 'Charlie', 10, 62000), -- Dept 10
SQL
SQL
(4, 'David', 30, 80000); -- Dept 30
SQL
SQL
-- 2. เปิดใช้งาน Row-Level Security บนตาราง employees
SQL
SQL
ALTER TABLE employees ENABLE ROW LEVEL SECURITY;
SQL
SQL
-- 3. สร้าง Policy เพื่อกำหนดขอบเขต (Boundary Policy)
SQL
SQL
-- นโยบายนี้กำหนดให้ผู้ใช้เห็นแถวข้อมูลที่ department_id ตรงกับค่าที่ส่งมาใน session variable (current_department)
SQL
SQL
CREATE POLICY department_policy ON employees FOR SELECT USING (department_id = current_department());
✅ การทดสอบการบังคับใช้ขอบเขต (Testing the Boundary)
เมื่อเรากำหนด Policy แล้ว การ Query ข้อมูลใดๆ จะถูกกรองโดยอัตโนมัติ หากเราตั้งค่า session ให้ผู้ใช้เป็นแผนก 20 (Bob) และพยายาม Query ข้อมูลทั้งหมด ระบบจะบังคับให้เห็นเฉพาะข้อมูลของ Bob เท่านั้น:
SQL
SQL
-- ตั้งค่าขอบเขตสำหรับผู้ใช้ (จำลองการล็อกอิน)
SQL
SQL
SET SESSION department_id = 20;
SQL
SQL
SELECT * FROM employees;
ผลลัพธ์ที่ได้: ระบบจะแสดงเฉพาะแถวของ Bob (department_id = 20) เท่านั้น แม้ว่าคำสั่ง Query จะไม่ได้ระบุเงื่อนไข WHERE เลยก็ตาม นี่คือการปกป้องข้อมูลที่สมบูรณ์แบบ
💡 บทสรุป: การสร้างระบบที่ปลอดภัยและสมดุล
การใช้ Row-Level Security ใน PostgreSQL ไม่ได้เป็นเพียงแค่การเพิ่มฟีเจอร์ แต่คือการยกระดับมาตรฐานความปลอดภัยของสถาปัตยกรรมฐานข้อมูล การกำหนดขอบเขตที่ชัดเจนนี้ช่วยให้เราบรรลุ ความกตัญญูทางข้อมูล (Data Stewardship) คือการใช้ข้อมูลอย่างรับผิดชอบและจำกัดสิทธิ์ตามความจำเป็น (Principle of Least Privilege) ซึ่งเป็นแนวทางปฏิบัติที่ดีที่สุด (Best Practice) สำหรับระบบที่ต้องการความปลอดภัยสูง การทำเช่นนี้คือการสร้างสมดุลระหว่างการเข้าถึงข้อมูลที่จำเป็นกับการปกป้องข้อมูลที่สำคัญอย่างสูงสุด