【问题标题】:What does GRANT USAGE ON SCHEMA do exactly?SCHEMA 上的 GRANT USAGE 到底是做什么的?
【发布时间】:2013-06-24 16:29:35
【问题描述】:

我第一次尝试创建 Postgres 数据库。所以这可能是一个愚蠢的问题。

我为必须从我的 PHP 脚本访问数据库的 DB 角色分配了基本只读权限,我有一个好奇心:如果我执行

GRANT some_or_all_privileges ON ALL TABLES IN SCHEMA schema TO role;

还有必要执行吗?

GRANT USAGE ON SCHEMA schema TO role;

来自documentation

USAGE:对于模式,允许访问包含在 指定的模式(假设对象自己的权限 也满足要求)。从本质上讲,这允许受让人 在架构中“查找”对象。

我认为,如果我可以选择或操作模式中包含的任何数据,我就可以访问模式本身的任何对象。我错了吗?如果不是,GRANT USAGE ON SCHEMA 是做什么用的?文档中的“假设对象自身的权限要求也得到满足”究竟意味着什么?

【问题讨论】:

    标签: database postgresql schema grant database-permissions


    【解决方案1】:

    GRANTs 在不同的对象上是分开的。 GRANT 对数据库不具有 GRANT 对其中架构的权限。类似地,GRANTing 架构不会授予对其中表的权限。

    如果您有权从表中访问SELECT,但无权在包含它的架构中查看它,则您无法访问该表。

    权限测试按顺序进行:

    Do you have `USAGE` on the schema? 
        No:  Reject access. 
        Yes: Do you also have the appropriate rights on the table? 
            No:  Reject access. 
            Yes: Check column privileges.
    

    您可能会感到困惑,因为public 架构具有对角色public 的所有权限的默认GRANT,每个用户/组都是该角色的成员。所以每个人都已经使用过该架构。

    短语:

    (假设也满足对象自身的权限要求)

    是说您必须在架构上拥有USAGE 才能使用其中的对象,但在架构上拥有USAGE 本身不足以使用架构内的对象,您还必须拥有对象的权限自己。

    它就像一个目录树。如果您创建一个目录somedir,其中包含文件somefile,然后将其设置为只有您自己的用户可以访问该目录或文件(目录上的模式rwx------,文件上的模式rw-------)然后没有人else 可以列出目录来查看文件是否存在。

    如果您要授予文件的全局读取权限(模式rw-r--r--)但不更改目录权限,则没有任何区别。没有人可以查看该文件以便阅读它,因为他们没有列出目录的权限。

    如果您改为在目录上设置rwx-r-xr-x,将其设置为人们可以列出和遍历目录但不更改文件权限,人们可以列出文件但不能读取 因为他们无权访问该文件。

    您需要设置 both 权限,人们才能真正查看文件。

    在 Pg 中也是一样的。您需要架构USAGE 权限和对象权限才能对对象执行操作,例如表中的SELECT

    (这个类比有点落空,因为 PostgreSQL 还没有行级安全性,所以用户仍然可以通过SELECTing 直接从pg_class“看到”表存在于模式中。他们但是不能以任何方式与之交互,所以它只是“列表”部分不太一样。)

    【讨论】:

    • 现在目录示例已经很清楚了 :) 我必须说,如果您使用超级用户插入一些表或行,例如当您使用 CREATE EXTENSION 添加 postGIS 时,这是一个问题。当您是su 时,在 Linux 上创建的文件或多或少是相同的问题。如果在 pqsl 中有一种sudo -e for 语句就好了。
    • 无论如何,现在我意识到GRANT 不是特定于表的语句不是我想要的,因为它们会影响所有数据库......:s
    • @LucasMalor 呃...不,他们没有。架构上的GRANT 会影响该架构。 GRANT ... ON ALL TABLES IN SCHEMA ... 影响特定数据库中模式中的所有表。没有影响所有数据库的GRANTs(好的,除了GRANTing 用户的角色成员身份)。
    • 对不起,我在以“postgres”超级用户身份登录时执行了这些语句,它们影响了“postgres”数据库。我认为如果您在没有-d db 的情况下运行psql,那么您将在“外部”任何数据库中运行,但是您始终连接到数据库,并且默认情况下您连接到与您的角色同名的数据库。 db = role = user = group ......这有点令人困惑:D
    • @LucasMalor 这样想。 默认情况下您连接到与您连接的登录角色(“用户”)同名的数据库。 “用户”只是具有WITH LOGIN 的角色;本质上,一切都可以是一个组,组可以设置为能够登录。
    【解决方案2】:

    对于生产系统,您可以使用此配置:

    --ACCESS DB
    REVOKE CONNECT ON DATABASE nova FROM PUBLIC;
    GRANT  CONNECT ON DATABASE nova  TO user;
    
    --ACCESS SCHEMA
    REVOKE ALL     ON SCHEMA public FROM PUBLIC;
    GRANT  USAGE   ON SCHEMA public  TO user;
    
    --ACCESS TABLES
    REVOKE ALL ON ALL TABLES IN SCHEMA public FROM PUBLIC ;
    GRANT SELECT                         ON ALL TABLES IN SCHEMA public TO read_only ;
    GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO read_write ;
    GRANT ALL                            ON ALL TABLES IN SCHEMA public TO admin ;
    

    【讨论】:

    • 不应该 admin 在架构上也被授予 CREATE 吗?
    • 访问是根据分层模型分配的:BD --> SCHEMA --> TABLES。使用 GRANT USAGE ON SCHEMA ,管理员用户无法创建表,但他可以使用 ALL GRANT ALL ON SCHEMA ....
    • @bilelovitch:你的意思是grant all on schema public to admin? PS:我还加了grant usage, select on all sequences in schema public to read_only/read_write;grant execute on all functions in schema public to read_only/read_write;
    【解决方案3】:

    嗯,这是我针对 Linux 的简单数据库的最终解决方案:

    # Read this before!
    #
    # * roles in postgres are users, and can be used also as group of users
    # * $ROLE_LOCAL will be the user that access the db for maintenance and
    #   administration. $ROLE_REMOTE will be the user that access the db from the webapp
    # * you have to change '$ROLE_LOCAL', '$ROLE_REMOTE' and '$DB'
    #   strings with your desired names
    # * it's preferable that $ROLE_LOCAL == $DB
    
    #-------------------------------------------------------------------------------
    
    //----------- SKIP THIS PART UNTIL POSTGRES JDBC ADDS SCRAM - START ----------//
    
    cd /etc/postgresql/$VERSION/main
    sudo cp pg_hba.conf pg_hba.conf_bak
    sudo -e pg_hba.conf
    
    # change all `md5` with `scram-sha-256`
    # save and exit
    
    //------------ SKIP THIS PART UNTIL POSTGRES JDBC ADDS SCRAM - END -----------//
    
    sudo -u postgres psql
    
    # in psql:
    create role $ROLE_LOCAL login createdb;
    \password $ROLE_LOCAL
    create role $ROLE_REMOTE login;
    \password $ROLE_REMOTE
    
    create database $DB owner $ROLE_LOCAL encoding "utf8";
    \connect $DB $ROLE_LOCAL
    
    # Create all tables and objects, and after that:
    
    \connect $DB postgres
    
    revoke connect on database $DB from public;
    revoke all on schema public from public;
    revoke all on all tables in schema public from public;
    
    grant connect on database $DB to $ROLE_LOCAL;
    grant all on schema public to $ROLE_LOCAL;
    grant all on all tables in schema public to $ROLE_LOCAL;
    grant all on all sequences in schema public to $ROLE_LOCAL;
    grant all on all functions in schema public to $ROLE_LOCAL;
    
    grant connect on database $DB to $ROLE_REMOTE;
    grant usage on schema public to $ROLE_REMOTE;
    grant select, insert, update, delete on all tables in schema public to $ROLE_REMOTE;
    grant usage, select on all sequences in schema public to $ROLE_REMOTE;
    grant execute on all functions in schema public to $ROLE_REMOTE;
    
    alter default privileges for role $ROLE_LOCAL in schema public
        grant all on tables to $ROLE_LOCAL;
    
    alter default privileges for role $ROLE_LOCAL in schema public
        grant all on sequences to $ROLE_LOCAL;
    
    alter default privileges for role $ROLE_LOCAL in schema public
        grant all on functions to $ROLE_LOCAL;
    
    alter default privileges for role $ROLE_REMOTE in schema public
        grant select, insert, update, delete on tables to $ROLE_REMOTE;
    
    alter default privileges for role $ROLE_REMOTE in schema public
        grant usage, select on sequences to $ROLE_REMOTE;
    
    alter default privileges for role $ROLE_REMOTE in schema public
        grant execute on functions to $ROLE_REMOTE;
    
    # CTRL+D
    

    【讨论】:

    • “# 创建所有表和对象,然后:”必须使用哪个用户?在您的案例中,表和其他对象的所有者是谁?
    • @ChristopheFurmaniak 你是对的,我纠正了这个过程。 db 及其对象的所有者是 $ROLE_LOCAL,在创建 db 结构后,我们必须返回 postgres 超级用户。
    • 我相信您的“ALTER DEFAULT PRIVILEGES ...”命令有问题。此命令用于在不同用户(角色)创建对象时触发向一个用户(角色)授予权限。请参阅此doc 的第 11 页第 7.1 节以进行澄清。目前,您的 ROLE_REMOTE 将无权访问 ROLE_LOCAL 将创建的任何对象。 ROLE_LOCAL 命令仅提供角色作为这些对象的所有者已经拥有的权限。 ROLE_REMOTE 命令也是如此。
    猜你喜欢
    • 2015-08-06
    • 2013-09-02
    • 2014-01-02
    • 2013-10-10
    • 2017-05-08
    • 2022-01-20
    • 2012-10-17
    • 2017-06-15
    • 2011-05-20
    相关资源
    最近更新 更多