A hozzáférési szerepmodelek megvalósítása Row Level Security használatával a PostgreSQL-ben

A téma fejlesztése Etüd a Row Level Security megvalósításáról a PostgreSQL-ben és kiterjedt válaszhoz Gyorsan emlékezzünk vissza, hogyan működik a moduláris aritmetika. Az óra már egy ismert koncepció. Az órák használata megjegyzés.

A használt stratégia magában foglalja a "Üzleti logika az adatbázisban" koncepció alkalmazását, amelyet itt kissé részletesebben ismertetünk — Üzleti logika megvalósítása PostgreSQL tárolt függvények szintjén

A teoretikus rész kiválóan van leírva a dokumentációban Postgres Pro — Sorvédelmi irányelvek. Az alábbiakban egy gyakorlati megvalósítást mutatunk be egy konkrét üzleti feladathoz — adatelérési szerepkör modell.

A hozzáférési szerepmodelek megvalósítása Row Level Security használatával a PostgreSQL-ben

A cikkben nincs semmi új, nincs rejtett jelentés és titkos tudás. Csak egy vázlat a teoretikus ötlet gyakorlati megvalósításáról. Ha érdekes — olvasd el. Ha nem érdekes — ne pazarold az idődet.

Lépjünk át a kitűzött feladatra: írjunk egy XDP mechanizmust SYN cookie-kkal.

Szükséges korlátozni a dokumentum megtekintésére/beküldésére/módosítására/törlésére való hozzáférést az alkalmazás felhasználójának szerepe szerint. A szerepkör alatt az alábbi táblázat roles több-többhöz kapcsolódó viszonyban van a táblázattal Miután megállapítottuk, hogy ki küldte a kérést, meg kell határoznunk, hogy az adott alanynak mit engedélyeztek. Egyes szolgáltatásrácsok lehetővé teszik alapvető irányelvek (arról, hogy ki mit tehet) megadását YAML-fájlok formájában vagy parancssoron, míg mások integrációt kínálnak olyan keretrendszerekkel, mint az. A táblák megvalósításának részleteit a triviális jelleg miatt kihagytuk. Továbbá kihagytuk a konkrét megvalósítással kapcsolatos részleteket a téma területén.

Megvalósítás

Szerepek, séma, táblázat létrehozása

Adatbázis objektumok létrehozása

CREATE ROLE store;
CREATE SCHEMA store AUTHORIZATION store;
CREATE TABLE store.docs
(
  id integer ,         --dokumentum id
  man_id integer , --dokumentum kezelőjének id-je
  stat_id integer ,  --dokumentum státuszának id-je
  ...
  is_del BOOLEAN DEFAULT FALSE 
);
ALTER TABLE store.docs ADD CONSTRAINT doc_pk PRIMARY KEY (id);
ALTER TABLE store.docs OWNER TO store ;

Funkciók létrehozása az RLS megvalósításához

Az egyes sorok SELECT-elési lehetőségének ellenőrzése

check_select

CREATE OR REPLACE FUNCTION store.check_select ( current_id store.docs.id%TYPE ) RETURNS boolean AS $$
DECLARE
  result boolean ;
  curr_pid integer ;
  curr_stat_id integer ;
  doc_man_id integer ;
BEGIN 
  -- A DBA hozzáféréssel bír minden dokumentumhoz
  IF SESSION_USER = 'curr_dba'
  THEN
    RETURN TRUE ;
  END IF ;
  --------------------------------

  --Ha a dokumentumnak van 'törölt' címkéje - ne jelenjen meg a lekérdezés során
  SELECT
    is_del
  INTO
    result
  FROM
    store.docs
  WHERE
    id = current_id ;
 IF result = TRUE
 THEN
   RETURN FALSE ;
 END IF ;
 --------------------------------

 --Jelenlegi felhasználó ID-jának lekérése
 SELECT
   service_function.get_curr_pid ()
 INTO
   curr_pid ;
 --------------------------------

 --A dokumentum kezelőjének ID-jának lekérése
 SELECT
   man_id
 INTO
   doc_man_id
 FROM
   store.docs
 WHERE
   id = current_id ;
 --------------------------------

 --Ha a dokumentum kezelője nem a jelenlegi felhasználó, vagy a kezelő nincs megadva
 --helyezze a dokumentumot a lekérdezésbe
 IF doc_man_id != curr_pid OR doc_man_id IS NULL
 THEN
   RETURN TRUE  ;
 ELSE
   --Jelenlegi dokumentum státuszának lekérése
   SELECT
     stat_id                                         
   INTO
     curr_statid
   FROM
     store.docs
   WHERE
     id = current_id ;
    
   --Ha a státusz lehetővé teszi a dokumentum megtekintését - helyezze a dokumentumot a lekérdezésbe                     
   IF curr_statid = 4 OR curr_statid = 9
   THEN
     RETURN TRUE ;
   ELSE
   --Ellenkező esetben - zárja ki a dokumentumot a lekérdezésből
     RETURN FALSE ;
    END IF ;
  END IF ;
  --------------------------------

 RETURN FALSE ;
END
$$ LANGUAGE plpgsql SECURITY DEFINER;
ALTER FUNCTION store.check_select( store.docs.id%TYPE  ) OWNER TO store ;
REVOKE EXECUTE ON FUNCTION store.check_select( store.docs.id%TYPE  ) FROM public; 
GRANT EXECUTE ON FUNCTION store.check_select( store.docs.id%TYPE  ) TO service_functions; 

A sor INSERT végrehajtásának ellenőrzése

check_insert

CREATE OR REPLACE FUNCTION store.check_insert ( current_id store.docs.id%TYPE ) RETURNS boolean AS $$
DECLARE
  curr_role_id integer ;
BEGIN
  --A DBA bárhol tud új sort hozzáadni
  IF SESSION_USER = 'curr_dba'
  THEN
    RETURN TRUE ;
  END IF ;
  --------------------------------

 --A jelenlegi felhasználó szerepkörének ID-jének lekérése 
 SELECT
   service_functions.current_rid()
  INTO
    curr_role_id ;
 --------------------------------

--Ha a szerepkör lehetővé teszi új dokumentum létrehozását
--engedni kell
IF curr_role_id = 3 OR curr_role_id = 5     
THEN
  RETURN TRUE ;
END IF ;
--------------------------------
RETURN FALSE  ;
END
$$ LANGUAGE plpgsql SECURITY DEFINER;
ALTER FUNCTION store.check_insert( store.docs.id%TYPE  ) OWNER TO store ;
REVOKE EXECUTE ON FUNCTION store.check_insert( store.docs.id%TYPE  ) FROM public;
GRANT EXECUTE ON FUNCTION store.check_insert( store.docs.id%TYPE  ) TO service_functions; 

A sor DELETE végrehajtásának ellenőrzése

check_delete

CREATE OR REPLACE FUNCTION store.check_delete ( current_id store.docs.id%TYPE )
RETURNS boolean AS $$
BEGIN  
  --Csak a DBA tud sort törölni 
  IF SESSION_USER = 'curr_dba'
  THEN
    RETURN TRUE ;
  END IF ;
  --------------------------------

  RETURN FALSE ;
END
$$ LANGUAGE plpgsql
SECURITY DEFINER;
ALTER FUNCTION store.check_delete( store.docs.id%TYPE  ) OWNER TO store ;
REVOKE EXECUTE ON FUNCTION store.check_delete( store.docs.id%TYPE  ) FROM public;

A sor UPDATE végrehajtásának ellenőrzése.

update_using

CREATE OR REPLACE FUNCTION store.update_using ( current_id store.docs.id%TYPE , is_del boolean  )
RETURNS boolean AS $$
BEGIN  
   --Az eltávolított státusszal rendelkező dokumentumok nem módosíthatók
   IF is_del 
   THEN
     RETURN FALSE ;
 ELSE
    RETURN TRUE ;
  END IF ;

END
$$ LANGUAGE plpgsql SECURITY DEFINER;
ALTER FUNCTION store.update_using(  store.docs.id%TYPE ,  boolean  ) OWNER TO store ;
REVOKE EXECUTE ON FUNCTION store.update_using(  store.docs.id%TYPE ,  boolean  ) FROM public;
GRANT EXECUTE ON FUNCTION store.update_using( store.docs.id%TYPE  ) TO service_functions;

update_check

CREATE OR REPLACE FUNCTION store.update_with_check ( current_id store.docs.id%TYPE , is_del boolean )
RETURNS boolean AS $$
DECLARE
  current_rid integer ;
  current_statid integer ;
BEGIN                

  --DBA megtekintheti a sort 
  IF SESSION_USER = 'curr_dba'
  THEN
    RETURN TRUE ;
  END IF ;
  --------------------------------

 --A jelenlegi felhasználó szerepkörazonosítójának megszerzése 
 SELECT
   service_functions.current_rid()
  INTO
    curr_role_id ;
 --------------------------------                            

 --Dokumentum eltávolítása - tulajdonság módosítása 
 IF is_deleted
 THEN
   --Ha a felhasználó szerepe ***
   IF current_role_id = 3        
   THEN
      SELECT
        stat_id                                          
      INTO
        curr_statid
      FROM
        store.docs
      WHERE
        id = current_id ;

      --A dokumentum *** státusza nem törölhető 
      IF current_status_id = 11
      THEN
         RETURN FALSE ;
      ELSE
      --Dokumentum törlése más státuszokban lehetséges
        RETURN TRUE ;
      END IF ;

    --Egyébként, ha a felhasználó szerepe ***
    ELSIF current_role_id = 5            
    THEN
      --A dokumentumok összes státusza 
      RETURN TRUE ;
    ELSE
      --A többi felhasználónak nem lehet dokumentumokat törölni
      RETURN FALSE ;
    END IF ;
 ELSE      
   --A dokumentum frissítése engedélyezett
    RETURN TRUE ;
END IF ;

RETURN FALSE ;
END
$$ LANGUAGE plpgsql SECURITY DEFINER;
ALTER FUNCTION store.update_with_check( storg.docs.id%TYPE ,  boolean   ) OWNER TO store ;
REVOKE EXECUTE ON FUNCTION store.update_with_check( storg.docs.id%TYPE ,  boolean   )  FROM public;
GRANT EXECUTE ON FUNCTION store.update_with_check( store.docs.id%TYPE  ) TO service_functions;

A sor szintű biztonsági politika aktiválása a táblázat számára.

ROW LEVEL SECURITY ENGEDÉLYEZÉSE

ALTER TABLE store.docs ENABLE ROW LEVEL SECURITY ;

CREATE POLICY doc_select ON store.docs FOR SELECT TO service_functions USING ( (SELECT store.check_select(id)) );
CREATE POLICY doc_insert ON store.docs FOR INSERT TO service_functions WITH CHECK ( (SELECT store.check_insert(id)) );
CREATE POLICY docs_delete ON store.docs FOR DELETE TO service_functions USING ( (SELECT store.check_delete(id)) );

CREATE POLICY doc_update_using ON store.docs FOR UPDATE TO service_functions USING ( (SELECT store.update_using(id , is_del )) );
CREATE POLICY doc_update_check ON store.docs FOR UPDATE TO service_functions  WITH CHECK ( (SELECT store.update_with_check(id , is_del )) );

Result

Ez működik.

A javasolt stratégia lehetővé tette a szerepkörmodell megvalósításának áthelyezését a bizniszfukciók szintjéről az adatkezelés szintjére.

A funkciók felhasználhatók mintákként összetettebb adatrejtési modellek megvalósítására is, ha az üzleti követelmények megkövetelik.

Forrás: habr.com

Megbízható hosting vásárlása weboldalak számára, DDoS védelemmel, VPS VDS szerverek. 🔥 Megbízható webtárhely vásárlása DDoS védelemmel, VPS VDS szerverek | ProHoster