Postgres 大对象和多用户

Usa*_*oot 6 postgresql users

问题

动态创建的用户无法查询包含大对象的表,因为它最初不是创建的。


背景

我有一个跨2 个实例部署到 AWS 的 Java Atom Hopper 应用程序,这两个实例都使用托管在 RDS 中的Postgres 9.5.2数据库。

保险库凭证

数据库凭据存储在Vault 中,它为 Postgres 中的数据库生成新的登录名和密码。此用户是使用以下权限创建的。

CREATE ROLE "{{name}}" WITH INHERIT LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}';GRANT ALL PRIVILEGES on DATABASE "DATABASE_NAME" to "{{name}}";GRANT databaserole to "{{name}}";
Run Code Online (Sandbox Code Playgroud)

这意味着每次 Java 应用程序启动时,它都会向Vault发送请求,以获取新的用户名和密码。

eg. username: token-1234-5678
=> \du

       Role name     |                  Attributes                   |   Member of
    -----------------+-----------------------------------------------+----------------
    token-1234-5678  |  Password valid until 2016-09-11 09:57:14+00  | {databaserole} (java instance 1)
    token-abcd-efgh  |  Password valid until 2016-09-11 09:57:14+00  | {databaserole} (java instance 2)
Run Code Online (Sandbox Code Playgroud)

数据库里面的表都归 databaserole

Schema |          Name           | Type  |     Owner
-------+-------------------------+-------+----------------
public | table1                  | table | databaserole
public | table2                  | table | databaserole
public | entries                 | table | databaserole
Run Code Online (Sandbox Code Playgroud)

插入数据

当我在表条目中插入新行时,其中一个字段太大,因此转换为Large Object,但其所有者设置为插入它的应用程序的登录名,而不是database role.

=> \lo_list
            Large objects
  ID   |     Owner       | Description
-------+-----------------+-------------
 17286 | token-1234-5678 |
Run Code Online (Sandbox Code Playgroud)

作为实例 2 上的 Java 应用程序,具有与实例 1 不同的登录名,例如。token-abcd-efgh,这意味着它不能执行,select * from entries;因为它不是大对象的所有者。

我知道我可以在创建对象后更改它的所有者,但由于插入次数的原因,这是不可行的。


如何设置它以便任何大型对象都拥有databaserole创建它的应用程序的所有者而不是登录名?


TLDR

因为我有一个应用程序的多个实例,具有唯一且动态创建的登录名。如何设置 Postgres 以便大型对象始终拥有角色的成员父级的所有权,以便作为该父级角色成员的任何登录都可以查看该对象?


解决了

每次休眠尝试在该表上插入时,我都添加了另一个事务来运行以下 sql。

SET ROLE databaserole
Run Code Online (Sandbox Code Playgroud)

Mat*_*sOl 6

一种选择是SET ROLE在打开从应用程序到以下内容的连接后使用命令databaserole

SET ROLE databaserole;
Run Code Online (Sandbox Code Playgroud)

通过这种方式,在此会话中创建的任何对象(包括大对象)都将由databaserole而不是token-XXX.

另一种选择是LOCAL仅在用于创建大对象的事务中使用并使其工作:

BEGIN;
SET LOCAL ROLE databaserole;
-- create and insert the large object
COMMIT;
Run Code Online (Sandbox Code Playgroud)

或者,您可以直接将角色设置为用户设置:

ALTER ROLE "{{name}}" SET role TO 'databaserole';
Run Code Online (Sandbox Code Playgroud)

我有点不喜欢这个选项,因为它的工作方式对其他人来说可能变得有点模糊,如果您为用户管理其他角色,它不会继承它们(尽管这对您来说似乎不是问题,就像动态创建的用户,您应该有一个它直接继承的角色)。