FirebirdSQL logo
 Управление пользователямиРоли 

Привилегии выполнения SQL кода

Все объекты метаданных содержащие DML или PSQL код могут выполняться в одном из следующих режимов:

  • С привилегиями вызывающего пользователя (привилегии CURRENT_USER);

  • С привилегиями определяющего пользователя (владельца объекта метаданных).

Исторически сложилось, что все PSQL модули по умолчанию выполняются с привилегиями вызывающего пользователя.Начиная с Firebird 4.0 появилась возможность указывать объектам метаданных с какими привилегиями они будут выполняться: вызывающего или определяющего пользователя.Для этого используется предложение SQL SECURITY, которое можно указать для таблицы, триггера, процедуры, функции или пакета.Если выбрана опция INVOKER, то объект метаданных будет выполняться с привилегиями вызывающего пользователя.Если выбрана опция DEFINER, то объект метаданных будет выполняться с привилегиями определяющего пользователя (владельца). Эти привилегии будут дополнены привилегиями выданные самому PSQL модулю с помощью оператора GRANT.

Привилегии выполнения, с которым по умолчанию (не указано у самого модуля) выполняется любой PSQL модуль можно изменить с помощью оператора

ALTER DATABASE SET DEFAULT SQL SECURITY {DEFINER | INVOKER}

Для сохранения обратной совместимости по умолчанию используется опция INVOKER.

Note
Замечания
  • Представления (VIEWs) всегда выполняются с привилегиями определяющего пользователя (владельца);

  • По умолчанию триггеры наследуют привилегии выполнения которые были указаны у таблицы. Привилегии выполнения могут быть переопределены в самом триггере;

  • Процедуры и функции пакета всегда наследуют привилегии выполнения указанный при определении пакета. Привилегии выполнения не могут быть переопределены в самих процедурах и функция пакета;

  • Анонимные PSQL блоки (EXECUTE BLOCK) всегда выполняются с правами вызывающего пользователя.

В хранимых процедурах, функциях и триггерах вы можете проверить эффективного в настоящий момент пользователя, т.е.пользователя с привилегиями которого выполняется текущий модуль, с помощью системной контекстной переменной EFFECTIVE_USER из пространства имён SYSTEM.

select RDB$GET_CONTEXT('SYSTEM', 'EFFECTIVE_USER') from RDB$DATABASE;
Note

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

  • хранимая процедура INV с SECURITY INVOKER, которая вставляет записи в таблицу T;

  • хранимая процедура DEF с SQL SECURITY DEFINER, которая определена пользователем SYSDBA.

Если пользователь U вызывает процедуру INV, то для доступа к таблице T потребуется привилегия INSERT выданная пользователю U (и конечно привилегия EXECUTE для INV). В этом случае U является эффективным пользователем (EFFECTIVE_USER) во время выполнения INV.

Если пользователь U вызывает процедуру DEF, то для доступа к таблице T потребуется привилегия INSERT выданная пользователю SYSDBAEXECUTE на DEF для пользователя U). В этом случае SYSDBA является эффективным пользователем (EFFECTIVE_USER) во время выполнения DEF.Если внутри DEF вызывается процедура INV, то эффективным пользователем по время выполнения INV будет так же SYSDBA.

Примеры

Example 1. Создание таблицы с привилегиями определяющего пользователя

В данном случае пользователю JOE достаточно только привилегии SELECT на таблицу t.Если бы таблица была создана с привилегиями вызывающего пользователя (INVOKER), то ещё потребовалось бы выдать привилегию EXECUTE для таблицы на функцию f.

SET TERM ^;

CREATE FUNCTION f() RETURNS INT
AS
BEGIN
  RETURN 3;
END^

SET TERM ;^

CREATE TABLE t (
  i INTEGER,
  c COMPUTED BY (i + f())
)
SQL SECURITY DEFINER;

INSERT INTO t VALUES (2);

GRANT SELECT ON TABLE t TO USER joe;

COMMIT;

CONNECT 'inet://localhost:test' USER joe PASSWORD 'pas';

SELECT * FROM t;
Example 2. Создание процедуры с привилегиями определяющего пользователя

В данном случае пользователю JOE достаточно только привилегии EXECUTE на процедуру p.Если бы процедура была создана с привилегиями вызывающего пользователя (опция INVOKER), то ещё потребовалось бы выдать привилегию INSERT для процедуры p на таблицу t.

CREATE TABLE t (i INTEGER);

SET TERM ^;

CREATE PROCEDURE p (i INTEGER)
SQL SECURITY DEFINER
AS
BEGIN
  INSERT INTO t VALUES (:i);
END^

SET TERM ;^

GRANT EXECUTE ON PROCEDURE p TO USER joe;

COMMIT;

CONNECT 'inet://localhost:test' USER joe PASSWORD 'pas';

EXECUTE PROCEDURE p(1);
Example 3. Создание функции с привилегиями определяющего пользователя

В данном случае пользователю JOE достаточно только привилегии EXECUTE на функцию f.Если бы функция была создана с привилегиями вызывающего пользователя (опция INVOKER), то ещё потребовалось бы выдать привилегию SELECT для функции f на таблицу t.

CREATE TABLE t (i INTEGER PRIMARY KEY, j INTEGER);

INSERT INTO t(i, j) VALUES(1, 2);
INSERT INTO t(i, j) VALUES(2, 5);

COMMIT;

SET TERM ^;

CREATE FUNCTION f (i INTEGER)
SQL SECURITY DEFINER
AS
  DECLARE j INTEGER DEFAULT NULL;
BEGIN
  SELECT j
  FROM t
  WHERE i = :i
  INTO j;

  RETURN COALESCE(j, 0);
END^

SET TERM ;^

GRANT EXECUTE ON FUNCTION f TO USER joe;

COMMIT;

CONNECT 'inet://localhost:test' USER joe PASSWORD 'pas';

SELECT f(1) AS j FROM RDB$DATABASE;
Example 4. Создание триггера с привилегиями определяющего пользователя

В данном случае пользователю JOE достаточно только привилегии INSERT на таблицу tr.Если бы триггер была создан с привилегиями вызывающего пользователя (опция INVOKER), то ещё потребовалось бы выдать привилегию INSERT для триггера tr_ins на таблицу t.

CREATE TABLE tr (i INTEGER);
CREATE TABLE t (i INTEGER);

SET TERM ^;

CREATE TRIGGER tr_ins FOR tr AFTER INSERT
SQL SECURITY DEFINER
AS
BEGIN
  INSERT INTO t(i) VALUES(NEW.i);
END^

SET TERM ;^

GRANT INSERT ON TABLE tr TO USER joe;

COMMIT;

CONNECT 'inet://localhost:test' USER joe PASSWORD 'pas';

INSERT INTO tr(i) VALUES(2);

COMMIT;

Тот же самый результат можно получить указав SQL SECURITY DEFINER для таблицы tr.

CREATE TABLE tr (i INTEGER) SQL SECURITY DEFINER;
CREATE TABLE t (i INTEGER);

SET TERM ^;

CREATE TRIGGER tr_ins FOR tr AFTER INSERT
AS
BEGIN
  INSERT INTO t(i) VALUES(NEW.i);
END^

SET TERM ;^

GRANT INSERT ON TABLE tr TO USER joe;

COMMIT;

CONNECT 'inet://localhost:test' USER joe PASSWORD 'pas';

INSERT INTO tr(i) VALUES(2);

COMMIT;
Example 5. Удаление привилегий выполнения у триггера
Если триггеру явно установлена опция SQL SECURITY, то, для того чтобы наследовать привилегии выполнения у таблицы, необходимо выполнить следующий оператор.
ALTER TRIGGER tr_ins DROP SQL SECURITY;
Example 6. Создание пакета с привилегиями определяющего пользователя

В данном случае пользователю JOE достаточно только привилегии EXECUTE на пакет pk.Если бы пакет была создана с привилегиями вызывающего пользователя (опция INVOKER), то ещё потребовалось бы выдать привилегию INSERT для пакета pk на таблицу t.

CREATE TABLE t (i INTEGER);

SET TERM ^;

CREATE PACKAGE pk
SQL SECURITY DEFINER
AS
BEGIN
  FUNCTION f(i INTEGER) RETURNS INT;
END^

CREATE PACKAGE BODY pk
AS
BEGIN
  FUNCTION f(i INTEGER) RETURNS INT
  AS
  BEGIN
    INSERT INTO t VALUES (:i);
    RETURN i + 1;
  END
END^

SET TERM ;^

GRANT EXECUTE ON PACKAGE pk TO USER joe;

COMMIT;

CONNECT 'inet://localhost:test' USER joe PASSWORD 'pas';

SELECT pk.f(3) FROM rdb$database;
Example 7. Изменение привилегий выполнения по умолчанию

После выполнения данного оператора PSQL модули по умолчанию будут создаваться с опцией SQL SECURITY DEFINER

ALTER DATABASE SET DEFAULT SQL SECURITY DEFINER;