5.9. ÐолиÑики заÑиÑÑ ÑÑÑок #
Рдополнение к ÑÑандаÑÑной ÑиÑÑеме пÑав SQL, ÑпÑавлÑемой командой GRANT, на ÑÑовне ÑÐ°Ð±Ð»Ð¸Ñ Ð¼Ð¾Ð¶Ð½Ð¾ опÑеделиÑÑ Ð¿Ð¾Ð»Ð¸Ñики заÑиÑÑ ÑÑÑок, огÑаниÑиваÑÑие Ð´Ð»Ñ Ð¿Ð¾Ð»ÑзоваÑелей набоÑÑ ÑÑÑок, коÑоÑÑе могÑÑ Ð±ÑÑÑ Ð²Ð¾Ð·Ð²ÑаÑÐµÐ½Ñ Ð¾Ð±ÑÑнÑми запÑоÑами или добавленÑ, Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ñ Ð¸ ÑÐ´Ð°Ð»ÐµÐ½Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð°Ð¼Ð¸, изменÑÑÑими даннÑе. ÐÑо назÑваеÑÑÑ Ñакже заÑиÑой на ÑÑовне ÑÑÑок (RLS, Row-Level Security). Ðо ÑмолÑÐ°Ð½Ð¸Ñ ÑаблиÑÑ Ð½Ðµ имеÑÑ Ð¿Ð¾Ð»Ð¸Ñик, Ñак ÑÑо еÑли ÑиÑÑема пÑав SQL ÑазÑеÑÐ°ÐµÑ Ð¿Ð¾Ð»ÑзоваÑÐµÐ»Ñ Ð´Ð¾ÑÑÑп к ÑаблиÑе, вÑе ÑÑÑоки в ней одинаково доÑÑÑÐ¿Ð½Ñ Ð´Ð»Ñ ÑÑÐµÐ½Ð¸Ñ Ð¸Ð»Ð¸ изменениÑ.
Ðогда Ð´Ð»Ñ ÑаблиÑÑ Ð²ÐºÐ»ÑÑаеÑÑÑ Ð·Ð°ÑиÑа ÑÑÑок (Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ ALTER TABLE ... ENABLE ROW LEVEL SECURITY), вÑе обÑÑнÑе запÑоÑÑ Ðº ÑаблиÑе на вÑбоÑÐºÑ Ð¸Ð»Ð¸ модиÑикаÑÐ¸Ñ ÑÑÑок Ð´Ð¾Ð»Ð¶Ð½Ñ ÑазÑеÑаÑÑÑÑ Ð¿Ð¾Ð»Ð¸Ñикой заÑиÑÑ ÑÑÑок. (Ðднако на владелÑÑа ÑаблиÑÑ Ñакие полиÑики обÑÑно не дейÑÑвÑÑÑ.) ÐÑли полиÑика Ð´Ð»Ñ ÑаблиÑÑ Ð½Ðµ опÑеделена, пÑименÑеÑÑÑ Ð¿Ð¾Ð»Ð¸Ñика запÑеÑа по ÑмолÑаниÑ, Ñак ÑÑо никакие ÑÑÑоки в ÑÑой ÑаблиÑе нелÑÐ·Ñ ÑвидеÑÑ Ð¸Ð»Ð¸ модиÑиÑиÑоваÑÑ. Ðа опеÑаÑии Ñ ÑаблиÑей в Ñелом, Ñакие как TRUNCATE и REFERENCES, заÑиÑа ÑÑÑок не ÑаÑпÑоÑÑÑанÑеÑÑÑ.
ÐолиÑики заÑиÑÑ ÑÑÑок могÑÑ Ð¿ÑименÑÑÑÑÑ Ðº опÑеделÑннÑм командам и/или ÑолÑм. ÐолиÑÐ¸ÐºÑ Ð¼Ð¾Ð¶Ð½Ð¾ опÑеделиÑÑ ÐºÐ°Ðº пÑименÑемÑÑ Ðº командам ALL (вÑем), либо SELECT, INSERT, UPDATE и DELETE. ÐÑоме Ñого, полиÑÐ¸ÐºÑ Ð¼Ð¾Ð¶Ð½Ð¾ ÑвÑзаÑÑ Ñ Ð½ÐµÑколÑкими ÑолÑми, пÑи ÑÑом дейÑÑвÑÑÑ Ð¾Ð±ÑÑнÑе пÑавила ÑленÑÑва и наÑледованиÑ.
ЧÑÐ¾Ð±Ñ Ð¾Ð¿ÑеделиÑÑ, какие ÑÑÑоки бÑдÑÑ Ð²Ð¸Ð´Ð¸Ð¼Ñми или могÑÑ Ð¸Ð·Ð¼ÐµÐ½ÑÑÑÑÑ Ð² ÑаблиÑе, Ð´Ð»Ñ Ð¿Ð¾Ð»Ð¸Ñики задаÑÑÑÑ Ð²ÑÑажение, возвÑаÑаÑÑее логиÑеÑкий ÑезÑлÑÑаÑ. ÐÑо вÑÑажение бÑÐ´ÐµÑ Ð²ÑÑиÑлÑÑÑÑÑ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ ÑÑÑоки пеÑед дÑÑгими ÑÑловиÑми или ÑÑнкÑиÑми, поÑÑÑпаÑÑими из запÑоÑа полÑзоваÑелÑ. (ÐдинÑÑвеннÑм иÑклÑÑением из ÑÑого пÑавила ÑвлÑÑÑÑÑ Ð³ÐµÑмеÑиÑнÑе ÑÑнкÑии, коÑоÑÑе гаÑанÑиÑованно не допÑÑкаÑÑ ÑÑеÑки инÑоÑмаÑии; опÑимизаÑÐ¾Ñ Ð¼Ð¾Ð¶ÐµÑ ÑеÑиÑÑ Ð²ÑполниÑÑ ÑÑи ÑÑнкÑии до пÑовеÑок заÑиÑÑ ÑÑÑок.) СÑÑоки, Ð´Ð»Ñ ÐºÐ¾ÑоÑÑÑ
ÑÑо вÑÑажение возвÑаÑÐ°ÐµÑ Ð½Ðµ true, обÑабаÑÑваÑÑÑÑ Ð½Ðµ бÑдÑÑ. ЧÑÐ¾Ð±Ñ Ð½ÐµÐ·Ð°Ð²Ð¸Ñимо ÑпÑавлÑÑÑ Ð½Ð°Ð±Ð¾Ñом ÑÑÑок, коÑоÑÑе можно видеÑÑ, и набоÑом ÑÑÑок, коÑоÑÑе можно модиÑиÑиÑоваÑÑ, в полиÑике можно задаÑÑ Ð¾ÑделÑнÑе вÑÑажениÑ. ÐÑÑÐ°Ð¶ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»Ð¸Ñик обÑабаÑÑваÑÑÑÑ Ð² ÑоÑÑаве запÑоÑа Ñ Ð¿Ñавами иÑполнÑÑÑего его полÑзоваÑелÑ, но Ð´Ð»Ñ Ð¾Ð±ÑаÑÐµÐ½Ð¸Ñ Ðº даннÑм, недоÑÑÑпнÑм ÑÑÐ¾Ð¼Ñ Ð¿Ð¾Ð»ÑзоваÑелÑ, в ÑÑиÑ
вÑÑажениÑÑ
могÑÑ Ð¿ÑименÑÑÑÑÑ ÑÑнкÑии, опÑеделÑÑÑие конÑекÑÑ Ð±ÐµÐ·Ð¾Ð¿Ð°ÑноÑÑи.
СÑпеÑполÑзоваÑели и Ñоли Ñ Ð°ÑÑибÑÑом BYPASSRLS вÑегда обÑаÑаÑÑÑÑ Ðº ÑаблиÑе, минÑÑ ÑиÑÑÐµÐ¼Ñ Ð·Ð°ÑиÑÑ ÑÑÑок. Ðа владелÑÑа ÑаблиÑÑ Ð·Ð°ÑиÑа ÑÑÑок Ñоже не дейÑÑвÑеÑ, Ñ
оÑÑ Ð¾Ð½ Ð¼Ð¾Ð¶ÐµÑ Ð²ÐºÐ»ÑÑиÑÑ ÐµÑ Ð´Ð»Ñ ÑÐµÐ±Ñ Ð¿ÑинÑдиÑелÑно, вÑполнив ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ ALTER TABLE ... FORCE ROW LEVEL SECURITY.
ÐеоÑÑемлемое пÑаво вклÑÑаÑÑ Ð¸Ð»Ð¸ оÑклÑÑаÑÑ Ð·Ð°ÑиÑÑ ÑÑÑок, а Ñакже опÑеделÑÑÑ Ð¿Ð¾Ð»Ð¸Ñики Ð´Ð»Ñ ÑаблиÑÑ, Ð¸Ð¼ÐµÐµÑ ÑолÑко ÐµÑ Ð²Ð»Ð°Ð´ÐµÐ»ÐµÑ.
ÐÐ»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¿Ð¾Ð»Ð¸Ñик пÑедназнаÑена команда CREATE POLICY, Ð´Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ â ALTER POLICY, а Ð´Ð»Ñ ÑÐ´Ð°Ð»ÐµÐ½Ð¸Ñ â DROP POLICY. ЧÑÐ¾Ð±Ñ Ð²ÐºÐ»ÑÑиÑÑ Ð¸Ð»Ð¸ оÑклÑÑиÑÑ Ð·Ð°ÑиÑÑ ÑÑÑок Ð´Ð»Ñ Ð¾Ð¿ÑеделÑнной ÑаблиÑÑ, воÑполÑзÑйÑеÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð¾Ð¹ ALTER TABLE.
Ðаждой полиÑике назнаÑаеÑÑÑ Ð¸Ð¼Ñ, пÑи ÑÑом Ð´Ð»Ñ Ð¾Ð´Ð½Ð¾Ð¹ ÑаблиÑÑ Ð¼Ð¾Ð¶Ð½Ð¾ опÑеделиÑÑ Ð½ÐµÑколÑко полиÑик. Так как полиÑики пÑивÑÐ·Ð°Ð½Ñ Ðº ÑаблиÑам, ÐºÐ°Ð¶Ð´Ð°Ñ Ð¿Ð¾Ð»Ð¸Ñика Ð´Ð»Ñ ÑаблиÑÑ Ð´Ð¾Ð»Ð¶Ð½Ð° имеÑÑ ÑникалÑное имÑ. Ð ÑазнÑÑ ÑаблиÑÐ°Ñ Ð¿Ð¾Ð»Ð¸Ñики могÑÑ Ð¸Ð¼ÐµÑÑ Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²Ñе имена.
Ðогда к опÑеделÑÐ½Ð½Ð¾Ð¼Ñ Ð·Ð°Ð¿ÑоÑÑ Ð¿ÑименÑÑÑÑÑ Ð½ÐµÑколÑко полиÑик, они обÑединÑÑÑÑÑ Ð»Ð¸Ð±Ð¾ логиÑеÑким Ñложением (еÑли полиÑики ÑазÑеÑиÑелÑнÑе (по ÑмолÑаниÑ)), либо Ñмножением (еÑли полиÑики огÑаниÑиÑелÑнÑе). Ðоведение OR подобно ÑомÑ, как некоÑоÑÐ°Ñ ÑÐ¾Ð»Ñ Ð¿Ð¾Ð»ÑÑÐ°ÐµÑ Ð¿Ñава вÑеÑ
Ñолей, в коÑоÑÑе она вклÑÑена. РазÑеÑиÑелÑнÑе и огÑаниÑиÑелÑнÑе полиÑики ÑаÑÑмаÑÑиваÑÑÑÑ Ð½Ð¸Ð¶Ðµ.
РкаÑеÑÑве пÑоÑÑого пÑимеÑа, ÑоздаÑÑ Ð¿Ð¾Ð»Ð¸ÑÐ¸ÐºÑ Ð´Ð»Ñ Ð¾ÑноÑÐµÐ½Ð¸Ñ account, позволÑÑÑÑÑ ÑолÑко Ñленам Ñоли managers обÑаÑаÑÑÑÑ Ðº ÑÑÑокам оÑноÑÐµÐ½Ð¸Ñ Ð¸ пÑи ÑÑом ÑолÑко к Ñвоим, можно Ñак:
CREATE TABLE accounts (manager text, company text, contact_email text);
ALTER TABLE accounts ENABLE ROW LEVEL SECURITY;
CREATE POLICY account_managers ON accounts TO managers
USING (manager = current_user);ÐÑа полиÑика неÑвно подÑазÑÐ¼ÐµÐ²Ð°ÐµÑ Ð¸ пÑедложение WITH CHECK, иденÑиÑное пÑÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ USING, поÑÑÐ¾Ð¼Ñ Ñказанное огÑаниÑение пÑименÑеÑÑÑ Ð¸ к ÑÑÑокам, вÑбиÑаемÑм командой (Ñак ÑÑо один Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑ Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ Ð²ÑполниÑÑ SELECT, UPDATE или DELETE Ð´Ð»Ñ ÑÑÑеÑÑвÑÑÑиÑ
ÑÑÑок, пÑинадлежаÑиÑ
дÑÑгомÑ), и к ÑÑÑокам, изменÑемÑм командой (Ñак ÑÑо командами INSERT и UPDATE нелÑÐ·Ñ ÑоздаÑÑ ÑÑÑоки, пÑинадлежаÑие дÑÑÐ³Ð¾Ð¼Ñ Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑÑ).
ÐÑли ÑÐ¾Ð»Ñ Ð½Ðµ задана, либо задано ÑпеÑиалÑное Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑзоваÑÐµÐ»Ñ PUBLIC, полиÑика пÑименÑеÑÑÑ ÐºÐ¾ вÑем полÑзоваÑелÑм в данной ÑиÑÑеме. ЧÑÐ¾Ð±Ñ Ð²Ñе полÑзоваÑели могли обÑаÑиÑÑÑÑ ÑолÑко к ÑобÑÑвенной ÑÑÑоке в ÑаблиÑе users, можно пÑимениÑÑ Ð¿ÑоÑÑÑÑ Ð¿Ð¾Ð»Ð¸ÑикÑ:
CREATE POLICY user_policy ON users
USING (user_name = current_user);ÐÑо ÑабоÑÐ°ÐµÑ Ð¿Ð¾Ð´Ð¾Ð±Ð½Ð¾ пÑедÑдÑÑÐµÐ¼Ñ Ð¿ÑимеÑÑ.
ЧÑÐ¾Ð±Ñ Ð¾Ð¿ÑеделиÑÑ Ð´Ð»Ñ ÑÑÑок, добавлÑемÑÑ
в ÑаблиÑÑ, оÑделÑнÑÑ Ð¿Ð¾Ð»Ð¸ÑикÑ, оÑлиÑнÑÑ Ð¾Ñ Ð¿Ð¾Ð»Ð¸Ñики, огÑаниÑиваÑÑей видимÑе ÑÑÑоки, можно ÑкомбиниÑоваÑÑ Ð½ÐµÑколÑко полиÑик. СледÑÑÑÐ°Ñ Ð¿Ð°Ñа полиÑик Ð¿Ð¾Ð·Ð²Ð¾Ð»Ð¸Ñ Ð²Ñем полÑзоваÑелÑм видеÑÑ Ð²Ñе ÑÑÑоки в ÑаблиÑе users, но изменÑÑÑ ÑолÑко ÑÐ²Ð¾Ñ ÑобÑÑвеннÑÑ:
CREATE POLICY user_sel_policy ON users
FOR SELECT
USING (true);
CREATE POLICY user_mod_policy ON users
USING (user_name = current_user);ÐÐ»Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ SELECT ÑÑи две полиÑики обÑединÑÑÑÑÑ Ð¾Ð¿ÐµÑаÑией OR, Ñак ÑÑо в иÑоге ÑÑо позволÑÐµÑ Ð²ÑбиÑаÑÑ Ð²Ñе ÑÑÑоки. ÐÐ»Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´ дÑÑгиÑ
Ñипов пÑименÑеÑÑÑ ÑолÑко вÑоÑÐ°Ñ Ð¿Ð¾Ð»Ð¸Ñика, и ÑÑÑÐµÐºÑ ÑÐ¾Ñ Ð¶Ðµ, ÑÑо и ÑанÑÑе.
ÐаÑиÑÑ ÑÑÑок можно оÑклÑÑиÑÑ Ñак же командой ALTER TABLE. ÐÑи оÑклÑÑении заÑиÑÑ, полиÑики, опÑеделÑннÑе Ð´Ð»Ñ ÑаблиÑÑ, не ÑдалÑÑÑÑÑ, а пÑоÑÑо игноÑиÑÑÑÑÑÑ. Ð ÑезÑлÑÑаÑе в ÑаблиÑе бÑдÑÑ Ð²Ð¸Ð´Ð½Ñ Ð¸ могÑÑ Ð¼Ð¾Ð´Ð¸ÑиÑиÑоваÑÑÑÑ Ð²Ñе ÑÑÑоки, Ñ ÑÑÑÑом огÑаниÑений ÑÑандаÑÑной ÑиÑÑÐµÐ¼Ñ Ð¿Ñав SQL.
Ðиже показан ÑазвÑÑнÑÑÑй пÑÐ¸Ð¼ÐµÑ Ñого, как ÑÑÐ¾Ñ Ð¼ÐµÑ
анизм заÑиÑÑ Ð¼Ð¾Ð¶Ð½Ð¾ пÑименÑÑÑ Ð² пÑоизводÑÑвенной ÑÑеде. ТаблиÑа passwd имиÑиÑÑÐµÑ Ñайл паÑолей в Unix:
-- ÐÑоÑÑой пÑÐ¸Ð¼ÐµÑ Ð½Ð° базе Ñайла passwd
CREATE TABLE passwd (
user_name text UNIQUE NOT NULL,
pwhash text,
uid int PRIMARY KEY,
gid int NOT NULL,
real_name text NOT NULL,
home_phone text,
extra_info text,
home_dir text NOT NULL,
shell text NOT NULL
);
CREATE ROLE admin; -- ÐдминиÑÑÑаÑоÑ
CREATE ROLE bob; -- ÐбÑÑнÑй полÑзоваÑелÑ
CREATE ROLE alice; -- ÐбÑÑнÑй полÑзоваÑелÑ
-- Ðаполнение ÑаблиÑÑ
INSERT INTO passwd VALUES
('admin','xxx',0,0,'Admin','111-222-3333',null,'/root','/bin/dash');
INSERT INTO passwd VALUES
('bob','xxx',1,1,'Bob','123-456-7890',null,'/home/bob','/bin/zsh');
INSERT INTO passwd VALUES
('alice','xxx',2,1,'Alice','098-765-4321',null,'/home/alice','/bin/zsh');
-- ÐеобÑ
одимо вклÑÑиÑÑ Ð´Ð»Ñ ÑÑой ÑаблиÑÑ Ð·Ð°ÑиÑÑ Ð½Ð° ÑÑовне ÑÑÑок
ALTER TABLE passwd ENABLE ROW LEVEL SECURITY;
-- Создание полиÑик
-- ÐдминиÑÑÑаÑÐ¾Ñ Ð¼Ð¾Ð¶ÐµÑ Ð²Ð¸Ð´ÐµÑÑ Ð¸ добавлÑÑÑ Ð»ÑбÑе ÑÑÑоки
CREATE POLICY admin_all ON passwd TO admin USING (true) WITH CHECK (true);
-- ÐбÑÑнÑе полÑзоваÑели могÑÑ Ð²Ð¸Ð´ÐµÑÑ Ð²Ñе ÑÑÑоки
CREATE POLICY all_view ON passwd FOR SELECT USING (true);
-- ÐбÑÑнÑе полÑзоваÑели могÑÑ Ð¸Ð·Ð¼ÐµÐ½ÑÑÑ ÑобÑÑвеннÑе даннÑе, но
-- не могÑÑ Ð·Ð°Ð´Ð°ÑÑ Ð¿ÑоизволÑнÑÑ Ð¾Ð±Ð¾Ð»Ð¾ÑÐºÑ Ð²Ñ
ода
CREATE POLICY user_mod ON passwd FOR UPDATE
USING (current_user = user_name)
WITH CHECK (
current_user = user_name AND
shell IN ('/bin/bash','/bin/sh','/bin/dash','/bin/zsh','/bin/tcsh')
);
-- ÐдминиÑÑÑаÑоÑÑ Ð¿Ð¾Ð»ÑÑаÑÑ Ð²Ñе обÑÑнÑе пÑава
GRANT SELECT, INSERT, UPDATE, DELETE ON passwd TO admin;
-- ÐолÑзоваÑелÑм ÑазÑеÑаеÑÑÑ ÑÑение ÑолÑко обÑедоÑÑÑпнÑÑ
ÑÑолбÑов
GRANT SELECT
(user_name, uid, gid, real_name, home_phone, extra_info, home_dir, shell)
ON passwd TO public;
-- ÐолÑзоваÑелÑм ÑазÑеÑаеÑÑÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ðµ опÑеделÑннÑÑ
ÑÑолбÑов
GRANT UPDATE
(pwhash, real_name, home_phone, extra_info, shell)
ON passwd TO public;Ðак и лÑбÑе ÑÑедÑÑва заÑиÑÑ, важно пÑовеÑиÑÑ Ð¿Ð¾Ð»Ð¸Ñики, и ÑбедиÑÑÑÑ Ð² Ñом, ÑÑо они ÑабоÑаÑÑ Ð¾Ð¶Ð¸Ð´Ð°ÐµÐ¼Ñм обÑазом. ÐÑимениÑелÑно к пÑедÑдÑÑÐµÐ¼Ñ Ð¿ÑимеÑÑ, ÑÑи ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ Ð¿Ð¾ÐºÐ°Ð·ÑваÑÑ, ÑÑо ÑиÑÑема ÑазÑеÑений ÑабоÑÐ°ÐµÑ ÐºÐ¾ÑÑекÑно.
-- ÐдминиÑÑÑаÑÐ¾Ñ Ð¼Ð¾Ð¶ÐµÑ Ð²Ð¸Ð´ÐµÑÑ Ð²Ñе ÑÑÑоки и полÑ
postgres=> set role admin;
SET
postgres=> table passwd;
user_name | pwhash | uid | gid | real_name | home_phone | extra_info | home_dir | shell
-----------+--------+-----+-----+-----------+--------------+------------+-------------+-----------
admin | xxx | 0 | 0 | Admin | 111-222-3333 | | /root | /bin/dash
bob | xxx | 1 | 1 | Bob | 123-456-7890 | | /home/bob | /bin/zsh
alice | xxx | 2 | 1 | Alice | 098-765-4321 | | /home/alice | /bin/zsh
(3 rows)
-- ÐÑовеÑим, ÑÑо Ð¼Ð¾Ð¶ÐµÑ Ð´ÐµÐ»Ð°ÑÑ ÐлиÑа
postgres=> set role alice;
SET
postgres=> table passwd;
ERROR: permission denied for table passwd
postgres=> select user_name,real_name,home_phone,extra_info,home_dir,shell from passwd;
user_name | real_name | home_phone | extra_info | home_dir | shell
-----------+-----------+--------------+------------+-------------+-----------
admin | Admin | 111-222-3333 | | /root | /bin/dash
bob | Bob | 123-456-7890 | | /home/bob | /bin/zsh
alice | Alice | 098-765-4321 | | /home/alice | /bin/zsh
(3 rows)
postgres=> update passwd set user_name = 'joe';
ERROR: permission denied for table passwd
-- ÐлиÑа Ð¼Ð¾Ð¶ÐµÑ Ð¸Ð·Ð¼ÐµÐ½Ð¸ÑÑ ÑÐ²Ð¾Ñ Ð¸Ð¼Ñ (поле real_name), но не Ð¸Ð¼Ñ ÐºÐ¾Ð³Ð¾-либо дÑÑгого
postgres=> update passwd set real_name = 'Alice Doe';
UPDATE 1
postgres=> update passwd set real_name = 'John Doe' where user_name = 'admin';
UPDATE 0
postgres=> update passwd set shell = '/bin/xx';
ERROR: new row violates WITH CHECK OPTION for "passwd"
postgres=> delete from passwd;
ERROR: permission denied for table passwd
postgres=> insert into passwd (user_name) values ('xxx');
ERROR: permission denied for table passwd
-- ÐлиÑа Ð¼Ð¾Ð¶ÐµÑ Ð¸Ð·Ð¼ÐµÐ½Ð¸ÑÑ ÑобÑÑвеннÑй паÑолÑ; попÑÑки поменÑÑÑ Ð´ÑÑгие паÑоли RLS пÑоÑÑо игноÑиÑÑеÑ
postgres=> update passwd set pwhash = 'abc';
UPDATE 1ÐÑе полиÑики, ÑоздаваемÑе до ÑÑого, бÑли ÑазÑеÑиÑелÑнÑми, ÑÑо знаÑиÑ, ÑÑо пÑи пÑименении неÑколÑкиÑ
полиÑик они обÑединÑлиÑÑ Ð»Ð¾Ð³Ð¸ÑеÑким опеÑаÑоÑом «ÐÐл. ХоÑÑ Ð¼Ð¾Ð¶Ð½Ð¾ ÑоздаÑÑ Ñакие ÑазÑеÑиÑелÑнÑе полиÑики, коÑоÑÑе бÑдÑÑ ÑолÑко ÑазÑеÑаÑÑ Ð´Ð¾ÑÑÑп к ÑÑÑокам пÑи опÑеделÑннÑÑ
ÑÑловиÑÑ
, Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¿ÑоÑе ÑкомбиниÑоваÑÑ ÑазÑеÑиÑелÑнÑе полиÑики Ñ Ð¾Ð³ÑаниÑиÑелÑнÑми (коÑоÑÑм Ð´Ð¾Ð»Ð¶Ð½Ñ ÑдовлеÑвоÑÑÑÑ Ð·Ð°Ð¿Ð¸Ñи и коÑоÑÑе обÑединÑÑÑÑÑ Ð»Ð¾Ð³Ð¸ÑеÑким опеÑаÑоÑом «Ð»). Ð ÑазвиÑие пÑедÑдÑÑего пÑимеÑа Ð¼Ñ Ð´Ð¾Ð±Ð°Ð²Ð¸Ð¼ огÑаниÑиÑелÑнÑÑ Ð¿Ð¾Ð»Ð¸ÑикÑ, ÑазÑеÑаÑÑÑÑ Ð°Ð´Ð¼Ð¸Ð½Ð¸ÑÑÑаÑоÑÑ, подклÑÑÑÐ½Ð½Ð¾Ð¼Ñ ÑеÑез локалÑнÑй ÑÐ¾ÐºÐµÑ Unix, обÑаÑаÑÑÑÑ Ðº запиÑÑм ÑаблиÑÑ passwd:
CREATE POLICY admin_local_only ON passwd AS RESTRICTIVE TO admin
USING (pg_catalog.inet_client_addr() IS NULL);ÐаÑем Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ ÑбедиÑÑÑÑ, ÑÑо админиÑÑÑаÑоÑ, подклÑÑÑннÑй по ÑеÑи, не ÑÐ²Ð¸Ð´Ð¸Ñ Ð½Ð¸ÐºÐ°ÐºÐ¸Ñ Ð·Ð°Ð¿Ð¸Ñей, благодаÑÑ ÑÑой огÑаниÑиÑелÑной полиÑике:
=> SELECT current_user; current_user -------------- admin (1 row) => select inet_client_addr(); inet_client_addr ------------------ 127.0.0.1 (1 row) => TABLE passwd; user_name | pwhash | uid | gid | real_name | home_phone | extra_info | home_dir | shell -----------+--------+-----+-----+-----------+------------+------------+----------+------- (0 rows) => UPDATE passwd set pwhash = NULL; UPDATE 0
Ðа пÑовеÑки ÑÑÑлоÑной ÑелоÑÑноÑÑи, напÑимеÑ, на огÑаниÑÐµÐ½Ð¸Ñ ÑникалÑноÑÑи и внеÑние клÑÑи, заÑиÑа ÑÑÑок никогда не ÑаÑпÑоÑÑÑанÑеÑÑÑ, ÑÑÐ¾Ð±Ñ Ð½Ðµ наÑÑÑалаÑÑ ÑелоÑÑноÑÑÑ Ð´Ð°Ð½Ð½ÑÑ . ÐоÑÑÐ¾Ð¼Ñ Ð¾ÑганизаÑÐ¸Ñ Ð¸ полиÑики заÑиÑÑ Ð½Ð° ÑÑовне ÑÑÑок Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ ÑÑаÑелÑно пÑоÑабаÑÑваÑÑ, ÑÑÐ¾Ð±Ñ Ð½Ðµ возникли «ÑкÑÑÑÑе каналÑ» ÑÑеÑки инÑоÑмаÑии ÑеÑез ÑÑи пÑовеÑки.
РнекоÑоÑÑÑ
ÑлÑÑаÑÑ
важно, ÑÑÐ¾Ð±Ñ Ð·Ð°ÑиÑа на ÑÑовне ÑÑÑок, наобоÑоÑ, не дейÑÑвовала. ÐапÑимеÑ, ÑезеÑвное копиÑование Ð¼Ð¾Ð¶ÐµÑ Ð¾ÐºÐ°Ð·Ð°ÑÑÑÑ Ð¿ÑовалÑнÑм, еÑли меÑ
анизм заÑиÑÑ Ð½Ð° ÑÑовне ÑÑÑок молÑа не даÑÑ ÑкопиÑоваÑÑ ÐºÐ°ÐºÐ¸Ðµ-либо ÑÑÑоки. Ð Ñаком ÑлÑÑае Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе ÑÑÑановиÑÑ Ð´Ð»Ñ Ð¿Ð°ÑамеÑÑа конÑигÑÑаÑии row_security знаÑение off. ÐÑо Ñамо по Ñебе не оÑклÑÑÐ¸Ñ Ð·Ð°ÑиÑÑ ÑÑÑок; пÑи ÑÑом пÑоÑÑо бÑÐ´ÐµÑ Ð²Ñдана оÑибка, еÑли ÑезÑлÑÑаÑÑ Ð·Ð°Ð¿ÑоÑа оÑÑилÑÑÑÑÑÑÑÑ Ð¿Ð¾Ð»Ð¸Ñикой, Ñ Ñем ÑÑÐ¾Ð±Ñ Ð¼Ð¾Ð¶Ð½Ð¾ бÑло изÑÑиÑÑ Ð¿ÑиÑÐ¸Ð½Ñ Ð¾Ñибки и ÑÑÑÑаниÑÑ ÐµÑ.
РпÑиведÑннÑÑ
вÑÑе пÑимеÑаÑ
вÑÑÐ°Ð¶ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»Ð¸Ñики ÑÑиÑÑвали ÑолÑко ÑекÑÑие знаÑÐµÐ½Ð¸Ñ Ð² запÑаÑиваемой или изменÑемой ÑÑÑоке. ÐÑо ÑамÑй пÑоÑÑой и наиболее ÑÑÑекÑивнÑй по ÑкоÑоÑÑи ваÑианÑ; по возможноÑÑи ÑеализаÑÐ¸Ñ Ð·Ð°ÑиÑÑ ÑÑÑок ÑледÑÐµÑ Ð¿ÑоекÑиÑоваÑÑ Ð¸Ð¼ÐµÐ½Ð½Ð¾ Ñак. ÐÑли же Ð´Ð»Ñ Ð¿ÑинÑÑÐ¸Ñ ÑеÑÐµÐ½Ð¸Ñ Ð¾ доÑÑÑпе необÑ
одимо обÑаÑаÑÑÑÑ Ðº дÑÑгим ÑÑÑокам или дÑÑгим ÑаблиÑам, ÑÑо можно оÑÑÑеÑÑвиÑÑ, пÑименÑÑ Ð² вÑÑажениÑÑ
полиÑик вложеннÑе SELECT или ÑÑнкÑии, ÑодеÑжаÑие SELECT. Ðднако ÑÑÑиÑе, ÑÑо пÑи Ñакой ÑеализаÑии Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ñ ÑÑÐ»Ð¾Ð²Ð¸Ñ Ð³Ð¾Ð½ÐºÐ¸, ÑÑо ÑÑеваÑо ÑÑеÑкой инÑоÑмаÑии, еÑли не пÑинÑÑÑ Ð¼ÐµÑÑ Ð¿ÑедоÑÑоÑожноÑÑи. ÐапÑимеÑ, ÑаÑÑмоÑÑим ÑледÑÑÑÑÑ ÐºÐ¾Ð½ÑÑÑÑкÑÐ¸Ñ ÑаблиÑ:
-- опÑеделение гÑÑпп пÑивилегий
CREATE TABLE groups (group_id int PRIMARY KEY,
group_name text NOT NULL);
INSERT INTO groups VALUES
(1, 'low'),
(2, 'medium'),
(5, 'high');
GRANT ALL ON groups TO alice; -- alice ÑвлÑеÑÑÑ Ð°Ð´Ð¼Ð¸Ð½Ð¸ÑÑÑаÑоÑом
GRANT SELECT ON groups TO public;
-- опÑеделение ÑÑовней пÑивилегий Ð´Ð»Ñ Ð¿Ð¾Ð»ÑзоваÑелей
CREATE TABLE users (user_name text PRIMARY KEY,
group_id int NOT NULL REFERENCES groups);
INSERT INTO users VALUES
('alice', 5),
('bob', 2),
('mallory', 2);
GRANT ALL ON users TO alice;
GRANT SELECT ON users TO public;
-- ÑаблиÑа, ÑодеÑжаÑÐ°Ñ Ð·Ð°ÑиÑаемÑÑ Ð¸Ð½ÑоÑмаÑиÑ
CREATE TABLE information (info text,
group_id int NOT NULL REFERENCES groups);
INSERT INTO information VALUES
('barely secret', 1),
('slightly secret', 2),
('very secret', 5);
ALTER TABLE information ENABLE ROW LEVEL SECURITY;
-- ÑÑÑока должна бÑÑÑ Ð´Ð¾ÑÑÑпна Ð´Ð»Ñ ÑÑениÑ/Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑзоваÑелÑм Ñ group_id,
-- болÑÑим или ÑавнÑм group_id данной ÑÑÑоки
CREATE POLICY fp_s ON information FOR SELECT
USING (group_id <= (SELECT group_id FROM users WHERE user_name = current_user));
CREATE POLICY fp_u ON information FOR UPDATE
USING (group_id <= (SELECT group_id FROM users WHERE user_name = current_user));
-- Ð¼Ñ Ð·Ð°ÑиÑаем ÑаблиÑÑ Ñ Ð¸Ð½ÑоÑмаÑией, полагаÑÑÑ ÑолÑко на RLS
GRANT ALL ON information TO public;ТепеÑÑ Ð¿Ñедположим, ÑÑо ÐлиÑа (ÑÐ¾Ð»Ñ alice) Ð¶ÐµÐ»Ð°ÐµÑ Ð·Ð°Ð¿Ð¸ÑаÑÑ Â«Ñлегка ÑекÑеÑнÑÑ» инÑоÑмаÑиÑ, но пÑи ÑÑом не Ñ
оÑÐµÑ Ð´Ð°Ð²Ð°ÑÑ mallory доÑÑÑп к ней. Ðна Ð´ÐµÐ»Ð°ÐµÑ ÑледÑÑÑее:
BEGIN; UPDATE users SET group_id = 1 WHERE user_name = 'mallory'; UPDATE information SET info = 'secret from mallory' WHERE group_id = 2; COMMIT;
Ðа пеÑвÑй взглÑд вÑÑ Ð½Ð¾ÑмалÑно; mallory ни пÑи какиÑ
ÑÑловиÑÑ
не должна ÑвидеÑÑ ÑÑÑÐ¾ÐºÑ Â«secret from mallory». Ðднако здеÑÑ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾ ÑÑловие гонки. ÐÑли ÐÑллоÑи (ÑÐ¾Ð»Ñ mallory) паÑаллелÑно вÑполнÑеÑ, Ñкажем:
SELECT * FROM information WHERE group_id = 2 FOR UPDATE;
и ÐµÑ ÑÑанзакÑÐ¸Ñ Ð² Ñежиме READ COMMITTED, она ÑÐ¼Ð¾Ð¶ÐµÑ ÑвидеÑÑ Â«secret from mallory». ÐÑо пÑоизойдÑÑ, еÑли ÐµÑ ÑÑанзакÑÐ¸Ñ Ð´Ð¾Ð¹Ð´ÑÑ Ð´Ð¾ ÑÑÑоки information ÑÑÐ°Ð·Ñ Ð¿Ð¾Ñле Ñого, как ÑÑÑ ÑÑÑÐ¾ÐºÑ Ð¸Ð·Ð¼ÐµÐ½Ð¸Ñ ÐлиÑа (ÑÐ¾Ð»Ñ alice). Ðна заблокиÑÑеÑÑÑ, Ð¾Ð¶Ð¸Ð´Ð°Ñ ÑикÑиÑÐ¾Ð²Ð°Ð½Ð¸Ñ ÑÑанзакÑии ÐлиÑÑ, а заÑем пÑоÑиÑÐ°ÐµÑ Ð¸Ð·Ð¼ÐµÐ½Ñнное ÑодеÑжимое ÑÑÑоки благодаÑÑ Ð¿ÑÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ FOR UPDATE. Ðднако пÑи ÑÑом изменÑнное ÑодеÑжимое users не бÑÐ´ÐµÑ Ð¿ÑоÑиÑано неÑвнÑм запÑоÑом SELECT, Ñак как ÑÑÐ¾Ñ Ð²Ð»Ð¾Ð¶ÐµÐ½Ð½Ñй SELECT вÑполнÑеÑÑÑ Ð±ÐµÐ· ÑÐºÐ°Ð·Ð°Ð½Ð¸Ñ FOR UPDATE; вмеÑÑо ÑÑого ÑÑÑока users ÑиÑаеÑÑÑ Ð¸Ð· Ñнимка, полÑÑенного в наÑале запÑоÑа. Таким обÑазом, вÑÑажение полиÑики пÑовеÑÑÐµÑ ÑÑаÑое знаÑение ÑÑÐ¾Ð²Ð½Ñ Ð¿Ñивилегий полÑзоваÑÐµÐ»Ñ mallory и позволÑÐµÑ ÐµÐ¹ видеÑÑ Ð¸Ð·Ð¼ÐµÐ½ÑннÑÑ ÑÑÑокÑ.
ÐбойÑи ÑÑÑ Ð¿ÑÐ¾Ð±Ð»ÐµÐ¼Ñ Ð¼Ð¾Ð¶Ð½Ð¾ неÑколÑкими ÑпоÑобами. ÐеÑвое пÑоÑÑое ÑеÑение заклÑÑаеÑÑÑ Ð² иÑполÑзовании SELECT ... FOR SHARE во вложеннÑÑ
запÑоÑаÑ
SELECT в полиÑикаÑ
заÑиÑÑ ÑÑÑок. Ðднако Ð´Ð»Ñ ÑÑого поÑÑебÑеÑÑÑ Ð´Ð°Ð²Ð°ÑÑ Ð·Ð°ÑÑонÑÑÑм полÑзоваÑелÑм пÑаво UPDATE в Ñелевой ÑаблиÑе (здеÑÑ users), ÑÑо Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð½ÐµÐ¶ÐµÐ»Ð°ÑелÑно. (ХоÑÑ Ð¼Ð¾Ð¶Ð½Ð¾ пÑимениÑÑ ÐµÑÑ Ð¾Ð´Ð½Ñ Ð¿Ð¾Ð»Ð¸ÑÐ¸ÐºÑ Ð·Ð°ÑиÑÑ ÑÑÑок, ÑÑÐ¾Ð±Ñ Ð¾Ð½Ð¸ не могли пÑакÑиÑеÑки воÑполÑзоваÑÑÑÑ ÑÑим пÑавилом; либо помеÑÑиÑÑ Ð²Ð»Ð¾Ð¶ÐµÐ½Ð½Ñй SELECT в ÑÑнкÑиÑ, опÑеделÑÑÑÑÑ ÐºÐ¾Ð½ÑекÑÑ Ð±ÐµÐ·Ð¾Ð¿Ð°ÑноÑÑи.) ÐÑоме ÑÑого, акÑивное иÑполÑзование блокиÑовок ÑÑÑок в Ñелевой ÑаблиÑе Ð¼Ð¾Ð¶ÐµÑ Ð¿Ð¾Ð²Ð»ÐµÑÑ Ð¿ÑÐ¾Ð±Ð»ÐµÐ¼Ñ Ñ Ð¿ÑоизводиÑелÑноÑÑÑÑ, оÑобенно пÑи ÑаÑÑÑÑ
изменениÑÑ
. ÐÑÑгое ÑеÑение, пÑакÑиÑное, еÑли ÑÐµÐ»ÐµÐ²Ð°Ñ ÑаблиÑа изменÑеÑÑÑ Ð½ÐµÑаÑÑо, заклÑÑаеÑÑÑ Ð² блокиÑовке Ñелевой ÑаблиÑÑ Ð² Ñежиме ACCESS EXCLUSIVE пÑи изменении, ÑÑÐ¾Ð±Ñ Ð½Ð¸ÐºÐ°ÐºÐ¸Ðµ паÑаллелÑнÑе ÑÑанзакÑии не видели ÑÑаÑÑе знаÑÐµÐ½Ð¸Ñ ÑÑÑок. Ðибо можно пÑоÑÑо дождаÑÑÑÑ Ð·Ð°Ð²ÐµÑÑÐµÐ½Ð¸Ñ Ð²ÑеÑ
паÑаллелÑнÑÑ
ÑÑанзакÑий поÑле Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² Ñелевой ÑаблиÑе, пÑежде Ñем вноÑиÑÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ, ÑаÑÑÑиÑаннÑе на новÑе ÑÑÐ»Ð¾Ð²Ð¸Ñ Ð±ÐµÐ·Ð¾Ð¿Ð°ÑноÑÑи.
Ðа дополниÑелÑнÑми подÑобноÑÑÑми обÑаÑиÑеÑÑ Ðº CREATE POLICY и ALTER TABLE.