FirebirdSQL logo

Вторым уровень модели обеспечения безопасности Firebird являются SQL привилегии.После успешного входа в систему (первый уровень), авторизованный пользователь получает доступ к серверу и ко всем базам данных этого сервера, но это не означает, что он имеет доступ к любым объектам в любой базе данных.После создания объекта, только пользователь создавший объект (его владелец) и администраторы имеют доступ к нему.Пользователю необходимы привилегии на каждый объект, к которому он должен получить доступ.Как правило, привилегии должны быть предоставлены явно пользователю владельцем объекта или администратором базы данных.

Привилегия включает тип DML доступа (SELECT, INSERT, UPDATE, DELETE, EXECUTE и REFERENCES), имя объекта базы данных для которого предоставляется привилегия (таблица, представление, процедура или роль) и имя объекта которому предоставляется привилегия (пользователь, процедура, триггер, роль). Существуют различные способы для предоставления нескольких типов доступа на один объект базы данных сразу нескольким пользователям в одном операторе GRANT.Привилегии могут быть отозваны с помощью оператора REVOKE.

Все привилегии по доступу к объектам базы данных хранятся в самой базе, и не могут быть применены к любой другой базе данных.

Владелец объекта базы данных

Пользователь, создавший объект базы данных, становится его владельцем.Только владелец объекта и пользователи с правами администратора в базе данных могут изменить или удалить объект базы данных.Владелец базы данных, то есть пользователь, который создал её, имеет все права на объекты, которые были созданы другими пользователями.

Администраторы или владелец объекта могут выдавать привилегии другим пользователям, в том числе и привилегии на право выдачи привилегий другим пользователям.Собственно сам процесс раздачи и отзыва привилегий на уровне SQL реализуется двумя операторами: GRANT, REVOKE.

Привилегии выполнения 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;