RDS 上的 Postgres 13 pg_cron 错误难以追踪

Postgres 13 pg_cron error on RDS that's hard to track down

pg_cron 作业全部失败并显示“...的角色不提供安排作业的权限”

我正在努力在 RDS 上设置 pg_partmanpg_cron,但是当我的 pg_cron 工作 运行 时,他们 return 这个错误:

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

从错误文本来看,似乎我遗漏了一个关于目录或资源中某些内容的简单权限问题或资源 pg_cron,但我找不到问题的根源。而且,它可能是别的东西。大量的谷歌搜索、资源搜索和反复试验并没有让我找到任何答案,我希望得到帮助。

对于背景,这是带有 pg_cron 1.3 的 Postgres 13.4。这些是 RDS 上现在可用的最新版本。我的目标是在此集群中的各种数据库中拥有 pg_cron 运行ning 作业,但我已将问题示例简化为 postgres.[=44 中的 cron 模式=]

RDS 定义了一个名为 rds_superuser 的角色,它没有登录名,然后您可以将其发送给其他用户。运行t。我们正在使用一个名为 rds_super 的自定义角色,并且使用了多年。

当您 create extension pg_cron 在 RDS 上启动时,默认情况下安装到 postgres 数据库,并创建一个名为 cron 的新架构。没关系。作为该问题的“hello world”版本,这里有一个简单的 table 任务,即每分钟将当前时间插入文本字段。

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) $$);

当以 rds_super 用户身份直接连接时,裸语句 INSERT INTO cron.foo VALUES (now()::text) 工作正常。但是当它通过上面定义的 cron.job 执行时,cron.job_run_details 输出有正确的代码,预期的用户,但是失败的结果是这个错误:

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

这是否为任何人敲响了警钟?我已经删除,重新安装,明确设置权限。没有改善。

Public

这可能已关闭,但我 运行 进行了一些看起来我需要提供对 public 的访问的事情。我从 PG 9.4 或 9.5 开始,无法集中精力保护 public... 并在所有地方剥夺了它的所有权利。这里可能需要放回一些?

权限检查

以下是我能想到的权限检查。

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;

我给了用户对所有 table 的所有权限,只是想看看是否解决了问题。不开心。

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

模式权限没有明显错误:

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

同样,当我检查函数执行权限时没有弹出任何内容:

   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';

我注意到后台工作人员已经 运行ning 一天多了(它作为共享库加载),似乎卡住了。我重新启动了服务器,并重新登录了 dbadmin 的所有内容,而不是我的自定义用户。在本例中,这是 pg_cron scheduler 进程 运行ning 作为的用户名。我不记得 dbadmin 是否是 RDS Postgres 软件包的一部分,或者它是否是我几年前添加的。 RDS pg_cron 说明中没有关于此的任何内容,所以也许只有我一个人。我需要设置它的 search_path 和一些权限才能让一切按我需要的方式工作,但这是正常的。

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

至少在我的例子中,答案是 运行 作为与 pg_cron 后台线程相同的用户的作业。我已经在原始问题的末尾发布了更多详细信息。