PostgreSQL හි පේළි මට්ටමේ ආරක්ෂාව භාවිතා කරමින් භූමිකාව පදනම් කරගත් ප්‍රවේශ ආකෘතියක් ක්‍රියාත්මක කිරීම

තේමා සංවර්ධනය PostgreSQL හි පේළි මට්ටමේ ආරක්ෂාව ක්‍රියාත්මක කිරීම පිළිබඳ අධ්‍යයනයක් и සවිස්තරාත්මක පිළිතුරක් සඳහා මත අදහස් දැක්වීමක්.

භාවිතා කරන උපාය මාර්ගයට "දත්ත ගබඩාවේ ව්‍යාපාර තර්කනය" සංකල්පය භාවිතා කිරීම ඇතුළත් වේ, එය මෙහි ටිකක් විස්තරාත්මකව විස්තර කර ඇත - PostgreSQL ගබඩා කර ඇති කාර්යයන් මට්ටමින් ව්‍යාපාර තර්කනය ක්‍රියාත්මක කිරීම පිළිබඳ අධ්‍යයනයක්

න්යායික කොටස ලේඛනගත කිරීමෙහි හොඳින් විස්තර කර ඇත PostgreSQL - පේළි ආරක්ෂණ ප්රතිපත්ති. පහත දැක්වෙන්නේ ප්රායෝගිකව ක්රියාත්මක කිරීමකි නිශ්චිත ව්යාපාරික කාර්යයක් - දත්ත ප්රවේශය සඳහා ආදර්ශයක්.

PostgreSQL හි පේළි මට්ටමේ ආරක්ෂාව භාවිතා කරමින් භූමිකාව පදනම් කරගත් ප්‍රවේශ ආකෘතියක් ක්‍රියාත්මක කිරීම

ලිපියේ අලුත් දෙයක් නැත, සැඟවුණු අර්ථයක් හෝ රහස් දැනුමක් නොමැත. න්‍යායාත්මක අදහසක් ප්‍රායෝගිකව ක්‍රියාත්මක කිරීම පිළිබඳ දළ සටහනක් පමණි. කැමති කෙනෙක් ඉන්නවා නම් කියවන්න. ඔබ උනන්දුවක් නොදක්වන්නේ නම්, ඔබේ කාලය නාස්ති නොකරන්න.

ගැටලුව ප්රකාශ කිරීම

යෙදුම් පරිශීලකයාගේ භූමිකාවට අනුකූලව ලේඛනයක් බැලීම / ඇතුළු කිරීම / වෙනස් කිරීම / මකා දැමීම සඳහා ප්‍රවේශය සීමා කිරීම අවශ්‍ය වේ. භූමිකාව යනු වගුවක ඇතුළත් කිරීමකි භූමිකාවන් මේසයක් සමඟ බොහෝ-බොහෝ සම්බන්ධතාවක් සමඟ සම්බන්ධ වේ පරිශීලකයන්. වගු ක්රියාත්මක කිරීම පිළිබඳ විස්තර, සුළු බව නිසා, ඉවත් කර ඇත. විෂය ක්ෂේත්‍රයට අදාළ නිශ්චිත ක්‍රියාත්මක කිරීමේ විස්තර ද මඟ හැර ඇත.

Реализация

භූමිකාවන්, යෝජනා ක්‍රම, වගු සාදන්න

දත්ත සමුදා වස්තු නිර්මාණය කිරීම

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 ;

RLS ක්රියාත්මක කිරීම සඳහා කාර්යයන් නිර්මාණය කිරීම

SELECT පේළි ඉටු කිරීමේ හැකියාව පරීක්ෂා කිරීම

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

පේළි ඇතුල් කිරීමේ හැකියාව පරීක්ෂා කිරීම

check_insert

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; 

පේළියක් මකා දැමීමේ හැකියාව පරීක්ෂා කිරීම

චෙක්_මකන්න

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;

පේළියක් යාවත්කාලීන කිරීමේ හැකියාව පරීක්ෂා කිරීම.

යාවත්කාලීන_භාවිතය

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;

යාවත්කාලීන_පරීක්ෂා කරන්න

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;

වගුවක් සඳහා පේළි මට්ටමේ ආරක්‍ෂක ප්‍රතිපත්තිය සබල කරන්න.

පේළි මට්ටමේ ආරක්ෂාව සබල කරන්න

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

ප්රතිඵලය

එය වැඩ කරනවා.

යෝජිත උපාය මාර්ගය ව්‍යාපාර ක්‍රියාකාරකම් මට්ටමේ සිට දත්ත ගබඩා මට්ටම දක්වා ආදර්ශ ක්‍රියාවට නැංවීමට හැකි විය.

ව්‍යාපාර අවශ්‍යතා සඳහා අවශ්‍ය නම් වඩාත් සංකීර්ණ දත්ත සැඟවීමේ ආකෘති ක්‍රියාත්මක කිරීමට මෙම ක්‍රියාකාරකම් අච්චුවක් ලෙස භාවිතා කළ හැක.

මූලාශ්රය: www.habr.com

අදහස් එක් කරන්න