Un studiu despre implementarea securității la nivel de rând în PostgreSQL

Ca o completare a Un studiu despre implementarea logicii de afaceri la nivelul funcțiilor stocate PostgreSQL и în principal pentru un răspuns detaliat pe comentariu.

Partea teoretică este bine descrisă în documentație PostgreSQL - Politici de protecție a rândurilor. Mai jos este o implementare practică a unui mic sarcină specifică de afaceri - ascunderea datelor șterse. Schiță dedicată implementării Modelare de rol folosind RLS prezentate separat.

Un studiu despre implementarea securității la nivel de rând în PostgreSQL

Nu există nimic nou în articol, nu există niciun sens ascuns sau cunoștințe secrete. Doar o schiță despre implementarea practică a unei idei teoretice. Daca e cineva interesat, citeste-l. Dacă nu ești interesat, nu-ți pierde timpul.

Declarație de problemă

Fără să ne scufundăm adânc în domeniul subiectului, pe scurt, problema poate fi formulată după cum urmează: Există un tabel care implementează o anumită entitate de afaceri. Rândurile din tabel pot fi șterse, dar rândurile nu pot fi șterse fizic; ele trebuie ascunse.

Căci se spune: „Nu șterge nimic, ci doar redenumiți. Internetul stochează TOTUL”

Pe parcurs, este recomandabil să nu rescrieți funcțiile stocate existente care funcționează cu această entitate.

Pentru a implementa acest concept, tabelul are atributul este_ștersă. Apoi totul este simplu - trebuie să vă asigurați că clientul poate vedea numai liniile în care atributul este_ștersă fals Pentru ce este folosit mecanismul? Securitate la nivel de rând.

punerea în aplicare

Creați un rol și o schemă separate

CREATE ROLE repos;
CREATE SCHEMA repos;

Creați tabelul țintă

CREATE TABLE repos.file
(
...
is_del BOOLEAN DEFAULT FALSE
);
CREATE SCHEMA repos

Includem Securitate la nivel de rând

ALTER TABLE repos.file  ENABLE ROW LEVEL SECURITY ;
CREATE POLICY file_invisible_deleted  ON repos.file FOR ALL TO dba_role USING ( NOT is_deleted );
GRANT ALL ON TABLE repos.file to dba_role ;
GRANT USAGE ON SCHEMA repos TO dba_role ;

Funcția de service — ștergerea unui rând din tabel

CREATE OR REPLACE repos.delete( curr_id repos.file.id%TYPE)
RETURNS integer AS $$
BEGIN
...
UPDATE repos.file
SET is_del = TRUE 
WHERE id = curr_id ; 
...
END
$$ LANGUAGE plpgsql SECURITY DEFINER;

Funcția de afaceri — ștergerea unui document

CREATE OR REPLACE business_functions.deleteDoc( doc_for_delete JSON )
RETURNS JSON AS $$
BEGIN
...
PERFORM  repos.delete( doc_id ) ;
...
END
$$ LANGUAGE plpgsql SECURITY DEFINER;

Constatări

Clientul șterge documentul

SELECT business_functions.delCFile( (SELECT json_build_object( 'CId', 3 )) );

După ștergere, clientul nu vede documentul

SELECT business_functions.getCFile"( (SELECT json_build_object( 'CId', 3 )) ) ;
-----------------
(0 rows)

Dar în baza de date documentul nu este șters, se schimbă doar atributul is_del

psql -d my_db
SELECT  id, name , is_del FROM repos.file ;
id |  name  | is_del
--+---------+------------
 1 |  test_1 | t
(1 row)

Ceea ce a fost cerut în declarația problemei.

Total

Dacă subiectul este interesant, în următorul studiu puteți arăta un exemplu de implementare a unui model bazat pe roluri pentru separarea accesului la date folosind Row Level Security.

Sursa: www.habr.com

Adauga un comentariu