Ошибка Postgres 13 pg_cron на RDS, которую трудно отследить

#postgresql #amazon-rds #pg-cron

Вопрос:

все задания pg_cron завершаются с ошибкой «роль….не предоставляет разрешения на планирование задания».

Я работаю над получением pg_partman и pg_cron настройкой RDS, но когда мои pg_cron задания выполняются, они возвращают эту ошибку:

 ERROR: The protected role of rds_super doesn't provide permission to schedule a job.
 

Из текста ошибки кажется, что мне не хватает простой проблемы с разрешениями на что-то в каталоге или ресурсах pg_cron , но я не могу найти источник проблемы. И, возможно, это что-то еще. Много поисков в Интернете, поиск источников и проб и ошибок не привели меня ни к каким ответам, и я надеюсь на помощь.

Для справки, это Postgres 13.4 с pg_cron 1.3. Это последние версии, которые теперь доступны на RDS. Моя цель состоит в том, чтобы pg_cron выполнять задания в различных базах данных в этом кластере, но я свел пример проблемы к cron схеме в postgres .

RDS определяет роль с именем rds_superuser , у которой нет имени входа, которое затем можно предоставить другим пользователям. Мы используем пользовательскую роль с именем rds_super , и так было уже много лет.

Когда вы create extension pg_cron подключаетесь к RDS, установка postgres по умолчанию выполняется в базе данных, и она создает новую схему с именем cron . Все это прекрасно. В качестве версии проблемы «привет, мир», вот простая таблица и задача для вставки текущего времени каждую минуту в текстовое поле.

 DROP TABLE IF EXISTS cron.foo;

CREATE TABLE IF NOT EXISTS cron.foo (
    bar text
);

GRANT INSERT ON TABLE cron.foo TO rds_super;

INSERT INTO cron.foo VALUES (now()::text);

select * from cron.foo;

-- Run every minute
SELECT cron.schedule('postgres.populate.foo','*/1 * * * *',
$INSERT INTO cron.foo VALUES (now()::text) $);
 

Голый оператор INSERT INTO cron.foo VALUES (now()::text) отлично работает при подключении непосредственно от имени rds_super пользователя. Но когда он выполняется с помощью cron.job указанного выше, cron.job_run_details вывод имеет правильный код, ожидаемого пользователя, но результат сбоя с этой ошибкой:

 ERROR: The protected role of rds_super doesn't provide permission to schedule a job.
 

Это кому-нибудь о чем-то говорит? Я удалил, переустановил, явно установил разрешения. Никаких улучшений.

Общественный

Это может быть выключено, но я столкнулся с парой вещей, к которым, похоже, мне нужно было предоставить доступ public . Я начал с 9.4 или 9.5 страницы, не мог сосредоточиться на обеспечении безопасности общественности…и лишил ее всех прав везде. Может быть, здесь понадобится положить немного обратно?

Permissions checks

Here are the permissions checks that I could think of.

 select grantor,
       grantee,
       table_schema,
       table_name,
       string_agg (privilege_type, ',' order by privilege_type) as grants

  from information_schema.role_table_grants
where table_catalog = 'postgres'
  and table_schema  = 'cron'
  and grantee       = 'rds_super'

group by 1,2,3,4

order by 1,2,3,4;
 

I gave the user all privileges on all of the tables, just to see if that cleared things up. No joy.

 grantor          grantee     table_schema  table_name             grants
rds_super        rds_super   cron          foo                    DELETE,INSERT,REFERENCES,SELECT,TRIGGER,TRUNCATE,UPDATE
rds_super        rds_super   cron          job_run_details_plus   DELETE,INSERT,REFERENCES,SELECT,TRIGGER,TRUNCATE,UPDATE
rds_superuser    rds_super   cron          job                    DELETE,INSERT,REFERENCES,SELECT,TRIGGER,TRUNCATE,UPDATE
rds_superuser    rds_super   cron          job_run_details        DELETE,INSERT,REFERENCES,SELECT,TRIGGER,TRUNCATE,UPDATE
 

Nothing is obviously wrong with the schema rights:

 select pg_catalog.has_schema_privilege('rds_super', 'cron', 'CREATE') AS create,
       pg_catalog.has_schema_privilege('rds_super', 'cron', 'USAGE')  AS usage;

create  usage
t       t
 

Likewise, nothing pops out when I check function execution rights:

    select proname, proargnames
     from pg_proc
    where has_function_privilege('rds_super',oid,'execute')
      and pronamespace::regnamespace::text = 'cron'
order by 1,2


proname                  proargnames
job_cache_invalidate
schedule                 {job_name,schedule,command}
schedule                 {schedule,command}
unschedule               {job_id}
unschedule               {job_name}
 

Ответ

Я не знаю, является ли это ответом, но, похоже, он решил мою проблему. Спойлер: Войдите в систему от имени пользователя pg_cron scheduler , от имени которого работает фоновый работник.

Я сжег все дотла и перезапустил, а затем обнаружил, что мои задания просто не будут выполняться. Ни ошибок, ни результатов. Я проверил статус фоновых работников следующим образом:

  select application_name,
        usename,
        backend_type,
        query,
        state,
        wait_event_type,
        age(now(),backend_start) as backend_start_age,
        age(now(),query_start)  as query_start_age,
        age(now(),state_change) state_change_age

  from pg_stat_activity
 where backend_type != 'client backend';
 

Я заметил, что фоновый рабочий работал более суток (он загружен как общая библиотека) и, похоже, застрял. Я перезагрузил сервер и переделал все, что вошло в систему как dbadmin , вместо моего пользовательского пользователя. В данном случае это имя пользователя, под которым pg_cron scheduler выполняется процесс. Я не помню dbadmin , является ли это частью пакета с RDS Postgres, или это что-то, что я добавил много лет назад. В pg_cron инструкциях RDS об этом ничего нет, так что, может быть, это только я. Мне нужно было немного настроить его search_path и разрешения, чтобы все работало так, как мне нужно, но это нормально.

https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/PostgreSQL_pg_cron.html

Ответ №1:

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