Utekelezaji wa kielelezo cha ufikiaji kulingana na jukumu kwa kutumia Usalama wa Kiwango cha Mstari katika PostgreSQL

Maendeleo ya mada Utafiti juu ya kutekeleza Usalama wa Kiwango cha Mstari katika PostgreSQL ΠΈ kwa jibu la kina juu ya maoni.

Mkakati unaotumika unahusisha matumizi ya dhana ya "Mantiki ya Biashara katika Hifadhidata", ambayo ilielezwa kwa undani zaidi hapa - Utafiti wa kutekeleza mantiki ya biashara katika kiwango cha vitendaji vilivyohifadhiwa vya PostgreSQL

Sehemu ya kinadharia imeelezewa vizuri katika nyaraka PostgreSQL - Sera za ulinzi wa safu mlalo. Chini ni utekelezaji wa vitendo kazi maalum ya biashara - mfano wa kuigwa kwa upatikanaji wa data.

Utekelezaji wa kielelezo cha ufikiaji kulingana na jukumu kwa kutumia Usalama wa Kiwango cha Mstari katika PostgreSQL

Hakuna kitu kipya katika makala, hakuna maana iliyofichwa au ujuzi wa siri. Mchoro tu kuhusu utekelezaji wa vitendo wa wazo la kinadharia. Ikiwa mtu yeyote ana nia, soma. Ikiwa hupendi, usipoteze wakati wako.

Taarifa ya tatizo

Inahitajika kuzuia ufikiaji wa kutazama / kuingiza / kurekebisha / kufuta hati kulingana na jukumu la mtumiaji wa programu. Jukumu linarejelea ingizo kwenye jedwali majukumu kuhusishwa na uhusiano wa wengi hadi wengi na meza watumiaji. Maelezo ya utekelezaji wa majedwali, kwa sababu ya udogo, yameachwa. Maelezo mahususi ya utekelezaji yanayohusiana na eneo la somo pia yameachwa.

Utekelezaji

Unda majukumu, schemas, meza

Kuunda Vitu vya Hifadhidata

CREATE ROLE store;
CREATE SCHEMA store AUTHORIZATION store;
CREATE TABLE store.docs
(
  id integer ,         --id Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°
  man_id integer , --id ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Π° Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°
  stat_id integer ,  --id статуса Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°
  ...
  is_del BOOLEAN DEFAULT FALSE 
);
ALTER TABLE store.docs ADD CONSTRAINT doc_pk PRIMARY KEY (id);
ALTER TABLE store.docs OWNER TO store ;

Kuunda vipengele vya kutekeleza RLS

Kuangalia uwezo wa kutekeleza CHAGUA safu mlalo

chagua_chagua

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 
  -- DBA ΠΈΠΌΠ΅Π΅Ρ‚ доступ ΠΊΠΎ всСм Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°ΠΌ
  IF SESSION_USER = 'curr_dba'
  THEN
    RETURN TRUE ;
  END IF ;
  --------------------------------

  --Если Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚ ΠΈΠΌΠ΅Π΅Ρ‚ ΠΌΠ΅Ρ‚ΠΊΡƒ 'ΡƒΠ΄Π°Π»Π΅Π½' - Π½Π΅ ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒ Π² Π²Ρ‹Π±ΠΎΡ€ΠΊΠ΅
  SELECT
    is_del
  INTO
    result
  FROM
    store.docs
  WHERE
    id = current_id ;
 IF result = TRUE
 THEN
   RETURN FALSE ;
 END IF ;
 --------------------------------

 --ΠŸΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ id Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ
 SELECT
   service_function.get_curr_pid ()
 INTO
   curr_pid ;
 --------------------------------

 --ΠŸΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ id ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Π° Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°
 SELECT
   man_id
 INTO
   doc_man_id
 FROM
   store.docs
 WHERE
   id = current_id ;
 --------------------------------

 --Если ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π° Π½Π΅ Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ ΠΈΠ»ΠΈ ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€ Π½Π΅ Π½Π°Π·Π½Π°Ρ‡Π΅Π½
 --Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚ Π² Π²Ρ‹Π±ΠΎΡ€ΠΊΡƒ
 IF doc_man_id != curr_pid OR doc_man_id IS NULL
 THEN
   RETURN TRUE  ;
 ELSE
   --ΠŸΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ статус Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°
   SELECT
     stat_id                                         
   INTO
     curr_statid
   FROM
     store.docs
   WHERE
     id = current_id ;
    
   --Если статус позволяСт ΠΏΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚ - Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚ Π² Π²Ρ‹Π±ΠΎΡ€ΠΊΡƒ                     
   IF curr_statid = 4 OR curr_statid = 9
   THEN
     RETURN TRUE ;
   ELSE
   --Π˜Π½Π°Ρ‡Π΅ - ΠΈΡΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚ ΠΈΠ· Π²Ρ‹Π±ΠΎΡ€ΠΊΠΈ
     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; 

Inakagua uwezo wa KUWEKA safu mlalo

angalia_ingiza

CREATE OR REPLACE FUNCTION store.check_insert ( current_id store.docs.id%TYPE ) RETURNS boolean AS $$
DECLARE
  curr_role_id integer ;
BEGIN
  --DBA ΠΌΠΎΠΆΠ΅Ρ‚ Π΄ΠΎΠ±Π°Π²Π»ΡΡ‚ΡŒ строку Π² любом случаС
  IF SESSION_USER = 'curr_dba'
  THEN
    RETURN TRUE ;
  END IF ;
  --------------------------------

 --ΠŸΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ id Ρ€ΠΎΠ»ΠΈ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ 
 SELECT
   service_functions.current_rid()
  INTO
    curr_role_id ;
 --------------------------------

--Если Ρ€ΠΎΠ»ΡŒ допускаСт Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ создания Π½ΠΎΠ²ΠΎΠ³ΠΎ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°
--Ρ€Π°Π·Ρ€Π΅ΡˆΠΈΡ‚ΡŒ
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; 

Inakagua uwezo wa KUFUTA safu mlalo

check_delete

CREATE OR REPLACE FUNCTION store.check_delete ( current_id store.docs.id%TYPE )
RETURNS boolean AS $$
BEGIN  
  --Волько DBA ΠΌΠΎΠΆΠ΅Ρ‚ ΡƒΠ΄Π°Π»ΡΡ‚ΡŒ строку 
  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;

Inakagua uwezo wa KUSASISHA safu mlalo.

sasisha_kutumia

CREATE OR REPLACE FUNCTION store.update_using ( current_id store.docs.id%TYPE , is_del boolean  )
RETURNS boolean AS $$
BEGIN  
   --Π”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Ρ‹ ΠΈΠΌΠ΅ΡŽΡ‰ΠΈΠ΅ статус 'ΡƒΠ΄Π°Π»Π΅Π½' - Π½Π΅ Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΡƒΡŽΡ‚ΡΡ
   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;

sasisha_angalia

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 ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΡ€ΠΎΡΠΌΠ°Ρ‚Ρ€ΠΈΠ²Π°Ρ‚ΡŒ строку 
  IF SESSION_USER = 'curr_dba'
  THEN
    RETURN TRUE ;
  END IF ;
  --------------------------------

 --ΠŸΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ id Ρ€ΠΎΠ»ΠΈ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ 
 SELECT
   service_functions.current_rid()
  INTO
    curr_role_id ;
 --------------------------------                            

 --Π£Π΄Π°Π»Π΅Π½ΠΈΠ΅ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π° - ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ ΠΏΡ€ΠΈΠ·Π½Π°ΠΊΠ° 
 IF is_deleted
 THEN
   --Если Ρ€ΠΎΠ»ΡŒ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ ***
   IF current_role_id = 3        
   THEN
      SELECT
        stat_id                                          
      INTO
        curr_statid
      FROM
        store.docs
      WHERE
        id = current_id ;

      --Π”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚ Π² статусС *** нСльзя ΡƒΠ΄Π°Π»ΠΈΡ‚ΡŒ 
      IF current_status_id = 11
      THEN
         RETURN FALSE ;
      ELSE
      --МоТно ΡƒΠ΄Π°Π»ΠΈΡ‚ΡŒ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚ Π² Π΄Ρ€ΡƒΠ³ΠΈΡ… статусах
        RETURN TRUE ;
      END IF ;

    --Π˜Π½Π°Ρ‡Π΅ , Ссли Ρ€ΠΎΠ»ΡŒ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ ***
    ELSIF current_role_id = 5            
    THEN
      --ВсС статусы Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π° 
      RETURN TRUE ;
    ELSE
      --Π”Ρ€ΡƒΠ³ΠΈΠ΅ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΠΈ Π½Π΅ ΠΌΠΎΠ³ΡƒΡ‚ ΡƒΠ΄Π°Π»ΡΡ‚ΡŒ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Ρ‹
      RETURN FALSE ;
    END IF ;
 ELSE      
   --ОбновлСниС Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π° Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΎ
    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;

Washa sera ya Utunzaji wa Ngazi ya Mstari kwa jedwali.

WASHA USALAMA NGAZI YA SAFU

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 )) );

Jumla ya

Inafanya kazi.

Mkakati uliopendekezwa ulifanya iwezekanavyo kuhamisha utekelezaji wa mfano wa kuigwa kutoka kwa kiwango cha kazi za biashara hadi kiwango cha kuhifadhi data.

Vipengele vya kukokotoa vinaweza kutumika kama kiolezo cha kutekeleza miundo ya kisasa zaidi ya kuficha data ikiwa mahitaji ya biashara yanahitaji hivyo.

Chanzo: mapenzi.com

Kuongeza maoni