postgres 创建可以选择表和这些表的列的有限用户

as.*_*ieu 7 postgresql permissions scripting users postgresql-9.6

我有一个应用程序,可以自动创建 PostgreSQL 数据库,还可以自动创建数据库用户。出于安全目的,该数据库用户被授予有限的访问权限,因为它将被移交给客户端使用。 我使用的版本是Postgres 9.6

CREATE USER %USERSETUP% WITH
    LOGIN PASSWORD '%USERSETUPPASS%'
    NOSUPERUSER
    NOCREATEDB
    NOCREATEROLE
    INHERIT
    NOREPLICATION
    CONNECTION LIMIT -1;

ALTER DEFAULT PRIVILEGES IN SCHEMA %SCHEMA% GRANT INSERT, SELECT, UPDATE, DELETE, REFERENCES ON TABLES TO %USERSETUP%;
Run Code Online (Sandbox Code Playgroud)

现在,我的测试还进入创建的数据库,并验证它是否已正确创建,使用查询脚本获取表名称,然后获取每个表内的列名称(作为奖励,还获取列数据类型

由于这些权限,用户无法使用 information_schema。 另外,我只请求带有 SYSTEM CATALOG 的查询脚本

我的表名脚本有效:

SELECT tablename FROM pg_catalog.pg_tables where schemaname = '{schema}'
Run Code Online (Sandbox Code Playgroud)

这将表名称作为列表返回:

业务、位置、人员、客户等...

但是,当我运行以下两个脚本来获取列名称时,我得到的返回值为 0,就好像该用户正在尝试查询 information_schema 一样。我猜这是因为特权:

SELECT c.oid,
  n.nspname,
  c.relname
FROM pg_catalog.pg_class c
     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE c.relname ~ 'schemaaryzdhyqoi'
  AND pg_catalog.pg_table_is_visible(c.oid)
ORDER BY 2, 3;
Run Code Online (Sandbox Code Playgroud)

SELECT c.oid,
  n.nspname,
  c.relname, t.*
FROM pg_catalog.pg_class c
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
CROSS JOIN LATERAL (
  SELECT a.attname,
    pg_catalog.format_type(a.atttypid, a.atttypmod),
    (
      SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128)
      FROM pg_catalog.pg_attrdef d
      WHERE d.adrelid = a.attrelid
        AND d.adnum = a.attnum
        AND a.atthasdef
    ),
    a.attnotnull, a.attnum,
    (
      SELECT c.collname
      FROM
        pg_catalog.pg_collation c,
        pg_catalog.pg_type t
      WHERE c.oid = a.attcollation
        AND t.oid = a.atttypid
        AND a.attcollation <> t.typcollation
    ) AS attcollation
  FROM pg_catalog.pg_attribute a
  WHERE a.attrelid = c.oid
    AND a.attnum > 0
    AND NOT a.attisdropped
) AS t
WHERE n.nspname ~ '^(schemaaryzdhyqoi)$'  -- YOUR SCHEMA HERE
AND pg_catalog.pg_table_is_visible(c.oid);
Run Code Online (Sandbox Code Playgroud)

问题是:如何添加受限用户的权限,以便也能够仅访问模式中每个表内的列的名称(可能还有数据类型)?

dez*_*zso 8

您可以将列级别权限设置为非常具体(且严格)地允许其他无权限的用户访问数据。就您而言,它是两个目录:pg_attributepg_type

\n\n

我有一个名为的用户alice,他与您的用户受到类似的限制:

\n\n
alice@test=> > SELECT * FROM pg_class LIMIT 1;\nERROR:  permission denied for relation pg_class\n
Run Code Online (Sandbox Code Playgroud)\n\n

发表以下GRANT声明:

\n\n
GRANT SELECT (oid, typname) ON pg_type TO alice;\nGRANT SELECT (attrelid, attname, atttypid, attnum) ON TABLE pg_attribute TO alice;\n
Run Code Online (Sandbox Code Playgroud)\n\n

在这些之后,alice可以执行以下操作,例如:

\n\n
SELECT attname, typname \n  FROM pg_attribute JOIN pg_type t ON t.oid = atttypid\n WHERE attrelid = 't2'::regclass AND attnum > 0;\n\n attname \xe2\x94\x82 typname \n\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xbc\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n key     \xe2\x94\x82 jsonb\n value   \xe2\x94\x82 jsonb\n
Run Code Online (Sandbox Code Playgroud)\n\n

您可以轻松扩展权限以满足您的需求。

\n