ทางเลือกของวิธีการรับรองความถูกต้องสำหรับแอพทางการเงินใน PostgreSQL


15

ก่อนอื่นให้พื้นหลัง

โครงการ LedgerSMB เป็นโครงการซอฟต์แวร์บัญชีการเงินที่ทำงานบน PostgreSQL เราใช้ตรรกะทางธุรกิจจำนวนมากในฟังก์ชั่นที่ผู้ใช้กำหนดซึ่งทำหน้าที่เป็นเครื่องมือการแมปหลักระหว่างวิธีการวัตถุของโปรแกรมและพฤติกรรมฐานข้อมูล ขณะนี้เราใช้ผู้ใช้ฐานข้อมูลเป็นผู้ใช้การพิสูจน์ตัวตนส่วนหนึ่งเป็นตัวเลือก (สิ่งนี้อนุญาตให้ตรรกะความปลอดภัยส่วนกลางเพื่อให้เครื่องมืออื่น ๆ สามารถเขียนและใช้สิทธิ์ที่ให้แก่ผู้ใช้) และอีกส่วนตามความจำเป็น (หลังจากเราแยกจาก SQL-Ledger ไม่มีตัวเลือกมากมายสำหรับการปรับเปลี่ยนการรักษาความปลอดภัยไปยัง codebase นั้น)

วิธีนี้ทำให้เราสามารถเข้าถึงตัวเลือกการลงชื่อเข้าใช้เพียงครั้งเดียวที่ PostgreSQL สามารถเข้าถึงได้ตั้งแต่ LDAP ไปจนถึง Kerberos 5. เราสามารถใช้ PAM ที่เกี่ยวข้องกับรหัสผ่าน นอกจากนี้ยังช่วยให้เราสามารถใช้สิทธิ์อีกครั้งเมื่อรวมกับแอปพลิเคชันอื่นหรืออนุญาตให้ส่วนต่อประสานลูกค้าอื่น ๆ สำหรับแอปพลิเคชันการบัญชีการเงินดูเหมือนว่าจะชนะสุทธิ

มีค่าใช้จ่ายที่เกี่ยวข้องอย่างชัดเจน สำหรับเว็บแอปพลิเคชันเรา จำกัด ประเภท http auth ที่สามารถรองรับได้มาก ตัวอย่างเช่น DIGEST นั้นหมดไปแล้ว การทำงานพื้นฐานและเราสามารถใช้ KRB5 ได้ง่ายพอ (ฉันวางแผนว่าจะให้การสนับสนุนและทำงานนอกกรอบสำหรับ 1.4) มาตรการการรับรองความถูกต้องที่แข็งแกร่งมากไม่สามารถจัดการได้อย่างถูกต้องโดยตรงแม้ว่าเราอาจจะสามารถกำหนดมาตรการเหล่านี้ได้ในกรณีที่จำเป็น (ตัวอย่างเช่นใบรับรอง SSL BASIC + ฝั่งไคลเอ็นต์ที่มี cn ที่ตรงกับชื่อผู้ใช้และรูท ca เฉพาะ)

ในขณะเดียวกันเราก็พบว่ามีการวิพากษ์วิจารณ์อย่างมากส่วนใหญ่มาจากกลุ่มพัฒนาและบางครั้งก็มากจาก dba ที่บอกว่าแอปพลิเคชั่นควรเป็นอุปสรรคด้านความปลอดภัยไม่ใช่ฐานข้อมูล มุมมองของฉันยังคงเป็นขอบเขตความปลอดภัยที่เล็กกว่าโดยทั่วไปดีกว่าการใช้ตรรกะทางธุรกิจและตรรกะความปลอดภัยกลับมารวมกันและมันทำให้ฉันเป็นอันตรายเมื่อต้องใช้ตรรกะทางธุรกิจอีกครั้งโดยไม่ต้องใช้ตรรกะความปลอดภัยในระดับเดียวกัน ของโปรแกรม

ฉันขาดการแลกเปลี่ยนที่สำคัญที่นี่หรือไม่? มี gotchas ที่ฉันไม่ได้พิจารณาหรือไม่?


1
ข้ามการโพสต์ไปยังรายชื่อผู้รับจดหมาย pgsql ทั่วไป ดูด้ายเริ่มต้นที่นี่
Craig Ringer

คำตอบ:


17

ฉันคิดว่าคุณกำลังคุยกัน การตรวจสอบและอนุมัติ

ฉันยอมรับอย่างสมบูรณ์ว่าการรักษารูปแบบความปลอดภัยในฐานข้อมูลนั้นฉลาดโดยเฉพาะอย่างยิ่ง LedgerSMB ได้รับการออกแบบโดยคำนึงถึงการเข้าถึงจากลูกค้าหลายราย ถ้าคุณวางแผนว่าจะไป 3 ชั้นมีชั้นตัวกลางก็จะทำให้สมบูรณ์แบบความรู้สึกที่มีผู้ใช้เป็นบทบาทของฐานข้อมูลโดยเฉพาะอย่างยิ่งบางอย่างเช่นแอปบัญชี

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

นี่คือวิธีการทำงานสำหรับ web UI

  • janeเชื่อมต่อกับเซิร์ฟเวอร์ web ui และรับรองความถูกต้องโดยใช้วิธีการใดก็ได้ที่ต้องการกล่าวว่าจับมือใบรับรองลูกค้า HTTPS X.509 และ DIGEST รับรองความถูกต้อง ตอนนี้เซิร์ฟเวอร์มีการเชื่อมต่อจากผู้ใช้ที่ยอมรับได้จริง ๆjane

  • เซิร์ฟเวอร์เชื่อมต่อกับ PostgreSQL โดยใช้ username / password คงที่ (หรือ Kerberos หรือสิ่งที่คุณต้องการ), webuiการตรวจสอบสิทธิ์ของตนเองไปยังเซิร์ฟเวอร์ฐานเป็นผู้ใช้ เซิร์ฟเวอร์ db เชื่อถือได้webuiเพื่อรับรองความถูกต้องของผู้ใช้ดังนั้นจึงwebuiได้รับGRANTs ที่เหมาะสม(ดูด้านล่าง)

  • ในการเชื่อมต่อที่เซิร์ฟเวอร์ที่ใช้จะถือว่าอยู่ในระดับที่ได้รับอนุญาตจากผู้ใช้SET ROLE jane; janeจนกว่าจะมีการเรียกใช้RESET ROLE;หรืออื่นSET ROLEการเชื่อมต่อจะทำงานโดยมีสิทธิ์การเข้าถึงเดียวกันกับjaneและSELECT current_user()ฯลฯ janeจะรายงาน

  • เซิร์ฟเวอร์รักษาการเชื่อมโยงระหว่างการเชื่อมต่อฐานข้อมูลที่มีSET ROLEกับjaneและเซสชันของเว็บสำหรับผู้ใช้janeไม่อนุญาตให้การเชื่อมต่อ PostgreSQL นั้นถูกใช้โดยการเชื่อมต่ออื่น ๆ กับผู้ใช้อื่นโดยไม่มีใหม่SET ROLE inbetween

ตอนนี้คุณกำลังตรวจสอบสิทธิ์ภายนอกเซิร์ฟเวอร์ แต่ทำการบำรุงรักษาสิทธิ์ในเซิร์ฟเวอร์ Pg จำเป็นต้องรู้ว่าผู้ใช้มีอยู่จริง แต่ไม่ต้องการรหัสผ่านหรือวิธีการตรวจสอบสิทธิ์สำหรับพวกเขา

ดู:

รายละเอียด

เซิร์ฟเวอร์ webui ควบคุมการสืบค้นที่เรียกใช้และจะไม่ปล่อยให้janeรัน SQL ดิบ (ฉันหวังว่า!) ดังนั้นจึงjaneไม่สามารถRESET ROLE; SET ROLE special_admin_user;ผ่านเว็บ UI ได้ เพื่อความปลอดภัยที่เพิ่มขึ้นฉันจะเพิ่มตัวกรองคำสั่งไปยังเซิร์ฟเวอร์ที่ปฏิเสธSET ROLEและRESET ROLEเว้นแต่ว่าการเชื่อมต่อนั้นอยู่ในหรือเข้าสู่กลุ่มการเชื่อมต่อที่ไม่ได้กำหนด

คุณยังสามารถใช้การรับรองความถูกต้องโดยตรงกับ Pg ในไคลเอนต์อื่น ๆ ได้ฟรี คุณสามารถผสมและจับคู่ได้อย่างอิสระ คุณเพียงแค่ต้องใช้สิทธิกับผู้ใช้ที่สามารถเข้าสู่ระบบผ่านทางเว็บและจากนั้นให้ผู้ใช้ปกติใด ๆสิทธิ, รหัสผ่าน, ฯลฯ ที่คุณต้องการ หากคุณต้องการทำให้เป็นเว็บเท่านั้นสิทธิ์ของพวกเขาในฐานข้อมูล (และจากGRANTwebuiSET ROLECONNECTREVOKECONNECTpublic )

ในการทำให้การรับรองความถูกต้อง / การอนุญาตแยกง่ายฉันมีบทบาทพิเศษassume_any_userที่ฉันGRANTทุกคนสร้างขึ้นใหม่เพื่อ ฉันGRANT assume_any_userชื่อผู้ใช้จริงที่ใช้โดยสิ่งต่าง ๆ เช่นส่วนหน้าเว็บที่เชื่อถือได้ให้สิทธิ์พวกเขาในการเป็นผู้ใช้ที่พวกเขาชอบ

เป็นสิ่งสำคัญที่จะต้องassume_any_userมีNOINHERITบทบาทดังนั้นwebuiผู้ใช้หรือสิ่งใดก็ตามที่ไม่มีสิทธิ์ของตนเองและสามารถดำเนินการกับฐานข้อมูลได้เมื่อSET ROLEมีการใช้งานจริง ภายใต้สถานการณ์ที่ไม่ควรwebuiจะเป็น superuser หรือเจ้าของ

หากคุณกำลังเชื่อมต่อร่วมกันคุณสามารถใช้SET LOCAL ROLEกับบทบาทชุดเฉพาะในการทำธุรกรรมเพื่อให้คุณสามารถกลับมาเชื่อมต่อกับสระว่ายน้ำหลังหรือCOMMIT ROLLBACKระวังว่าRESET ROLEยังใช้งานได้ดังนั้นจึงยังไม่ปลอดภัยที่จะให้ไคลเอนต์เรียกใช้ SQL ที่พวกเขาต้องการ

SET SESSION AUTHORIZATIONเป็นเวอร์ชันที่เกี่ยวข้อง แต่แข็งแกร่งกว่าของคำสั่งนี้ มันไม่จำเป็นต้องเป็นสมาชิกของบทบาท แต่เป็นคำสั่ง superuser เท่านั้น คุณไม่ต้องการให้ UI ของเว็บเชื่อมต่อเป็น superuser มันสามารถกลับด้วยRESET SESSION AUTHORIZATION, SET SESSION AUTHORIZATION DEFAULTหรือSET SESSION AUTHORIZATION theusernameจะฟื้นสิทธิ superuser จึงไม่เป็นอุปสรรคการรักษาความปลอดภัยสิทธิ์ลดลงอย่างใดอย่างหนึ่ง

คำสั่งที่ทำงานเหมือน SET SESSION AUTHORIZATIONแต่กลับไม่ได้และจะทำงานได้ถ้าคุณเป็นสมาชิกบทบาท แต่ไม่ใช่ superuser จะดีมาก ถึงตอนนี้ยังไม่มีสักเครื่อง แต่คุณยังสามารถแยกการพิสูจน์ตัวตนและการอนุญาตได้ดีถ้าคุณระวัง

ตัวอย่างและคำอธิบาย

CREATE ROLE dbowner NOLOGIN;
CREATE TABLE test_table(x text);
INSERT INTO test_table(x) VALUES ('bork');
ALTER TABLE test_table OWNER TO dbowner;

CREATE ROLE assume_any_user NOINHERIT NOLOGIN;
CREATE ROLE webui LOGIN PASSWORD 'somepw' IN ROLE assume_any_user;

CREATE ROLE jane LOGIN PASSWORD 'somepw';
GRANT jane TO assume_any_user;
GRANT ALL ON TABLE test_table TO jane;

CREATE ROLE jim LOGIN PASSWORD 'somepw';
GRANT jim TO assume_any_user;

webuiตอนนี้เชื่อมต่อเป็น โปรดทราบว่าคุณไม่สามารถทำอะไรให้test_tableแต่คุณสามารถ SET ROLEไปjaneและจากนั้นคุณสามารถเข้าถึงtest_table:

$ psql -h 127.0.0.1 -U webui regress
Password for user webui:

regress=> SELECT session_user, current_user;
 session_user | current_user 
--------------+--------------
 webui        | webui
(1 row)



regress=> SELECT * FROM test_table;
ERROR:  permission denied for relation test_table

regress=> SET ROLE jane;
SET

regress=> SELECT session_user, current_user;
 session_user | current_user 
--------------+--------------
 webui        | jane
(1 row)

regress=> SELECT * FROM test_table;
  x   
------
 bork
(1 row)

โปรดทราบว่าwebui สามารถ SET ROLEไปjimแม้ในขณะที่แล้วSET ROLEวันที่ไปjaneและแม้ว่าjaneยังไม่ได้รับการGRANTed jimสิทธิที่จะถือว่าบทบาท SET ROLEตั้งค่า ID ผู้ใช้ที่มีประสิทธิภาพของคุณ แต่ไม่ได้ลบความสามารถของคุณไปSET ROLEยังบทบาทอื่น ๆ นั่นเป็นคุณสมบัติของบทบาทที่คุณเชื่อมต่อไม่ใช่บทบาทที่มีประสิทธิภาพในปัจจุบันของคุณ ดังนั้นคุณต้องควบคุมการเข้าถึงคำสั่งSET ROLEและ RESET ROLEนั่นคือ AFAIK ไม่มีวิธีใดในSET ROLEการเชื่อมต่ออย่างถาวรกลายเป็นผู้ใช้เป้าหมายอย่างแท้จริงแม้ว่าจะเป็นสิ่งที่ดีจริงๆ

เปรียบเทียบ:

$ psql -h 127.0.0.1 -U webui regress
Password for user webui:

regress=> SET ROLE jane;
SET

regress=> SET ROLE jim;
SET
regress=> SELECT session_user, current_user;
 session_user | current_user 
--------------+--------------
 webui        | jim
(1 row)

ถึง:

$ psql -h 127.0.0.1 -U jane regress
Password for user jane:

regress=> SET ROLE webui;
ERROR:  permission denied to set role "webui"
regress=> SET ROLE jim;
ERROR:  permission denied to set role "jim"

ซึ่งหมายความว่าSET ROLEไม่เหมือนกับการเข้าสู่ระบบตามบทบาทที่กำหนดสิ่งที่คุณต้องจำไว้

webuiไม่สามารถSET ROLEที่จะdbownerเพราะมันไม่ได้รับการGRANTed ที่ขวา:

regress=> SET ROLE dbowner;
ERROR:  permission denied to set role "dbowner"

ดังนั้นโดยตัวของมันเองมันไม่มีพลังงานเลยมันสามารถรับสิทธิ์ของผู้ใช้รายอื่นได้และเมื่อผู้ใช้เหล่านั้นเปิดใช้งานการเข้าถึงเว็บ


1
btw คุณอาจต้องการดูวิธีการpgbouncerทำงานของรายละเอียดบางอย่าง
Craig Ringer

2
โอ้DISCARD ALLเป็นอีกวิธีหนึ่งที่สิทธิ์จะถูกยกเลิกกลับไปเป็นค่าเริ่มต้น ฉันหวังว่า Pg จะมีSET ROLE NORESETหรือคล้ายกัน ...
Craig Ringer
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.