აპლიკაციების უმეტესობა PostgreSQL-ს superuser-ად უკავშირდება, რადგან ეს არის პაროლი, რომელიც ჰოსტმა გადმოგცა და ის მუშაობს. მუშაობს იმ დღემდე, როცა bug-ი, ჩაშენებული query ან დაღლილი ადამიანი ტერმინალთან გააკეთებს რამეს, რაც აპლიკაციას არასოდეს უნდა შეძლებოდა: ცხრილის წაშლა, სხვა tenant-ის მწკრივების წაკითხვა ან პარამეტრის გამორთვა, რომელიც სერვერს იცავს. ყველაზე მცირე პრივილეგია აქ პარანოია არ არის, ის დაახლოებით ათი წუთის SQL-ია, და ეს პოსტი სწორედ ეს SQL-ია პლუს მოდელის ის ნაწილები, რომლებიც მას გამძლეს ხდის.
მოკლე ვერსია: შექმენი როლი, რომელიც სქემას ფლობს და მიგრაციებს ატარებს, როლი, რომლითაც აპლიკაცია შედის მხოლოდ მონაცემთა უფლებებით, და მხოლოდ წასაკითხი როლი შენთვის და შენი რეპორტინგის ინსტრუმენტებისთვის. გააუქმე ის, რასაც PostgreSQL ყველას ნაგულისხმევად აძლევს. შემდეგ დააყენე ნაგულისხმევი პრივილეგიები, რადგან მათ გარეშე შემდეგი მიგრაცია ცხრილებს შექმნის, რომლებსაც შენი აპლიკაცია ვერ წაიკითხავს.
როლები ერთდროულად მომხმარებლებიც არის და ჯგუფებიც#
PostgreSQL-ს ერთი ცნება აქვს იქ, სადაც სხვა სისტემებს ორი. როლს შეუძლია შესვლა, პრივილეგიების ფლობა და სხვა როლების შემცველობა. CREATE USER არის CREATE ROLE ... LOGIN სხვა მართლწერით და მათ სხვა არაფერი გამოარჩევს.
CREATE ROLE app_owner NOLOGIN;CREATE ROLE app LOGIN PASSWORD 'generated-not-chosen';CREATE ROLE readonly LOGIN PASSWORD 'also-generated' CONNECTION LIMIT 3;GRANT app_owner TO app; -- only if you want app to act as the ownerატრიბუტები, რომლებიც როლს შეიძლება ჰქონდეს, ცოტაა და თითოეული გადაწყვეტილებაა:
| ატრიბუტი | ნაგულისხმევი | რას უშვებს |
|---|---|---|
LOGIN | გამორთული | საერთოდ დაკავშირებას. ჯგუფურ როლებს არ სჭირდებათ |
SUPERUSER | გამორთული | ყველაფერს, ყველა უფლების შემოწმების გვერდის ავლით |
CREATEDB | გამორთული | ბაზების შექმნას |
CREATEROLE | გამორთული | სხვა როლების შექმნასა და შეცვლას |
REPLICATION | გამორთული | streaming replication-სა და base backup-ებს |
BYPASSRLS | გამორთული | row-level security პოლიტიკების იგნორირებას |
INHERIT | ჩართული | იმ როლების უფლებების ავტომატურ გამოყენებას, რომლებსაც ეკუთვნის |
CONNECTION LIMIT | -1 | ამ როლის ერთდროული კავშირების ზღვარს |
VALID UNTIL | არასოდეს | პაროლის ვადის გასვლის თარიღს |
INHERIT ის არის, რაზეც ღირს ფიქრი. ჩართულთან ჯგუფის წევრს ჯგუფის უფლებები აქვს კავშირის დამყარებისთანავე. NOINHERIT-თან ის უნდა ითხოვდეს: SET ROLE app_owner;. ეს დამატებითი ნაბიჯი კარგი ღვედია ადამიანის ანგარიშისთვის, რომელსაც ხანდახან მიგრაციის გაშვება სჭირდება, რადგან სახიფათო უფლებები შემთხვევით არ არის აქტიური.
\du psql-ში მთელ სურათს ბეჭდავს: ყველა როლს, მის ატრიბუტებს და წევრობებს. ეს პირველი ბრძანებაა, რომელიც უნდა გაუშვა ბაზაზე, რომელიც სხვისგან მიიღე.
ერთი შენიშვნა ვერსიებზე: PostgreSQL 16-მა გააძლიერა, რისი გაკეთებაც CREATEROLE-ს შეუძლია, ამიტომ მას აღარ შეუძლია თვითნებურ როლებში წევრობის გაცემა, რომლებსაც არ ადმინისტრირებს. თუ თვითმომსახურე მომხმარებლის შექმნის ნაკადი ძველ ქცევაზე ააგე, შეამოწმე შენს ვერსიაზე და ნუ დაეყრდნობი ვარაუდს.
რას გასცემს ახალი ბაზა#
ახალი ბაზა უფლებებისგან ცარიელი არ არის. PostgreSQL-ს აქვს ფსევდო-როლი სახელით PUBLIC, რომელსაც ყველა როლი იმპლიციტურად ეკუთვნის და რომლის წაშლაც არ შეიძლება, და ნაგულისხმევად PUBLIC უფრო მეტს ფლობს, ვიდრე ადამიანები ელიან:
CONNECTბაზაზე, ამიტომ ნებისმიერ როლს, რომელსაც ავთენტიფიკაცია შეუძლია, მისი გახსნა შეუძლია.TEMP, ამიტომ შეუძლია დროებითი ცხრილების შექმნა.USAGEpublicსქემაზე, ამიტომ შეუძლია დაინახოს, რა არის იქ.EXECUTEფუნქციებზე, მათ შორის იმათზე, რომლებიც შენმა extension-ებმა დააყენა.
PostgreSQL 15-მდე PUBLIC-ს ასევე ჰქონდა CREATE public სქემაზე, რაც ნიშნავდა, რომ ნებისმიერ როლს, რომელსაც დაკავშირება შეეძლო, მასში ცხრილების შექმნა შეეძლო. 15-ში ეს შეიცვალა: public სქემას ახლა pg_database_owner ფლობს და CREATE PUBLIC-ს არ ეძლევა. ეს ამ სფეროში ვერსიაზე დამოკიდებული ყველაზე გავრცელებული სიურპრიზია, ორივე მიმართულებით. 15-სა და უფრო ახალზე მიიღებ permission denied for schema public-ს, როცა მიგრაცია როლით გადის, რომელიც მფლობელი არ არის. 14-სა და უფრო ძველზე აღმოაჩენ, რომ მხოლოდ წასაკითხ როლს მაინც შეუძლია ცხრილების შექმნა.
უფსკრული ცხადად დახურე, ნებისმიერ ვერსიაზე:
REVOKE ALL ON DATABASE shop FROM PUBLIC;REVOKE ALL ON SCHEMA public FROM PUBLIC;GRANT CONNECT ON DATABASE shop TO app, readonly;გააკეთე ეს აპლიკაციის როლების შექმნამდე და დაიწყებ უარყოფიდან და არა ნაგულისხმევიდან, რომელიც უნდა გახსოვდეს.
ყველაზე მცირე პრივილეგიის კონფიგურაცია სრულად#
სამი როლი, ერთი სქემა, ერთხელ გასაშვები superuser-ით ან ბაზის მფლობელით. შეცვალე სახელები; მთავარია ფორმა.
-- 1. The owner. Owns every object, runs migrations, never logs in from the app.CREATE ROLE shop_owner NOLOGIN;ALTER DATABASE shop OWNER TO shop_owner;CREATE SCHEMA IF NOT EXISTS app AUTHORIZATION shop_owner;-- 2. The application. Reads and writes rows, changes nothing structural.CREATE ROLE shop_app LOGIN PASSWORD 'from-a-password-manager';GRANT CONNECT ON DATABASE shop TO shop_app;GRANT USAGE ON SCHEMA app TO shop_app;GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA app TO shop_app;GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA app TO shop_app;-- 3. Reporting and humans. Reads, and only reads.CREATE ROLE shop_read LOGIN PASSWORD 'a-different-one' CONNECTION LIMIT 3;GRANT CONNECT ON DATABASE shop TO shop_read;GRANT USAGE ON SCHEMA app TO shop_read;GRANT SELECT ON ALL TABLES IN SCHEMA app TO shop_read;იქ ოთხი რამ განზრახაა და ღირს ახსნად.
აპლიკაციის როლი მფლობელი არ არის. GRANT SELECT, INSERT, UPDATE, DELETE არ არის იგივე, რაც ცხრილის ფლობა: მფლობელს შეუძლია მისი ALTER და DROP, და ამას არც ერთი GRANT არ გასცემს. აპლიკაციის როლიდან ჩაშენებული DROP TABLE orders უფლების შეცდომით ვარდება და შენს საღამოს არ ანგრევს.
მიგრაციის როლი ცალკეა. შენი მიგრაციის ინსტრუმენტი უკავშირდება როგორც shop_owner (ან როგორც login როლი, რომელიც მისი წევრია) სხვა პაროლით, რომელსაც deploy job იყენებს და არა მოთხოვნის handler-ები. სწორედ ამიტომ არის expand-and-contract ხერხი სქემის მიგრაციები გათიშვის გარეშე-ში ავტომატიზაციისთვის უსაფრთხო.
Sequence-ები ცალკე გაიცემა. serial სვეტი sequence-ზე nextval-ს იძახებს, და როლი, რომელსაც ცხრილზე INSERT აქვს, sequence-ზე კი არაფერი, პირველ insert-ზე იღებს permission denied for sequence orders_id_seq-ს. Identity სვეტები (GENERATED ... AS IDENTITY) სხვანაირად იქცევა, ამიტომ გაუშვი ერთი insert აპლიკაციის როლით და დარწმუნდი, და არ დაეყრდნო ვარაუდს არც ერთი მიმართულებით.
`ALL TABLES IN SCHEMA` ნიშნავს ყველა ცხრილს, რომელიც ახლა არსებობს. ეს ციკლია დღევანდელ ობიექტებზე და არა მუდმივი წესი. რაც მიგვიყვანს ნაბიჯამდე, რომელიც მთელ ამას გამძლეს ხდის.
ნაგულისხმევი პრივილეგიები: ნაბიჯი, რომელიც ყველას გამოეპარება#
როლების დაყენების შემდეგ პირველი მიგრაცია ქმნის ცხრილს, აპლიკაცია ამბობს permission denied for table invoices, და ვიღაც GRANT-ს ხელით ხელახლა უშვებს. მერე ეს შემდეგ თვეს ისევ ხდება. ALTER DEFAULT PRIVILEGES არის გამოსავალი:
ALTER DEFAULT PRIVILEGES FOR ROLE shop_owner IN SCHEMA app GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO shop_app;ALTER DEFAULT PRIVILEGES FOR ROLE shop_owner IN SCHEMA app GRANT USAGE, SELECT ON SEQUENCES TO shop_app;ALTER DEFAULT PRIVILEGES FOR ROLE shop_owner IN SCHEMA app GRANT SELECT ON TABLES TO shop_read;ხაფანგი FOR ROLE-შია. ნაგულისხმევი პრივილეგიები მიება როლს, რომელიც ობიექტს ქმნის, და არა სქემას საერთოდ. თუ მათ shop_owner-ისთვის დააყენებ და მერე მიგრაციას superuser-ით გაუშვებ, ახალი ცხრილი მათგან არაფერს მიიღებს. რომელი როლითაც შენი მიგრაციები გადის, ის არის როლი FOR ROLE პუნქტში, და ის ყოველთვის ერთი და იგივე უნდა იყოს.
\ddp psql-ში ბეჭდავს ამჟამად მოქმედ ნაგულისხმევ პრივილეგიებს, რაც ყველაზე სწრაფი გზაა დასადასტურებლად, რომ სწორ როლს მიაბი.
სქემები და search path#
სქემა არის ცხრილების namespace და ის ასევე უფლებების ბუნებრივი საზღვარია. GRANT USAGE ON SCHEMA არის კარიბჭე: მის გარეშე შიგნით არსებულ არც ერთ ცხრილზე პრივილეგია მისაწვდომი არ არის.
search_path წყვეტს, რომელ სქემაზე გადაწყდება ცხრილის კვალიფიკაციის გარეშე სახელი. მისი ნაგულისხმევია "$user", public, ანუ დაკავშირებული როლის სახელის მქონე სქემა, თუ არსებობს, შემდეგ public. დააყენე როლზე, რომ აპლიკაციას ყველა სახელის კვალიფიცირება არ დასჭირდეს:
ALTER ROLE shop_app SET search_path = app, public;ALTER ROLE shop_app SET statement_timeout = '30s';ALTER ROLE shop_read SET statement_timeout = '120s';ბოლო ორი ხაზი ღირს ჯაფად პატარა სერვერზე. როლის დონის statement_timeout ნიშნავს, რომ გაუკონტროლებელ რეპორტს კავშირის საათობით შენახვა არ შეუძლია, და ის მოქმედებს აპლიკაციის კოდის ერთი ხაზის შეხების გარეშე. ამ ოჯახის სხვა პარამეტრები PostgreSQL-ის ტიუნინგი პატარა სერვერებისთვის-შია.
search_path-ს უსაფრთხოების მხარეც აქვს. SECURITY DEFINER ფუნქცია, რომელიც ცხრილის კვალიფიკაციის გარეშე სახელს იძახებს, მას გამომძახებლის search_path-ით გადაწყვეტს, რაც გამომძახებელს საშუალებას აძლევს, ის მის მიერ კონტროლირებად ცხრილზე მიუთითოს. ასეთ ფუნქციებზე გზა ყოველთვის ცხადად დააყენე:
CREATE FUNCTION app.recalc_totals() RETURNS void LANGUAGE sql SECURITY DEFINER SET search_path = app, pg_tempAS $$ UPDATE app.orders SET total = ... $$;ჩაშენებული როლები, რომლებიც უნდა იცოდე#
PostgreSQL-ს მოჰყვება წინასწარ განსაზღვრული როლების ნაკრები, რათა გავრცელებულ საქმეებს superuser არ სჭირდებოდეს. ერთ-ერთის ადამიანის ანგარიშზე გაცემა თითქმის ყოველთვის სჯობს SUPERUSER-ის გაცემას.
| როლი | რას იძლევა | ვერსიიდან |
|---|---|---|
pg_read_all_data | SELECT ყველა სქემის ყველა ცხრილზე | 14 |
pg_write_all_data | INSERT, UPDATE, DELETE ყველგან | 14 |
pg_monitor | მონიტორინგის view-ებსა და სტატისტიკის ფუნქციებს | 10 |
pg_read_all_settings | პარამეტრების წაკითხვას, რომლებიც ჩვეულებრივ არა-superuser-ებს უმალავს | 10 |
pg_signal_backend | სხვა სესიების გაუქმებასა და შეწყვეტას | 9.6 |
pg_checkpoint | CHECKPOINT-ის გაშვებას | 15 |
pg_maintain | VACUUM, ANALYZE, REINDEX, CLUSTER ნებისმიერ ცხრილზე | 17 |
pg_monitor პლუს pg_signal_backend თითქმის ყველაფერს ფარავს, რაც on-call ადამიანს გაჭედილი ბაზის დიაგნოსტიკისთვის სჭირდება, და არც ერთს კლიენტის მონაცემების ერთი მწკრივის წაკითხვა არ შეუძლია. pg_read_all_data ანალიტიკოსისთვის ყველაფერზე წვდომის გაცემის პატიოსანი გზაა, მისი შეცვლის უნარის გარეშე.
Row-level security და როდის ღირს ის#
ცხრილის დონის grant-ები ამბობს, ვის შეუძლია ცხრილის წაკითხვა. row-level security ამბობს, რომელი მწკრივების. ეს სწორი ინსტრუმენტია multi-tenant მონაცემებისთვის, სადაც ერთი შეცდომით დაწერილი WHERE პირობა სხვა კლიენტის ჩანაწერებს გაჟონავდა.
ALTER TABLE app.orders ENABLE ROW LEVEL SECURITY;CREATE POLICY tenant_isolation ON app.orders USING (tenant_id = current_setting('app.tenant_id', true)::uuid);GRANT SELECT, INSERT, UPDATE, DELETE ON app.orders TO shop_app;აპლიკაცია შემდეგ tenant-ს ერთხელ ტრანზაქციაზე ადგენს და ყოველი query ფილტრდება, გახსოვდა თუ არა მისი დაფილტვრა:
BEGIN;SET LOCAL app.tenant_id = '9f1c...';SELECT * FROM app.orders; -- only this tenant's rows, alwaysCOMMIT;სამი გაფრთხილება წყვეტს, კარგი იდეაა თუ არა ეს შენთვის. RLS-ის ჩართვა პოლიტიკის გარეშე ყველაფერს კრძალავს, რაც უსაფრთხო ნაგულისხმევია და დამაბნეველი პირველი ხუთი წუთი. ცხრილის მფლობელზე საკუთარი პოლიტიკები არ ვრცელდება, თუ FORCE ROW LEVEL SECURITY არ დაამატე, ამიტომ ტესტირება აპლიკაციის როლით გააკეთე და არა მფლობელით. და superuser-ები და ნებისმიერი როლი BYPASSRLS-ით პოლიტიკებს საერთოდ უგულებელყოფენ, რაც კიდევ ერთი მიზეზია, რატომაც აპლიკაცია superuser არ უნდა იყოს.
ფასი არსებობს: პოლიტიკის გამოსახულება ყოველ query-ს ემატება, ამიტომ დააინდექსე სვეტი, რომელზეც პოლიტიკა ფილტრავს. ამის გარდა წარმადობის კითხვა ჩვეულებრივია და განხილულია PostgreSQL-ის ინდექსები ახსნილი-ში.
რა გასცე, როგორ შეამოწმო და უკან წაიღო#
უფლებები დრეიფობს. შეამოწმე ისე, როგორც ყველაფერს სხვას, query-ით და არა მეხსიერებით.
-- Who can do what to a table\dp app.orders-- Every table privilege held by one roleSELECT table_schema, table_name, privilege_typeFROM information_schema.role_table_grantsWHERE grantee = 'shop_app'ORDER BY table_schema, table_name;-- A direct questionSELECT has_table_privilege('shop_app', 'app.orders', 'DELETE');\dp-ის გამოტანაში პრივილეგიები ასოებია: r SELECT-ისთვის, a INSERT-ისთვის, w UPDATE-ისთვის, d DELETE-ისთვის, D TRUNCATE-ისთვის, x REFERENCES-ისთვის, t TRIGGER-ისთვის. ჩანაწერი =r/shop_owner ნიშნავს, რომ PUBLIC-ს აქვს SELECT, გაცემული shop_owner-ის მიერ, და ჩვეულებრივ ის არის, რაც უნდა გააუქმო.
როლის წაშლა ის ადგილია, სადაც ხალხი ებმევა. DROP ROLE ვარდება, სანამ როლი რამეს ფლობს ან რაიმე პრივილეგია აქვს, შეტყობინებით, რომელიც დამოკიდებულ ობიექტებს ჩამოთვლის. თანმიმდევრობა ასეთია:
REASSIGN OWNED BY old_role TO shop_owner;DROP OWNED BY old_role;DROP ROLE old_role;REASSIGN OWNED BY ობიექტების საკუთრებას გადასცემს; DROP OWNED BY დარჩენილ grant-ებს შლის. ორივე მხოლოდ მიმდინარე ბაზაზე მოქმედებს, ამიტომ გაუშვი ისინი ყველა ბაზაში, რომელსაც როლი შეეხო, სანამ ბოლო DROP ROLE-ს გაუშვებ, რომელიც მთელ კლასტერზე მოქმედებს.
როტაციისთვის შეცვალე პაროლი და არა როლი. psql-ში გამოიყენე \password shop_app: ის გეკითხება, პაროლს შენს მანქანაზე ჰეშავს და მხოლოდ ჰეშს აგზავნის, ამიტომ ღია ტექსტი სერვერის ლოგამდე ან შენი shell-ის ისტორიამდე არასოდეს აღწევს. ALTER ROLE shop_app PASSWORD 'literal' საპირისპიროს აკეთებს.
ორი RE:NODE-სპეციფიკური შენიშვნა, რადგან ორი ფენა ერთმანეთში ირევა. ბაზის superuser-ის პაროლი თითოეული სერვერისთვის გენერირდება და ის შენია; ზემოთ მოცემული როლები კი ის რამეებია, რასაც ამ ბაზის შიგნით ქმნი და პანელმა მათ შესახებ არაფერი იცის. პანელზე წვდომა ცალკეა: subuser-ები, როლები და გუნდები განსაზღვრავს, ვის შეუძლია კონსოლის გახსნა, ფაილების შეხება ან backup-ის გაკეთება, და ადამიანს შეიძლება ერთი ჰქონდეს მეორის გარეშე. თანაგუნდელს მიეცი პანელის subuser საჭირო უფლებებით და ბაზის როლი საჭირო მწკრივებით, და ეს ორი განსხვავებულ კითხვად მიიჩნიე. Subuser-ები და ყველაზე მცირე პრივილეგია პანელის მხარეს ფარავს, ხოლო ბაზის უსაფრთხოების checklist - დანარჩენს.
უფლებების შეცდომები, რომლებსაც რეალურად შეხვდები#
PostgreSQL-ის შეტყობინებები ზუსტია, როგორც კი იცი, რომელი ფენიდან მოდის. ეს ისინია, ვინც დაკარგული შუადღეების უმეტესობას იწვევს.
`permission denied for schema public` - თითქმის ყოველთვის PostgreSQL 15 ან უფრო ახალია, სადაც PUBLIC-ს ამ სქემაზე CREATE აღარ აქვს. როლი, რომელიც მიგრაციას ატარებს, სქემის მფლობელი არ არის. ან გაუშვი მიგრაციები მფლობელით, ან GRANT CREATE ON SCHEMA public TO shop_owner, ან გადაიტანე შენი ცხრილები საკუთარ სქემაში, რაც ისედაც მოწესრიგებულია.
`permission denied for table orders` - სამი კანდიდატი, ალბათობის მიხედვით: grant ამ ცხრილზე არასოდეს გაცემულა, რადგან ის GRANT ... ON ALL TABLES-ის გაშვების შემდეგ შეიქმნა; როლი სხვა სქემას კითხულობს, ვიდრე ფიქრობ, ამიტომ შეამოწმე SHOW search_path; ან grant არასწორ როლს გასცი და ვერავინ შეამჩნია, რადგან superuser მუშაობას აგრძელებდა.
`permission denied for sequence orders_id_seq` - insert-ის გზა. გასცი USAGE, SELECT ON ALL SEQUENCES IN SCHEMA app და დაამატე შესაბამისი ნაგულისხმევი პრივილეგია.
`must be owner of table orders` - როლი ცდილობს ALTER-ს, DROP-ს, ინდექსის ან შეზღუდვის დამატებას. საკუთრება პრივილეგია არ არის, რომლის გაცემაც შეიძლება; ის გადაიცემა ALTER TABLE ... OWNER TO-თი. ეს შეცდომა ნიშნავს, რომ შენი მიგრაცია აპლიკაციის როლით გადის, რაც სწორედ განცალკევებაა, რომელიც ისე მუშაობს, როგორც გათვლილია.
`must be superuser to execute ALTER SYSTEM` და მსგავსი - სერვერის დონის კონფიგურაცია. გაითვალისწინე, რომ CREATE EXTENSION ყოველთვის ამ კატეგორიაში არ არის: PostgreSQL 13-დან extension-ების ნაკრები trusted-ად არის მონიშნული და ბაზის მფლობელს მათი superuser-ის გარეშე დაყენება შეუძლია.
query, რომელიც ნულ მწკრივს აბრუნებს შეცდომის გარეშე - თუ ცხრილზე row-level security ჩართულია, პოლიტიკა, რომელიც არ ემთხვევა, შეცდომა არ არის, ის ცარიელი შედეგია. შეამოწმე pg_policies და დარწმუნდი, რომ სესიის ცვლადი, რომელსაც შენი პოლიტიკა კითხულობს, მართლა დაყენებულია.
`role "old_app" cannot be dropped because some objects depend on it` - ზემოთ მოცემული REASSIGN OWNED BY და DROP OWNED BY თანმიმდევრობა, ყველა ბაზაში, რომელსაც როლი შეეხო.
`no pg_hba.conf entry for host ...` - საერთოდ არ არის უფლებების პრობლემა. ეს host-based ავთენტიფიკაცია უარყოფს კავშირს ისე, რომ როლის პრივილეგია არც კი გამოკითხულა, და ის სხვა ფაილში სწორდება. PostgreSQL-ის დისტანციური კავშირები ამ ფენას გადის.
FAQ#
რა განსხვავებაა როლსა და მომხმარებელს შორის PostgreSQL-ში?
არაფერი, მართლწერის გარდა. CREATE USER არის მოკლე ჩანაწერი CREATE ROLE ... LOGIN-ისთვის. როლს LOGIN-ით შეუძლია დაკავშირება; როლი მის გარეშე გამოიყენება როგორც ჯგუფი ან როგორც მფლობელი, რომლითაც არავინ შედის.
რატომ იღებს ჩემი აპი "permission denied"-ს მხოლოდ ახალ ცხრილებზე?
იმიტომ, რომ GRANT ... ON ALL TABLES IN SCHEMA იმ ცხრილებზე გავრცელდა, რომლებიც არსებობდა მისი გაშვებისას. დააყენე ALTER DEFAULT PRIVILEGES FOR ROLE <როლი, რომლითაც შენი მიგრაციები გადის>, რომ მომავალ ცხრილებს grant ავტომატურად ჰქონდეთ.
უნდა უკავშირდებოდეს თუ არა აპლიკაცია ბაზას მფლობელად?
არა. მფლობელს შეუძლია ყველა ობიექტის წაშლა და შეცვლა, და შენს აპლიკაციაში არაფერს ეს არ სჭირდება. მიგრაციის job უკავშირდეს მფლობელად, ხოლო მოთხოვნის handler-ები - როლით, რომელსაც მხოლოდ მონაცემთა უფლებები აქვს.
როგორ მივცე ვინმეს მხოლოდ წაკითხვის წვდომა უსაფრთხოდ?
შექმენი login როლი, მიეცი CONNECT ბაზაზე, USAGE სქემებზე, SELECT ცხრილებზე და დაამატე ნაგულისხმევი პრივილეგიები მომავალი ცხრილებისთვის. PostgreSQL 14-სა და უფრო ახალზე GRANT pg_read_all_data TO analyst იგივე საქმეს ერთ ხაზში აკეთებს ყველა სქემაზე.
მჭირდება თუ არა row-level security multi-tenant აპლიკაციისთვის?
ყოველთვის არა, მაგრამ ეს ერთადერთი მიდგომაა, რომელიც დავიწყებულ WHERE პირობას უძლებს. თუ tenant-ებს შორის გაჟონვა სერიოზული ინციდენტი იქნებოდა, ჩართე, ცხრილებზე დაამატე FORCE ROW LEVEL SECURITY და დააინდექსე tenant-ის სვეტი.
როგორ შევცვალო ბაზის პაროლი გათიშვის გარეშე?
შექმენი მეორე login როლი იგივე grant-ებით, გადაუშვი აპლიკაცია ახალი credential-ებით, დარწმუნდი, რომ pg_stat_activity-ში ძველით აღარავინ არის დაკავშირებული, მერე წაშალე. პაროლის ადგილზე შეცვლაც მუშაობს, მაგრამ ის არავის წყვეტს და ყველას ერთდროულად აკავშირებს თავიდან, რაც უარესი მომენტია შეცდომის აღმოსაჩენად.




კომენტარები
სრულიად ანონიმურად: ანგარიშის, ელფოსტის და cookie-ის გარეშე. ინახება მხოლოდ სახელი, ტექსტი და დრო - სხვა არაფერი. ბმულების რაოდენობა ლიმიტირებულია.