Database User Management ใน PostgreSQL

การจัดการผู้ใช้ (User Management) เป็นหนึ่งในงานสำคัญที่ผู้ดูแลฐานข้อมูลต้องเข้าใจอย่างถ่องแท้ PostgreSQL มีระบบจัดการสิทธิ์ที่ยืดหยุ่นและรัดกุม โดยใช้แนวคิด Role-Based Access Control ซึ่งช่วยให้สามารถกำหนดสิทธิ์การเข้าถึงข้อมูลได้อย่างละเอียดในทุกระดับ

บทความนี้จะอธิบายการสร้าง แก้ไข และลบผู้ใช้งาน รวมถึงการกำหนดสิทธิ์ (Privileges) การใช้ Role และ Group Role การจัดการรหัสผ่าน และแนวทางปฏิบัติที่ดีในการรักษาความปลอดภัยของระบบฐานข้อมูล

ทำความเข้าใจ Role ใน PostgreSQL

ใน PostgreSQL ไม่มีการแยกแนวคิดระหว่าง “User” กับ “Group” อย่างชัดเจนเหมือนระบบฐานข้อมูลอื่น ๆ แต่ใช้แนวคิดเดียวคือ Role ซึ่งสามารถทำหน้าที่เป็นได้ทั้งผู้ใช้งาน (User Role) และกลุ่ม (Group Role) ขึ้นอยู่กับวิธีการตั้งค่า

Role ที่มี LOGIN attribute จะทำหน้าที่เหมือน User ที่สามารถเชื่อมต่อเข้าฐานข้อมูลได้ ส่วน Role ที่ไม่มี LOGIN จะทำหน้าที่เป็น Group Role สำหรับรวบรวมสิทธิ์แล้วมอบให้ผู้ใช้อื่น

การสร้าง Role และ User

สร้าง User Role (เข้าสู่ระบบได้)

คำสั่ง CREATE ROLE ร่วมกับ LOGIN attribute ใช้สำหรับสร้างผู้ใช้ที่สามารถเชื่อมต่อเข้าฐานข้อมูลได้

-- สร้าง user พร้อมรหัสผ่าน
CREATE ROLE app_user WITH LOGIN PASSWORD 'SecurePass123!';

-- สร้าง user พร้อมกำหนดวันหมดอายุ
CREATE ROLE temp_user WITH LOGIN PASSWORD 'TempPass456!'
    VALID UNTIL '2026-12-31';

-- ใช้ CREATE USER (shorthand ของ CREATE ROLE WITH LOGIN)
CREATE USER api_user WITH PASSWORD 'ApiPass789!';

คำสั่ง CREATE USER เป็น shorthand ของ CREATE ROLE WITH LOGIN กล่าวคือทั้งสองคำสั่งทำงานเหมือนกัน ต่างกันแค่ CREATE USER จะมี LOGIN attribute เป็นค่าเริ่มต้น

สร้าง Group Role (ใช้รวมสิทธิ์)

Group Role ใช้สำหรับจัดกลุ่มสิทธิ์แล้วมอบให้ผู้ใช้หลายคนพร้อมกัน ช่วยลดความซ้ำซ้อนในการกำหนดสิทธิ์

-- สร้าง group role (ไม่มี LOGIN)
CREATE ROLE readonly;
CREATE ROLE readwrite;
CREATE ROLE admin_group;

-- เพิ่ม user เข้า group
GRANT readonly TO app_user;
GRANT readwrite TO api_user;
GRANT admin_group TO app_user, api_user;

Role Attributes ที่สำคัญ

แต่ละ Role สามารถกำหนด Attributes ต่าง ๆ เพื่อควบคุมความสามารถได้

-- สร้าง superuser (มีสิทธิ์ทุกอย่าง)
CREATE ROLE dba WITH LOGIN PASSWORD 'DbaPass!' SUPERUSER;

-- สร้าง user ที่สร้างฐานข้อมูลได้
CREATE ROLE developer WITH LOGIN PASSWORD 'DevPass!' CREATEDB;

-- สร้าง user ที่สร้าง role อื่นได้
CREATE ROLE user_admin WITH LOGIN PASSWORD 'AdminPass!' CREATEROLE;

-- สร้าง user ที่ใช้ replication ได้
CREATE ROLE replicator WITH LOGIN PASSWORD 'ReplPass!' REPLICATION;

-- จำกัดจำนวน connection
CREATE ROLE limited_user WITH LOGIN PASSWORD 'LimitPass!'
    CONNECTION LIMIT 5;

สรุป Attributes หลักที่ใช้บ่อย ได้แก่ SUPERUSER (สิทธิ์สูงสุด), CREATEDB (สร้างฐานข้อมูลได้), CREATEROLE (สร้าง Role ได้), REPLICATION (ใช้ทำ Replication), LOGIN (เข้าสู่ระบบได้), CONNECTION LIMIT (จำกัด Connection) และ VALID UNTIL (กำหนดวันหมดอายุ)

การจัดการสิทธิ์ (Privileges)

GRANT — มอบสิทธิ์

คำสั่ง GRANT ใช้มอบสิทธิ์การเข้าถึงวัตถุต่าง ๆ ในฐานข้อมูลให้กับ Role

-- สิทธิ์ระดับฐานข้อมูล
GRANT CONNECT ON DATABASE mydb TO app_user;
GRANT CREATE ON DATABASE mydb TO developer;

-- สิทธิ์ระดับ Schema
GRANT USAGE ON SCHEMA public TO app_user;
GRANT CREATE ON SCHEMA public TO developer;

-- สิทธิ์ระดับตาราง
GRANT SELECT ON TABLE customers TO readonly;
GRANT SELECT, INSERT, UPDATE ON TABLE orders TO readwrite;
GRANT ALL PRIVILEGES ON TABLE products TO admin_group;

-- สิทธิ์บนทุกตารางใน schema
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO readwrite;

REVOKE — ถอนสิทธิ์

คำสั่ง REVOKE ใช้ถอนสิทธิ์ที่เคยมอบให้ออก

-- ถอนสิทธิ์เฉพาะ
REVOKE INSERT ON TABLE customers FROM readwrite;

-- ถอนสิทธิ์ทั้งหมดบนตาราง
REVOKE ALL PRIVILEGES ON TABLE sensitive_data FROM app_user;

-- ถอนสิทธิ์บนทุกตารางใน schema
REVOKE ALL ON ALL TABLES IN SCHEMA public FROM old_user;

Default Privileges — สิทธิ์อัตโนมัติสำหรับวัตถุใหม่

เมื่อสร้างตารางหรือวัตถุใหม่ สิทธิ์จะไม่ถูกมอบให้ Role เดิมอัตโนมัติ ต้องใช้ ALTER DEFAULT PRIVILEGES เพื่อกำหนดสิทธิ์ล่วงหน้า

-- กำหนดว่าตารางใหม่ที่สร้างใน schema public
-- จะให้ readonly มีสิทธิ์ SELECT อัตโนมัติ
ALTER DEFAULT PRIVILEGES IN SCHEMA public
    GRANT SELECT ON TABLES TO readonly;

-- ตารางใหม่ให้ readwrite มีสิทธิ์ CRUD อัตโนมัติ
ALTER DEFAULT PRIVILEGES IN SCHEMA public
    GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO readwrite;

-- Sequence ใหม่ให้ readwrite ใช้ได้อัตโนมัติ
ALTER DEFAULT PRIVILEGES IN SCHEMA public
    GRANT USAGE, SELECT ON SEQUENCES TO readwrite;

Default Privileges เป็นสิ่งที่มักถูกมองข้าม แต่มีความสำคัญมาก เพราะหากไม่กำหนด ทุกครั้งที่สร้างตารางใหม่จะต้องมา GRANT สิทธิ์ด้วยตนเอง

การจัดการสิทธิ์ระดับ Column

ระบบฐานข้อมูลนี้รองรับการกำหนดสิทธิ์ในระดับคอลัมน์ ช่วยให้จำกัดการเข้าถึงเฉพาะคอลัมน์ที่จำเป็น เหมาะสำหรับตารางที่มีข้อมูลอ่อนไหว

-- อนุญาตให้ดูได้เฉพาะบางคอลัมน์
GRANT SELECT (id, name, email) ON TABLE customers TO support_team;

-- อนุญาตให้แก้ไขเฉพาะบางคอลัมน์
GRANT UPDATE (phone, address) ON TABLE customers TO support_team;

-- ซ่อนคอลัมน์ sensitive เช่น credit_card, ssn
-- โดยไม่ GRANT คอลัมน์เหล่านั้น

Row-Level Security (RLS)

Row-Level Security ช่วยจำกัดการเข้าถึงข้อมูลในระดับแถว โดยสร้าง Policy เพื่อกำหนดว่าผู้ใช้แต่ละคนจะเห็นหรือแก้ไขข้อมูลแถวใดได้บ้าง

-- เปิดใช้งาน RLS บนตาราง
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;

-- สร้าง Policy: user เห็นเฉพาะข้อมูลของตัวเอง
CREATE POLICY user_orders ON orders
    FOR ALL
    USING (user_id = current_user)
    WITH CHECK (user_id = current_user);

-- Policy สำหรับ manager เห็นข้อมูลทุกคนในทีม
CREATE POLICY manager_orders ON orders
    FOR SELECT
    USING (
        department_id IN (
            SELECT department_id FROM managers
            WHERE manager_name = current_user
        )
    );

-- ให้ admin ข้ามกฎ RLS ได้
ALTER TABLE orders FORCE ROW LEVEL SECURITY;
GRANT ALL ON TABLE orders TO admin_group;
CREATE POLICY admin_all ON orders
    TO admin_group
    USING (true)
    WITH CHECK (true);

RLS เป็นเครื่องมือที่ทรงพลังสำหรับระบบ Multi-Tenant หรือแอปพลิเคชันที่ผู้ใช้แต่ละคนต้องเห็นเฉพาะข้อมูลของตนเอง ช่วยลดความเสี่ยงในการเข้าถึงข้อมูลข้ามผู้ใช้ได้อย่างมีประสิทธิภาพ

การแก้ไขและลบ Role

แก้ไข Role

-- เปลี่ยนรหัสผ่าน
ALTER ROLE app_user WITH PASSWORD 'NewSecurePass456!';

-- เพิ่ม/ลบ attribute
ALTER ROLE developer WITH CREATEDB;
ALTER ROLE developer WITH NOCREATEDB;

-- เปลี่ยนชื่อ
ALTER ROLE old_name RENAME TO new_name;

-- กำหนดวันหมดอายุ
ALTER ROLE temp_user VALID UNTIL '2026-06-30';

-- กำหนด configuration เฉพาะ role
ALTER ROLE app_user SET statement_timeout = '30s';
ALTER ROLE readonly SET default_transaction_read_only = on;

ลบ Role

การลบ Role ต้องถอนสิทธิ์และโอนความเป็นเจ้าของวัตถุทั้งหมดก่อน ไม่เช่นนั้นจะลบไม่สำเร็จ

-- ขั้นตอนลบ role อย่างถูกต้อง

-- 1. ถอนสิทธิ์ทั้งหมด
REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA public FROM old_user;
REVOKE ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public FROM old_user;
REVOKE USAGE ON SCHEMA public FROM old_user;
REVOKE CONNECT ON DATABASE mydb FROM old_user;

-- 2. โอนความเป็นเจ้าของวัตถุ
REASSIGN OWNED BY old_user TO postgres;

-- 3. ลบวัตถุที่เหลือ (ถ้ามี)
DROP OWNED BY old_user;

-- 4. ลบ role
DROP ROLE old_user;

หากพยายามลบ Role ที่ยังเป็นเจ้าของวัตถุอยู่ จะได้รับ error เช่น “role cannot be dropped because some objects depend on it” ดังนั้นต้องทำตามขั้นตอนข้างต้นทุกครั้ง

การจัดการรหัสผ่านและ Authentication

นโยบายรหัสผ่านที่แนะนำ

ระบบฐานข้อมูลนี้ไม่มี built-in password policy แต่สามารถบังคับใช้ผ่านการตั้งค่าและเครื่องมือเสริมได้

-- กำหนดวันหมดอายุรหัสผ่าน (บังคับเปลี่ยนทุก 90 วัน)
ALTER ROLE app_user VALID UNTIL '2026-07-07';

-- ใช้ SCRAM-SHA-256 แทน MD5 (แนะนำ)
-- แก้ไขใน postgresql.conf
-- password_encryption = 'scram-sha-256'

-- ตรวจสอบ authentication method ใน pg_hba.conf
-- host  mydb  app_user  10.0.0.0/24  scram-sha-256

ตั้งค่า pg_hba.conf สำหรับ User แต่ละคน

ไฟล์ pg_hba.conf ควบคุมวิธีการ Authentication สำหรับแต่ละ User และ IP ต้นทาง

# pg_hba.conf — ตัวอย่างการตั้งค่า

# superuser เข้าได้เฉพาะ local
local   all   postgres                peer
host    all   postgres   127.0.0.1/32   scram-sha-256

# app_user เข้าได้จาก application server
host    mydb   app_user   10.0.1.0/24   scram-sha-256

# readonly เข้าได้จาก analytics server
host    mydb   readonly   10.0.2.50/32   scram-sha-256

# ปิดกั้นทุก connection อื่น
host    all   all   0.0.0.0/0   reject

หลังแก้ไข pg_hba.conf ต้อง reload configuration ด้วยคำสั่ง SELECT pg_reload_conf(); หรือ systemctl reload postgresql

การตรวจสอบสิทธิ์และ Role ที่มีอยู่

การตรวจสอบสถานะของผู้ใช้และสิทธิ์เป็นงานประจำที่ผู้ดูแลระบบควรทำอย่างสม่ำเสมอ

-- แสดง role ทั้งหมดใน psql
\du

-- ดูรายละเอียด role จาก system catalog
SELECT rolname, rolsuper, rolcreaterole, rolcreatedb,
       rolcanlogin, rolconnlimit, rolvaliduntil
FROM pg_roles
WHERE rolname NOT LIKE 'pg_%'
ORDER BY rolname;

-- ดู role membership (ใครอยู่ group ไหน)
SELECT r.rolname AS role,
       m.rolname AS member
FROM pg_auth_members am
JOIN pg_roles r ON r.oid = am.roleid
JOIN pg_roles m ON m.oid = am.member
ORDER BY r.rolname, m.rolname;

-- ดูสิทธิ์บนตาราง
SELECT grantee, table_name, privilege_type
FROM information_schema.table_privileges
WHERE table_schema = 'public'
ORDER BY grantee, table_name;

-- ดู default privileges ที่ตั้งไว้
SELECT defaclrole::regrole AS owner,
       defaclnamespace::regnamespace AS schema,
       defaclobjtype AS object_type,
       defaclacl AS default_acl
FROM pg_default_acl;

แนวทางปฏิบัติที่ดี (Best Practices)

หลัก Least Privilege

มอบสิทธิ์เท่าที่จำเป็นเท่านั้น อย่าให้สิทธิ์ SUPERUSER หรือ ALL PRIVILEGES โดยไม่จำเป็น ใช้ Group Role จัดกลุ่มสิทธิ์แล้วมอบให้ผู้ใช้แทนการให้สิทธิ์ทีละคน

-- ❌ ไม่แนะนำ: ให้สิทธิ์กว้างเกินไป
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO app_user;

-- ✅ แนะนำ: ให้สิทธิ์เฉพาะที่จำเป็น
GRANT SELECT, INSERT ON TABLE orders TO app_user;
GRANT SELECT ON TABLE products TO app_user;
GRANT USAGE, SELECT ON SEQUENCE orders_id_seq TO app_user;

แยก Role ตามหน้าที่

สร้าง Role แยกสำหรับแต่ละการใช้งาน เช่น Role สำหรับแอปพลิเคชัน Role สำหรับ Backup และ Role สำหรับ Monitoring อย่าใช้ Role เดียวทำทุกอย่าง

-- Role สำหรับแอปพลิเคชัน
CREATE ROLE app_role;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app_role;

-- Role สำหรับ backup
CREATE ROLE backup_role WITH LOGIN PASSWORD 'BackupPass!';
GRANT SELECT ON ALL TABLES IN SCHEMA public TO backup_role;

-- Role สำหรับ monitoring
CREATE ROLE monitor_role WITH LOGIN PASSWORD 'MonitorPass!';
GRANT SELECT ON pg_stat_activity TO monitor_role;
GRANT SELECT ON pg_stat_user_tables TO monitor_role;

-- Role สำหรับ migration
CREATE ROLE migration_role WITH LOGIN PASSWORD 'MigratePass!';
GRANT CREATE ON SCHEMA public TO migration_role;
GRANT ALL ON ALL TABLES IN SCHEMA public TO migration_role;

ใช้ Schema แยกข้อมูล

การใช้ Schema แยกข้อมูลช่วยจัดการสิทธิ์ได้สะดวกขึ้น โดยเฉพาะในระบบที่มีหลายทีมหรือหลายโมดูล

-- สร้าง schema แยกตามทีม
CREATE SCHEMA sales;
CREATE SCHEMA analytics;
CREATE SCHEMA internal;

-- กำหนดสิทธิ์ตาม schema
GRANT USAGE ON SCHEMA sales TO sales_team;
GRANT ALL ON ALL TABLES IN SCHEMA sales TO sales_team;

GRANT USAGE ON SCHEMA analytics TO data_team;
GRANT SELECT ON ALL TABLES IN SCHEMA analytics TO data_team;

-- ตั้ง search_path ให้แต่ละ role
ALTER ROLE sales_user SET search_path = sales, public;
ALTER ROLE analyst SET search_path = analytics, public;

Audit การใช้งาน

เปิด logging เพื่อตรวจสอบการใช้งานของผู้ใช้แต่ละคน ช่วยในการตรวจจับปัญหาและพฤติกรรมผิดปกติ

# postgresql.conf — Audit logging
log_connections = on
log_disconnections = on
log_statement = 'ddl'        # log เฉพาะ DDL (CREATE, ALTER, DROP)
log_line_prefix = '%t [%u@%d] '  # แสดง timestamp, user, database

# สำหรับ audit ละเอียดขึ้น ใช้ pgAudit extension
# shared_preload_libraries = 'pgaudit'
# pgaudit.log = 'write, ddl'
# pgaudit.log_relation = on

ตัวอย่างการตั้งค่าจริงสำหรับ Web Application

ด้านล่างเป็นตัวอย่างการตั้งค่าผู้ใช้และสิทธิ์แบบครบวงจรสำหรับเว็บแอปพลิเคชันที่มีฐานข้อมูลชื่อ webapp

-- ============================================
-- ตั้งค่า User Management สำหรับ Web Application
-- ============================================

-- 1. สร้างฐานข้อมูล
CREATE DATABASE webapp OWNER postgres;

-- 2. สร้าง Group Roles
CREATE ROLE web_readonly;
CREATE ROLE web_readwrite;
CREATE ROLE web_admin;

-- 3. กำหนดสิทธิ์ให้ Group Roles
\c webapp

-- readonly: อ่านได้อย่างเดียว
GRANT CONNECT ON DATABASE webapp TO web_readonly;
GRANT USAGE ON SCHEMA public TO web_readonly;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO web_readonly;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
    GRANT SELECT ON TABLES TO web_readonly;

-- readwrite: อ่าน-เขียนได้
GRANT CONNECT ON DATABASE webapp TO web_readwrite;
GRANT USAGE ON SCHEMA public TO web_readwrite;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO web_readwrite;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO web_readwrite;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
    GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO web_readwrite;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
    GRANT USAGE, SELECT ON SEQUENCES TO web_readwrite;

-- admin: ทุกสิทธิ์ + สร้าง/ลบตารางได้
GRANT CONNECT ON DATABASE webapp TO web_admin;
GRANT ALL ON SCHEMA public TO web_admin;
GRANT ALL ON ALL TABLES IN SCHEMA public TO web_admin;
GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO web_admin;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
    GRANT ALL ON TABLES TO web_admin;

-- 4. สร้าง User และเพิ่มเข้า Group
CREATE USER web_app WITH PASSWORD 'WebApp2026!';
GRANT web_readwrite TO web_app;

CREATE USER web_report WITH PASSWORD 'Report2026!';
GRANT web_readonly TO web_report;

CREATE USER web_migrate WITH PASSWORD 'Migrate2026!';
GRANT web_admin TO web_migrate;

-- 5. กำหนด connection limits
ALTER ROLE web_app CONNECTION LIMIT 20;
ALTER ROLE web_report CONNECTION LIMIT 5;
ALTER ROLE web_migrate CONNECTION LIMIT 2;

-- 6. กำหนด timeout
ALTER ROLE web_report SET statement_timeout = '60s';
ALTER ROLE web_app SET statement_timeout = '30s';

สรุป

การจัดการผู้ใช้ใน PostgreSQL อาศัยระบบ Role-Based Access Control ที่ยืดหยุ่น สามารถกำหนดสิทธิ์ได้ตั้งแต่ระดับฐานข้อมูล Schema ตาราง คอลัมน์ ไปจนถึงระดับแถวด้วย Row-Level Security การใช้ Group Role ร่วมกับ Default Privileges ช่วยให้การจัดการสิทธิ์เป็นระบบและดูแลรักษาง่าย

หลักสำคัญคือยึดแนวทาง Least Privilege มอบสิทธิ์เท่าที่จำเป็น แยก Role ตามหน้าที่ใช้งาน และเปิด Audit Logging เพื่อตรวจสอบย้อนหลัง เมื่อปฏิบัติตามแนวทางเหล่านี้อย่างสม่ำเสมอ จะช่วยให้ระบบฐานข้อมูลมีความปลอดภัยสูงและจัดการได้อย่างมีประสิทธิภาพ

แนะนำบริการ DE

การจัดการผู้ใช้และสิทธิ์ในฐานข้อมูลต้องอาศัยเซิร์ฟเวอร์ที่ให้คุณควบคุมได้เต็มที่ ตั้งแต่การแก้ไข pg_hba.conf ไปจนถึงการติดตั้ง Extension สำหรับ Audit Cloud VPS ของ DE รองรับการติดตั้งและตั้งค่าฐานข้อมูลได้อย่างอิสระ พร้อม root access เต็มรูปแบบ เหมาะสำหรับงาน Production ที่ต้องการความปลอดภัยสูง

สำหรับผู้ที่ต้องการโฮสต์เว็บแอปพลิเคชันที่เชื่อมต่อกับฐานข้อมูลโดยไม่ต้องดูแลเซิร์ฟเวอร์เอง Cloud Hosting ของ DE เป็นทางเลือกที่สะดวก มีระบบจัดการฐานข้อมูลผ่าน Control Panel ใช้งานง่ายและพร้อมรองรับเว็บไซต์ได้ทันที