Почему разрешения PostgreSQL ведут себя по-разному между ограничениями Trigger и Check? - PullRequest
0 голосов
/ 04 апреля 2020

У меня сейчас база данных с двумя схемами app_private & app_publi c (в дополнение к схеме publi c по умолчанию). У меня также есть роль, которой предоставлено использование в схеме app_publi c, но не в схеме app_private . Я также использую две функции (одну функцию триггера и одну функцию проверки ограничений) в таблице.

См. Ниже код:

(1) Создание схем (и grants)

CREATE SCHEMA app_public;
CREATE SCHEMA app_private;

grant usage on schema public, app_public to "grant_test_role";

(2) Отменить гранты от пользователя PUBLI C

Тогда у меня есть специальное заявление DDL. Предполагается, что REVOKE разрешений для любой вновь добавленной функции из пользовательской роли publi c (от которой наследуются все другие роли).

alter default privileges revoke all on functions from public;

(3) Функция Определения (Trigger & Constraint)

-- Trigger Function
create OR replace function app_private.tg__timestamps() returns trigger as $$
begin
  NEW.created_at = (case when TG_OP = 'INSERT' then NOW() else OLD.created_at end);
  NEW.updated_at = (case when TG_OP = 'UPDATE' and OLD.updated_at >= NOW() then OLD.updated_at + interval '1 millisecond' else NOW() end);
  return NEW;
end;
$$ language plpgsql volatile set search_path to pg_catalog, app_private, public, pg_temp;

-- Constraint Function
CREATE OR REPLACE FUNCTION app_private.constraint_max_length(
  value text,
  maxLength integer,
  error_message text default 'The value "$1" is too long. It must be maximum $2 characters long.',
  error_code text default 'MXLEN'
) RETURNS boolean
  AS $$
begin
  if length(value) > maxLength then
    error_text = replace(replace(error_message, '$1', value), '$2', maxLength);
    raise exception '%', error_text using errcode = error_code;
  end if;
  return true;
end;
$$ LANGUAGE plpgsql set search_path to pg_catalog, app_private, public, pg_temp;

(4) Таблица Definition (которая использует вышеуказанные функции Trigger & Constraint)

create table app_public.test_tab (
   id INT not null primary key,
   name text not null,
   created_at timestamptz not null default now(),
   updated_at timestamptz not null default now(),

   constraint name_length_check check (app_private.constraint_max_length(name, 5));
);

create trigger _100_timestamps
before insert or update on app_public.test_tab
for each row
execute procedure app_private.tg__timestamps();

-- Setting some restrictions on the test_tab for the "grant_test_role"
REVOKE ALL ON TABLE app_public.test_tab FROM "grant_test_role";
GRANT SELECT, DELETE ON app_public.test_tab TO "grant_test_role";
GRANT
INSERT(id, name),
UPDATE(id, name) ON app_public.test_tab TO "grant_test_role";

(5) Код (который работает как grant_test_role )

begin;
  set local role to grant_test_role;
  insert into app_public.test_tab (id, name) values (1, 'Very Long Name');
commit;

Я пытаюсь выполнить это в свободной sh БД каждый раз, чтобы я мог понять, как * Разрешения 1068 * работают в различных контекстах вызова (например, функция триггера, проверка ограничений, которая вызывает функцию автоматически, и т. Д. c.)

Когда у меня нет блока кода (2), который отзывает разрешения функций из Пользователь PUBLI C, блок кода (5) выполняется без ошибок. Событие, хотя роль пользователя не имеет прав доступа к схеме app_private , в которой существует функция триггера и функция ограничения. Но при наличии блока кода (2) код выполняет триггер просто отлично, но дает мне "permission denied for function constraint_max_length" для ограничения проверки.

Итак, я пытаюсь понять,

  1. Каким образом функция триггера, которая существует в схеме, где роль пользователя не имеет разрешений на использование, всегда выполняется успешно?
  2. Если функция триггера выполняется, почему функция ограничения CHECK дает мне вышеуказанное ошибка отказа в разрешении?
  3. Что на самом деле делает блок кода (2)?

Я изо всех сил пытаюсь найти документацию о том, как разрешения применяются в этом виде "авто выполнил «сценарий ios (триггеры / ограничения)», поскольку пользователь не «явно» вызывает эти функции, скорее они автоматически вызываются БД. Поэтому я не уверен, какая роль выполняет их.

1 Ответ

2 голосов
/ 06 апреля 2020

Я отправил этот вопрос в список рассылки PostgreSQL и, наконец, получил ответ.

Итак, на данный момент, как работает PostgreSQL (будь он совместим с SQL spe c или нет:)

Оригинальная почтовая нить - https://www.postgresql.org/message-id/CANYEAx8vZnN9eeFQfsiLGMi9NdCP0wUdriHTCGU-7jP0VmNKPA%40mail.gmail.com


Функции триггера

  • Права доступа к функции триггера проверяются в " время создания против роли, которая их создает.
  • Во время выполнения привилегии для функции триггера вообще не проверяются относительно исполняющей роли, а просто способность анализировать.
  • Операторы внутри функции триггера будет go с помощью обычных проверок привилегий для исполняющей роли

Проверка функций ограничения

  • Проверка привилегий функции ограничения проверяются при "создании" время против роли, которая их создает.
  • Во время выполнения схема функции ограничения проверяется только на «возможность анализа». Как в случае, если такая схема существует, но нет, если она доступна.
  • Однако во время выполнения сама функция (независимо от схемы, в которой она существует) проверяется на наличие привилегий для исполняющей роли.

Так что это объясняет поведение, с которым я столкнулся в PostgreSQL

...