ในโลกของระบบข้อมูลขนาดใหญ่ (Enterprise Systems) การควบคุมการเข้าถึงข้อมูล (Access Control) ไม่ได้จำกัดอยู่แค่การอ่านหรือแก้ไขเท่านั้น แต่ยังรวมถึงการควบคุมว่าผู้ใช้กลุ่มใดมีสิทธิ์ในการ ‘พิมพ์’ หรือ ‘ส่งออก’ ข้อมูลชุดใดได้ด้วย การรั่วไหลของข้อมูลผ่านการพิมพ์จึงเป็นความเสี่ยงด้านความปลอดภัยที่สำคัญอย่างยิ่ง
ในฐานะ Senior Architect ที่ใช้ PostgreSQL เป็นแกนหลักในการพัฒนา เราต้องมั่นใจว่ากลไกการควบคุมสิทธิ์ (Permissions) นั้นแข็งแกร่งและสามารถตรวจสอบได้ บทความนี้จะเจาะลึกวิธีการใช้คุณสมบัติขั้นสูงของ PostgreSQL เพื่อจำลองและบังคับใช้ Print Access Control & Permissions อย่างมีประสิทธิภาพ
Understanding Print Permissions in PostgreSQL
สิ่งสำคัญที่ต้องทำความเข้าใจคือ PostgreSQL ไม่ได้มีคำสั่ง `GRANT PRINT` โดยตรง แต่การควบคุมสิทธิ์ในการพิมพ์จะถูกจัดการผ่านการควบคุมสิทธิ์ในการเข้าถึงข้อมูล (Data Access) และการจำกัดการมองเห็นข้อมูล (Data Visibility) ซึ่งสามารถทำได้โดยใช้กลไกหลักๆ ดังนี้:
- Role-Based Access Control (RBAC): กำหนดว่าผู้ใช้กลุ่มใดสามารถเข้าถึงตารางหรือฟังก์ชันใดได้
- Views: สร้างมุมมองที่จำกัดเฉพาะคอลัมน์หรือแถวที่ผู้ใช้กลุ่มนั้นๆ ควรเห็น
- Row-Level Security (RLS): เป็นกลไกที่ทรงพลังที่สุดในการจำกัดแถวข้อมูลที่ผู้ใช้สามารถเห็นได้ แม้ว่าผู้ใช้จะมีสิทธิ์เข้าถึงตารางก็ตาม
Implementing Access Control with PostgreSQL Functions and RLS
เพื่อจำลองการควบคุมสิทธิ์การพิมพ์ที่ซับซ้อน เรามักจะใช้ฟังก์ชัน (Functions) ที่ทำงานภายใต้บริบทของสิทธิ์ที่กำหนด (Security Context) และผสานรวมกับ RLS เพื่อให้แน่ใจว่าข้อมูลที่ถูกดึงออกมาเพื่อการพิมพ์นั้นเป็นไปตามขอบเขตที่กำหนดเท่านั้น
สมมติว่าเรามีตาราง `documents` ที่มีข้อมูลความลับ และเราต้องการให้เฉพาะผู้ใช้ระดับ ‘Manager’ เท่านั้นที่สามารถดึงข้อมูลทั้งหมดได้ ส่วน ‘Staff’ จะเห็นได้เฉพาะข้อมูลของตนเอง
SQL
-- 1. สร้างตารางตัวอย่าง (Documents) และคอลัมน์ผู้รับผิดชอบ (assigned_to)
CREATE TABLE documents (
document_id SERIAL PRIMARY KEY,
title VARCHAR(100),
content TEXT,
assigned_to VARCHAR(50)
);
-- 2. เปิดใช้งาน Row-Level Security บนตาราง
ALTER TABLE documents ENABLE ROW LEVEL SECURITY;
-- 3. สร้าง Policy สำหรับ Staff (จำกัดการเห็นเฉพาะข้อมูลของตนเอง)
CREATE POLICY staff_policy ON documents
FOR SELECT USING (assigned_to = current_user);
-- 4. สร้างฟังก์ชันเพื่อจำกัดการเข้าถึงข้อมูลสำหรับการพิมพ์
-- ฟังก์ชันนี้จะถูกเรียกใช้แทนการ SELECT โดยตรง
CREATE OR REPLACE FUNCTION get_printable_documents()
RETURNS TABLE (document_id INT, title VARCHAR, content TEXT) AS $$
BEGIN
-- ใช้ SELECT ที่ถูกจำกัดสิทธิ์โดย RLS
RETURN QUERY SELECT document_id, title, content FROM documents;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER; -- SECURITY DEFINER ให้ฟังก์ชันรันด้วยสิทธิ์สูงสุด
-- 5. การเรียกใช้: ผู้ใช้ทุกคนต้องเรียกผ่านฟังก์ชันนี้เท่านั้น
SELECT * FROM get_printable_documents();
การใช้ `SECURITY DEFINER` ในฟังก์ชันทำให้มั่นใจว่าแม้ผู้ใช้จะถูกจำกัดสิทธิ์ในการเข้าถึงตารางโดยตรง แต่เมื่อพวกเขาเรียกใช้ฟังก์ชันนี้ ข้อมูลที่ถูกส่งออกมาจะถูกกรองและจำกัดตามตรรกะที่เขียนไว้ในฟังก์ชันเท่านั้น นี่คือการควบคุมสิทธิ์ที่เหนือกว่าการใช้แค่ `GRANT` ทั่วไป
Conclusion
การควบคุมสิทธิ์ในการพิมพ์ข้อมูลใน PostgreSQL ไม่ใช่การใช้คำสั่งเดียว แต่เป็นการออกแบบสถาปัตยกรรมความปลอดภัยที่ซ้อนทับกัน (Layered Security) โดยการผสานรวม Row-Level Security (RLS) เข้ากับฟังก์ชันที่ทำงานด้วยสิทธิ์ที่กำหนด (SECURITY DEFINER) ช่วยให้เราสามารถบังคับใช้หลักการ Least Privilege ได้อย่างสมบูรณ์ ทำให้มั่นใจได้ว่าข้อมูลที่ถูกดึงออกมาเพื่อวัตถุประสงค์ในการพิมพ์หรือส่งออก จะเป็นข้อมูลที่ผู้ใช้มีสิทธิ์เห็นอย่างแท้จริง ซึ่งเป็นมาตรฐานสูงสุดของระบบ Enterprise Data Security