Детализированный аудит FGA для кодера PL/SQL: безопасность и производительность

Детализированный аудит FGA в PL/SQL для безопасностиДетализированный аудит (FGA, Fine-Grained Auditing) предоставляет механизм для регистрации факта выдачи пользователями определенных команд и выполнения некоторых условий. При этом регистрируется команда, введенная пользователем, а также другая информация: время, терминал и т. д.

Под традиционным аудитом в Oracle понимается механизм регистрации того, какая схема выполнила то или иное действие: пользователь Joe выполняет процедуру X, пользователь John выполнил выборку данных из таблицы Y и т. д. Протокол всех этих действий, называемый журналом аудита, хранится в таблице AUD$ в схеме SYS, доступной для всех пользователей через несколько представлений словаря данных — например, DBA_AUDIT_TRAIL. Журналы аудита также могут записываться в файлы операционной системы вместо таблиц базы данных. Независимо от того, где хранится эта информация, главный недостаток традиционного аудита остается неизменным: он следит за тем, кто выполнил ту или иную команду, а не за тем, что при этом было сделано. Например, из журнала аудита можно узнать, что пользователь Joe получил данные из таблицы ACCOUNTS, но какие именно записи — остается неизвестным. Если вы хотите знать измененные значения, приходится устанавливать для таблиц триггеры DML и сохранять значения в таблице, определенной вами. Но поскольку определить триггер для команды SELECT не удастся, для ситуации с Joe этот вариант не подойдет.


Оглавление статьи[Показать]


На помощь приходит механизм FGA. Функциональность FGA используется через встроенный пакет DBMS_FGA. Механизм FGA, появившийся в Oracle9i Database, изначально применялся только к командам SELECT; начиная с Oracle Database 10g он применяется ко всем командам DML.

Не путайте FGA с FGAC (Fine Grained Access Control) — этот термин является синонимом RLS.

При помощи FGA можно сохранить описания операций SELECT, INSERT, UPDATE и DELETE в журнале аудита (хотя и в другом журнале, не в таблице AUD$). Из журнала вы получите информацию не только о том, кто выполнил ту или иную операцию, но и множество других полезных сведений — точную команду, введенную пользователем, код SCN (System Change Number), значения подставляемых параметров (если они использовались) и многое другое.

Одна из самых полезных особенностей FGA — возможность избирательного применения для конкретных операций. Например, аудит может выполняться при выборке из столбца SAL, но не из других столбцов; или операция может регистрироваться в журнале аудита только при выборке из столбца SAL, и если значение этого столбца не менее 1500. Избирательная регистрация сокращает объем генерируемых данных аудита.

Другая чрезвычайно полезная особенность FGA связана с возможностью автоматического выполнения процедуры, определяемой пользователем. Некоторые практические применения этой возможности описаны в следующих разделах этого блога.

 

Зачем изучать FGA?

FGA — «близкий родственник» традиционного аудита. Безусловно, эта возможность предназначена в первую очередь для администраторов баз данных; зачем же разработчикам PL/SQL изучать ее? Есть несколько причин:

Безопасность. Как уже упоминалось для других возможностей, умение пользоваться встроенными средствами безопасности Oracle в наши дни попросту является одной из составляющих качественного проектирования. Средства FGA должны стать частью вашего инструментария.

Производительность. Другая, более убедительная причина — практическая ценность информации, возвращаемой FGA. Кроме информации о том, кто выполнил ту или иную команду, FGA может точно описать выполненные команды SQL. Если включить FGA для таблицы, то все команды SQL, обращенные к этой таблице, будут сохраняться в журналах аудита FGA. Последующий анализ этой информации поможет выявить закономерности в выполнении команд и решить, не нужно ли добавить или изменить индексы или внести другие изменения, способствующие повышению производительности.

Подставляемые параметры. FGA также сохраняет значения параметров, а в любом нормально спроектированном приложении используется множество подставляемых параметров. Как узнать, какие значения передавались во время запуска приложения? На основании собранной информации вы решите, нужно ли определять дополнительный индекс. Журналы FGA предоставляют сведения, упрощающие принятие таких решений.

Модули-обработчики. FGA также может выполнить процедуру, называемую модулем- обработчиком, при выполнении некоторых условий аудита. Скажем, при включении FGA для команд SELECT модуль-обработчик будет выполняться для каждой команды SELECT, обращенной к таблице. Происходящее напоминает включение триггера для команды SELECTOracle не поддерживает эту возможность, но она может оказаться в высшей степени полезной. Предположим, каждый раз, когда пользователь запрашивает информацию об окладе руководства компании, сообщение должно ставиться в расширенную очередь для последующей передачи в другую базу данных. Для решения этой задачи можно реализовать модуль-обработчик, который будет делать то же самое, что делает триггер для SELECT.

Давайте поближе познакомимся с применением FGA в ваших приложениях.

Для правильной работы FGA база данных должна работать в режиме затратного оптимизатора (CBO), запросы должны использовать CBO (то есть они не должны содержать рекомендации RULE), а таблицы (или представления) в запросе должны быть проанализированы (по крайней мере с оценками). Если эти условия не выполняются, при использовании FGA возможны ложноположительные срабатывания: информация будет записываться в журнал аудита, хотя содержимое столбца на самом деле не выбирается.

 

Простой пример


Начнем с простого примера — таблица EMP из схемы HR уже знакома вам по обсуждению RLS в предыдущем разделе. Предположим, для контроля за использованием конфиденциальной информации вы хотите регистрировать в журнале все операции выборки столбцов SAL и COMM. Чтобы сократить объем генерируемого журнала, регистрироваться будут только операции со строками, в которых оклад составляет $150 000 и более. Наконец, аудит также должен включаться при запросе оклада работника 100 (то есть вас). Разобравшись с требованиями, перейдем к построению архитектуры FGA. Как и в случае с RLS, все начинается с определения политики FGA для таблицы. Политика определяет все условия, в которых должен срабатывать механизм аудита. Для добавления политики используется процедура ADD_P0LICY из встроенного пакета DBMS_FGA:

1 BEGIN
2     DBMS_FGA.add_policy (object_schema        => 'HR',
3                          object_name          => 'EMP',
4                          policy_name          => 'EMP_SEL',
5                          audit_column         => 'SAL, COMM',
6                          audit_condition      => 'SAL >= 150000 OR EMPID = 100'
7                         );
8 END;

Я определяю политику FGA с именем EMP_SEL (строка 4), передавая ее в параметре policy_name. Политика определяется для таблицы EMP (строка 3), владельцем которой является HR (строка 2).

Политика требует сохранять данные в журнале аудита каждый раз, когда пользователь выбирает данные из двух столбцов, SAL и COMM (строка 5). Однако данные сохраняются только в том случае, если значение SAL в этой строке не менее $150 000 или если идентификатор работника равен 100 (условие аудита, строка 6).

Параметры audit_column и audit_condition не являются обязательными. Если они не указаны, то в аудите будет участвовать каждая команда SELECT к таблице EMP схемы HR. Начиная с Oracle Database 10g, поскольку FGA также может применяться и к обычным операциям DML, я могу определять конкретные команды, на которые должна распространяться политика аудита, при помощи нового параметра statement_types:

1    BEGIN
2       DBMS_FGA.add_policy (object_schema        => 'HR',
3                  object_name          => 'EMP',
4                  policy_name          => 'EMP_DML',
5                  audit_column         => 'SALARY, COMM',
6                  audit_condition      => 'SALARY >= 150000 OR EMPID = 100,
7                  statement_types      => 'SELECT, INSERT, DELETE, UPDATE'
8                           );
9    END;

Хотя политика используется и в FGA, и в RLS, она играет совершенно разные роли. Впрочем, имеется и сходство — политика FGA, как и ее «родственник» в RLS, не является «объектом схемы», то есть не принадлежит никакому пользователю. Каждый пользователь, обладающей привилегией EXECUTE для пакета DBMS_FGA, может создавать политики и удалять политики, созданные другим пользователем. Ваш администратор базы данных должен быть очень осмотрительным при предоставлении привилегий EXECUTE для этого встроенного пакета; предоставление привилегии категории PUBLIC делает всю вашу деятельность по аудиту сомнительной — в лучшем случае.

В нашем примере журнал аудита записывается только в том случае, если:

  •  Пользователь получает данные из одного или обоих столбцов, SAL и COMM.
  •  Значение SAL не менее 150 000 или значение EMPID равно 100.

Для сохранения информации в журнале аудита истинными должны быть оба условия. Если одно условие истинно, а другое нет, то операция не регистрируется. Если пользователь в своем запросе не получает либо столбец SAL, либо столбец COMM (прямо или косвенно), то запись в журнале не генерируется, даже если у записи столбец SAL содержит значение 150 000 и более. Предположим, оклад Джейка равен 160 000, а его идентификатор EMPID равен 52. Пользователь, который просто хочет узнать имя руководителя, выдает следующий запрос:

SELECT mgr
  FROM emp
 WHERE empid = 52;

Так как в запросе ни столбец SAL, ни столбец COMM не задействован, операция не регистрируется. Однако запрос:

SELECT mgr
  FROM emp
 WHERE sal >= 160000;

будет зарегистрирован в журнале. Почему? Потому что столбец SAL задействован в секции WHERE, то есть пользователь неявно обращается к нему; следовательно, условие аудита выполнено. Кроме того, значение SAL прочитанных записей больше 150 000. Так как оба условия выполнены, выполняется аудит.

Условие аудита не обязано ссылаться на столбцы таблицы, для которой определена политика; оно также может ссылаться на другие значения (например, псевдостолбцы). Это может быть полезно при включении аудита для некоторого подмножества пользователей. Допустим, вы хотите регистрировать обращения к таблице EMP от пользователя Scott. Политика определяется следующим образом:

BEGIN
   DBMS_FGA.add_policy (object_schema        => 'HR',
                        object_name          => 'EMP',
                        policy_name          => 'EMP_SEL',
                        audit_column         => 'SALARY, COMM',
                        audit_condition      => 'USER=''SCOTT'''
                       );
END;

 

Количество столбцов

В предыдущем примере список столбцов был задан следующим образом:

audit_column    => 'SAL, COMM'

Это означает, что регистрируются все обращения пользователя к столбцу SAL или COMM. Однако в некоторых ситуациях могут действовать более точные требования: обращение ко всем перечисленным столбцам, а не только к одному из них. Например, в базе данных employee механизм FGA должен регистрировать только обращения к SAL и EMPNAME одновременно. Если в запросе задействован только один столбец, операция вряд ли раскроет конфиденциальную информацию. Выполняется следующий запрос:

SELECT salary FROM hr.emp;

Он выводит оклады всех работников, но без указания имен рядом с окладами эта информация окажется бесполезной для пользователя, желающего узнать оклад конкретного работника. Аналогичным образом запрос:

SELECT empname
  FROM hr.emp;

вернет имена работников без окладов, то есть конфиденциальность останется под защитой. Однако при выдаче запроса 

SELECT empname, salary FROM hr.emp;

пользователь узнает, сколько получает каждый из работников — это та самая информация, которую следует защитить.

Из трех показанных случаев запись в журнал аудита должна происходить только для последнего (единственного, для которого запрос вернет содержательную информацию). В Oracle9i Database не было возможности задать комбинацию столбцов как условие аудита; в Oracle Database 10g и выше это стало возможно благодаря параметру audit_ colum_opts процедуры ADD_POLICY. По умолчанию значение параметра равно DBMS_FGA. ANY_COLUMNS, то есть запись в журнал аудита производится при обращении к любому из столбцов. Если же задать параметру значение DBMS_FGA.ALL_COLUMNS, то данные аудита генерируются только при обращении ко всем перечисленным столбцам. В моем примере, чтобы политика FGA создавала запись аудита только при выборке столбцов SALARY и EMPNAME, она должна выглядеть так:

BEGIN
   DBMS_FGA.add_policy (object_schema          => 'HR',
         object_name            => 'EMP',
         policy_name            => 'EMP_DML',
         audit_column           => 'SALARY, EMPNAME',
         audit_condition        => 'USER=''SCOTT''',
         statement_types        => 'SELECT, INSERT, DELETE, UPDATE',
         audit_column_opts      => DBMS_FGA.all_columns
    );
END;

Данная возможность чрезвычайно полезна — она позволяет ограничиться ведением журнала аудита для актуальных операций, чтобы сократить объем данных журнала.

 

Просмотр журнала аудита

Данные аудита FGA записываются в таблицу FGA_LOG$, принадлежащую схеме SYS. Для работы с данными аудита используется внешний интерфейс — представление словаря данных DBA_FGA_AUDIT_TRAIL:

SELECT db_user, sql_text
  FROM dba_fga_audit_trail
 WHERE object_schema = 'HR' AND object_name = 'EMP'

Запрос выдает следующий результат:

DB_USER SQL_TEXT
------- -----------------------------------------------
SCOTT   select salary from hr.emp where empid = 1

Кроме пользователя и команды SQL, в журнале FGA также сохраняются другие полезные сведения. Некоторые важные столбцы представления:

  •  TIMESTAMP — время выполнения операции.
  •  SCN — номер изменения системы при выполнении операции. Для просмотра прошлых SCN используются ретроспективные запросы Oracle.
  •  OS_USER — пользователь операционной системы, подключенный к базе данных.
  •  USERHOST — терминал или клиентский компьютер, с которого подключается пользователь.
  •  EXT_NAME — если пользователь проходит внешнюю аутентификацию (например, средствами LDAP), переданное такому внешнему механизму аутентификации имя становится важным; оно сохраняется в этом столбце.

 

Основные принципы FGA

 


Подставляемые параметры

Описывая FGA, я упомянул о подставляемых параметрах. Давайте посмотрим, как использовать FGA с этими переменными. Предположим, вместо «обычной» команды в форме:

SELECT salary
  FROM emp
 WHERE empid = 100;

был использован блок следующего вида:

DECLARE
   l_empid PLS_INTEGER;
BEGIN
   SELECT salary
     FROM emp
    WHERE empid = l_empid;
END;

FGA сохраняет значения подставляемых параметров вместе с текстом команды SQL. Сохраненные значения находятся в столбце SQL_BIND представления DBA_FGA_AUDIT_TRAIL. В предыдущем примере используется код:

SQL> SELECT sql_text,sql_bind from dba_fga_audit_trail;

SQL_TEXT                                       SQL_BIND
---------------------------------------------- -----------------------
select * from hr.emp where empid = :empid      #1(3):100

Обратите внимание на формат вывода сохраненного параметра:

#1(3):100

Здесь #1 — номер параметра. Если запрос использует более одного подставляемого параметра, то другим будут присвоены номера #2, #3 и т. д. Фрагмент(3) обозначает фактическую длину переменной. В нашем примере пользователь Scott указал значение 100, поэтому длина равна 3. Фрагмент :100 обозначает фактическое значение параметра (100). Если в запросе используется несколько подставляемых параметров, столбец SQL_BIND содержит строку значений. Например, для запроса:

DECLARE
   l_empid    PLS_INTEGER := 100;
   l_salary   NUMBER := 150000;

   TYPE emps_t IS TABLE OF emp%ROWTYPE;
   l_emps     empts_t;
BEGIN
   SELECT * BULK COLLECT INTO l_emps
     FROM hr.emp
    WHERE empid = l_empid OR salary > l_salary;
END;

столбец SQL_BIND будет выглядеть так:

#1(3):100 #2(5):150000

Текст команды SQK и подставляемые параметры сохраняются только в том случае, если параметру audit_trail процедуры ADD_POLICY задано значение DB_EXTENDED (по умолчанию), но не значение DB.

 

Модули-обработчики

Как упоминалось ранее, механизм FGA также позволяет выполнять хранимые программные блоки PL/SQL — например, хранимые процедуры. Если хранимая процедура, в свою очередь, содержит внешнюю программу, эта программа тоже будет выполнена. Хранимая программа называется модулем-обработчиком (handler module). В приведенном ранее примере с построением механизма для аудита обращений к таблице EMP я также мог бы указать хранимую процедуру (отдельную или пакетную), которая должна выполняться при аудите. Если владельцем хранимой процедуры является пользователь FGA_ADMIN и она называется myproc, то процедура создания политики ADD_POLICY будет вызываться с двумя новыми параметрами — handler_schema и handler_module:

BEGIN
   DBMS_FGA.add_policy (object_schema        => 'HR',
              object_name          => 'EMP',
              policy_name          => 'EMP_SEL',
              audit_column         => 'SALARY, COMM',
              audit_condition      => 'SALARY >= 150000 OR EMPID = 100',
              handler_schema       => 'FGA_ADMIN',
              handler_module       => 'MYPROC'
              );
END;

При выполнении условий аудита и обращениях к соответствующим столбцам помимо регистрации операции в журнале также выполняется процедура fga_admin.myproc. Она выполняется автоматически при каждой записи данных аудита в виде автономной транзакции. Процедура получает ровно три параметра — имя схемы, имя таблицы и имя политики. Структура процедуры модуля-обработчика:

PROCEDURE myproc (
   p_table_owner   IN   VARCHAR2,
   p_table_name    IN   VARCHAR2,
   p_fga_policy    IN   VARCHAR2
)
IS
BEGIN
   -- здесь размещается код END;
END;

Как использовать эту возможность? Есть множество вариантов. Например, вы можете построить собственную программу, которая будет сохранять данные в ваших таблицах наряду с записью в стандартные таблицы журналов аудита. Можно записывать сообщения в очереди для размещения в других базах данных, запросить отправку электронной почты администраторам по безопасности, просто подсчитать количество выполнений условий аудита... Словом, возможности безграничны.

Если при выполнении модуля-обработчика происходит какая-либо ошибка, FGA не сообщает об ошибке при запросе данных из таблицы. Вместо этого FGA просто прекращает выборку строк, для которых выполнение модуля-обработчика завершилось неудачей. Это коварная ситуация, потому что вы не узнаете о возникновении ошибки, однако возвращение лишь части строк приводит к ошибочным результатам. По этой причине важно особенно тщательно тестировать модули-обработчики.

Вас заинтересует / Intresting for you:

Управление приложениями PL/SQL...
Управление приложениями PL/SQL... 1462 просмотров Rasen Fasenger Mon, 22 Oct 2018, 04:44:08
Встроенные методы коллекций PL...
Встроенные методы коллекций PL... 2166 просмотров sepia Tue, 29 Oct 2019, 09:54:01
Тип данных RAW в PL/SQL
Тип данных RAW в PL/SQL 1707 просмотров Doctor Thu, 12 Jul 2018, 08:41:33
Символьные функции и аргументы...
Символьные функции и аргументы... 3338 просмотров Анатолий Wed, 23 May 2018, 18:54:01


OraCool аватар
OraCool ответил в теме #9510 08 окт 2019 05:43
Если вы используете удаленную проверку зависимостей на базе сигнатур при удаленных вызовах процедур, создайте процедуры для устранения возможности ложноотрицательных срабатываний (приводящих к ошибке времени выполнения).
Oracle_Admin аватар
Oracle_Admin ответил в теме #9472 28 сен 2019 13:38
Fasenger, ты крут! Тема раскрыта на 100% Добавил в закладки эту статью. Маст хэв)

Comments on Детализированный аудит FGA для кодера PL/SQL: безопасность и производительность

Будьте первым прокомментировавшим
Пожалуйста, авторизуйтесь, для комментирования