严格控制PostgreSQL中的statement_timeout变量

发布于 2024-10-19 16:03:30 字数 657 浏览 2 评论 0 原文

有谁知道如何限制用户设置变量的能力?具体来说statement_timeout?

无论我是否更改用户将此变量设置为一分钟,或者是否在 postgresql.conf 文件中将其设置为一分钟,用户始终只需键入 SET statements_timeount TO 0;完全禁用该会话的超时。

有人知道有什么方法可以阻止这种情况吗?我知道有些变量只能由超级用户更改,但我无法弄清楚是否有办法强制它成为这些受控变量之一。或者,有没有办法撤销 SET 的角色?

在我的应用程序中,此变量用于限制随机用户(用户注册向公众开放)通过(接近)无限查询耗尽所有 CPU 时间的能力。如果他们可以禁用它,那么这意味着我必须找到一种新的方法来限制用户的资源。如果没有方法来保护这个变量,您是否可以建议其他方法来实现相同的目标?

编辑2011-03-02 数据库向公众开放并允许任意SQL的原因是因为该项目是直接在数据库中玩的游戏。每个玩家都是数据库用户。数据被锁定在视图、规则和触发器后面,CREATE 被从公共和玩家角色中撤销,以防止对架构进行大多数更改,并且删除 pg_proc 上的 SELECT 以保护游戏敏感的函数代码。

这不是我向世界开放的某个关键任务系统。这是一个奇怪的概念证明,它对数据库施加了异常程度的信任,试图将整个中央情报局安全三角维持在其中。

感谢您的帮助, 摘要

Does anybody know how to limit a users ability to set variables? Specifically statement_timeout?

Regardless of if I alter the user to have this variable set to a minute, or if I have it set to a minute in the postgresql.conf file, a user can always just type SET statement_timeount TO 0; to disable the timeout completely for that session.

Does anybody know a way to stop this? I know some variables can only be changed by a superuser but I cannot figure out if there is a way to force this to be one of those controlled variables. Alternatively, is there a way to revoke SET from their role?

In my application, this variable is used to limit the ability of random users (user registration is open to the public) from using up all the CPU time with (near) infinite queries. If they can disable it then it means that I must find a new methodology for limiting resources to users. If there is no method for securing this variable, is there other ways of achieving this same goal that you may suggest?

Edit 2011-03-02
The reason the database is open to the public and arbitrary SQL is allowed is because this project is for a game played directly in the database. Every player is a database user. Data is locked down behind views, rules and triggers, CREATE is revoked from public and the player role to prevent most alterations to the schema and SELECT on pg_proc is removed to secure game-sensitive function code.

This is not some mission critical system I have opened up to the world. It is a weird proof of concept that puts an abnormal amount of trust in the database in an attempt to maintain the entire CIA security triangle within it.

Thanks for your help,
Abstrct

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

青衫负雪 2024-10-26 16:03:30

没有办法覆盖这个。如果您允许用户运行任意 SQL 命令,那么更改 statements_timeout 无论如何只是冰山一角...如果您不信任您的用户,则不应让他们运行任意 SQL - 或接受他们可以运行,好吧,任意SQL。并且有某种外部监视器可以取消查询。

There is no way to override this. If you allow the user to run arbitrary SQL commands, changing the statement_timeout is just the top of the iceberg anyway... If you don't trust your users, you shouldn't let them run arbitrary SQL - or accept that they can run, well, arbitrary SQL. And have some sort of external monitor that cancels the queries.

倾听心声的旋律 2024-10-26 16:03:30

基本上你不能在普通的 postgres 中做到这一点。
同时为了实现您的目标,您可以使用某种类型的代理并重写/禁止某些查询。

有几种解决方案,例如:

  1. db-query-proxy - 文章它是如何诞生的(俄语)。
  2. BGBouncer + pgbouncer-rr-patch

最后包含非常 有用的例子,在Python上做起来非常简单:

import re
def rewrite_query(username, query):
    q1="SELECT storename, SUM\(total\) FROM sales JOIN store USING \(storeid\) GROUP BY storename ORDER BY storename"
    q2="SELECT prodname, SUM\(total\) FROM sales JOIN product USING \(productid\) GROUP BY prodname ORDER BY prodname"
    if re.match(q1, query):
        new_query = "SELECT storename, SUM(total) FROM store_sales GROUP BY storename ORDER BY storename;"
    elif re.match(q2, query):
        new_query = "SELECT prodname, SUM(total) FROM product_sales GROUP BY prodname ORDER BY prodname;"
    else:
        new_query = query
    return new_query

Basically you can't do this in plain postgres.
Meantime for accomplish your goal you may use some type of proxies and rewrite/forbidd some queries.

There several solutions for that, f.e.:

  1. db-query-proxy - article how it born (in Russian).
  2. BGBouncer + pgbouncer-rr-patch

Last contains very useful examples and it is very simple do on Python:

import re
def rewrite_query(username, query):
    q1="SELECT storename, SUM\(total\) FROM sales JOIN store USING \(storeid\) GROUP BY storename ORDER BY storename"
    q2="SELECT prodname, SUM\(total\) FROM sales JOIN product USING \(productid\) GROUP BY prodname ORDER BY prodname"
    if re.match(q1, query):
        new_query = "SELECT storename, SUM(total) FROM store_sales GROUP BY storename ORDER BY storename;"
    elif re.match(q2, query):
        new_query = "SELECT prodname, SUM(total) FROM product_sales GROUP BY prodname ORDER BY prodname;"
    else:
        new_query = query
    return new_query
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文