【问题标题】:Postgres row-level security for anonymous block scriptsPostgres 匿名块脚本的行级安全性
【发布时间】:2020-03-30 15:05:44
【问题描述】:

我正在开发一款使用 Postgres 作为后端的游戏。我一直在努力解决的功能之一是允许玩家编写游戏玩法的某些方面的脚本。这些脚本将存储在一个表(文本列)中,并且在每一轮结束时,这些脚本将由一个存储过程执行。

我可以从该表中选择脚本代码并使用如下语句运行它:

do [script-code-here] language whatever-pl-language; 
--haven't decided which languages to allow, might give them choice of several

运行这些的存储过程将在适当的 postgres 角色下运行代码,该角色被锁定并具有足够的授权,它们只能影响它们应该能够影响的表(和列)。但是当然,其他玩家的数据会在同一张表中,所以我需要行级别的安全性,以便他们能够更新/删除/插入自己的行,而不会欺骗和修改对手的行。

Postgres 文档中的create policy 示例很少。我一直找不到一个不能简单检查 x = current_user 的 USING 子句(current_user 是代码运行的角色)。

如果我在脚本表中有一个 player_id 列,并且在所有其他表中脚本将被允许影响,有没有办法制定一个 create policy 语句,不会强迫我创建一个新的 postgres每个玩家的角色(其中可能有任意高的数字)?匿名代码块可以(例如)将一些变量设置为正在运行的脚本的 player_id,除了 set 语句可以设置自定义参数或变量。我也找不到一个可以重新调整用途并设置为这个值的不重要的值(它甚至看起来不像它们可以在 plsql 中引用)。

是否有一些功能或技巧可以让我使用我描述的表格/列来制定create policy 语句,而无需为每个玩家创建新角色? Postgres 扩展解决方案非常受欢迎。

【问题讨论】:

    标签: postgresql stored-procedures row-level-security


    【解决方案1】:

    您可以创建一个 C 扩展来引入一个新的数据库参数,该参数只能设置一次,如果您尝试修改它会引发错误。为此,您将创建一个 _PG_init 函数,该函数使用适当的检查函数调用 DefineCustomStringVariable。确保将生成的模块添加到shared_preload_libraries,以便始终定义参数。

    然后您可以在播放器连接后立即设置参数,并且可以使用策略定义中的current_setting 函数来检索当前设置。

    但我认为整个想法都是错误的。我永远不会允许用户在我的数据库中运行任意 SQL 语句。对于任何用户来说,通过占用 CPU 或用随机数据填充文件系统来对数据库发起拒绝服务攻击都是微不足道的。除非您删除架构 public FROM PUBLIC 上的 CREATE 权限,否则攻击者可能还会创建对象并造成更大的危害。

    SQL 太强大了,你可以合理地限制它。

    【讨论】:

    • 我打算将它们锁定到一个模式,并且只锁定那些允许它们添加到的表。行级安全性是将其限制为允许他们访问的行(毕竟是这个问题)。如果有人对数据库进行核武器攻击,那只是一场游戏。我在原木中挖掘,找到它们,然后对它们进行敲击。数据库就是这里的游戏。权限方案的重点是我可以将它们限制为仅我想要的那些对象,不是吗?
    • 如果您不介意用户关闭您的数据库,请继续。
    • 这就是游戏。数据库是一个 docker 容器,它只是一个网页游戏。游戏玩家通常是混蛋,混蛋有时会通过拒绝服务攻击游戏。不管这个功能如何,它都会发生,但是如果没有这个功能,游戏就不会很有趣……在游戏之外实现这个功能会出现性能问题,这会让它变得不好玩。
    猜你喜欢
    • 2017-07-05
    • 2019-05-10
    • 2017-07-23
    • 1970-01-01
    • 1970-01-01
    • 2017-05-02
    • 2020-10-25
    • 1970-01-01
    • 2011-11-19
    相关资源
    最近更新 更多