具有特权的GCP SQL Postgres问题:无法使用生成的symfony db对postgres用户运行查询

Ale*_*don 3 php postgresql symfony google-cloud-sql google-cloud-platform

我正在努力使用Google Cloud Platform的Cloud SQL组件解决此问题。我的技术栈包括将我的应用程序托管在Google Kubernetes Engine(GKE)部署中,使用Cloud SQL代理sidecar连接到Pod中的数据库。后端是一个Symfony项目。

我按照以下步骤创建和填充数据库(没有成功):

  1. 创建Cloud SQL Postgres实例
  2. 将代理添加到k8s容器以使用所有凭据连接到Cloud SQL实例,如GCP文档中所述
  3. 输入我的Symfony(phpfpm)窗格并运行命令php bin/console doctrine:schema:update --force以更新架构。查询在数据库中执行,因此创建了架构,依此类推。
  4. 我尝试与postgres用户通过GCP中的SQL控制台连接打开数据库,并尝试执行简单的select * from foo;查询。响应是Insufficient privilege: 7 ERROR: permission denied for relation

如何与postgres用户查询数据库中的数据?

编辑:

我有关于用户的这种情况:

     Role name     |                         Attributes                         |           Member of           
-------------------+------------------------------------------------------------+-------------------------------
 acando14          | Create role, Create DB                                     | {cloudsqlsuperuser,proxyuser}
 cloudsqladmin     | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
 cloudsqlagent     | Create role, Create DB                                     | {cloudsqlsuperuser}
 cloudsqlreplica   | Replication                                                | {}
 cloudsqlsuperuser | Create role, Create DB                                     | {}
 postgres          | Create role, Create DB                                     | {cloudsqlsuperuser,acando14}
 proxyuser         | Create role, Create DB                                     | {cloudsqlsuperuser}
Run Code Online (Sandbox Code Playgroud)

我在表中有这种情况:

              List of relations
 Schema |      Name       | Type  |  Owner   
--------+-----------------+-------+----------
 public | article         | table | acando14
Run Code Online (Sandbox Code Playgroud)

如果我使用postgres用户登录我的数据库symfony工作:

symfony => select * from article;
 id | model_id | code | size 
----+----------+------+------
(0 rows)
Run Code Online (Sandbox Code Playgroud)

但是,如果我使用服务器执行代码,则响应为:

SQLSTATE [42501]:特权不足:7错误:在PDOException(代码:42501),关系雇员的权限被拒绝:SQLSTATE [42501]:特权不足:7错误:在关系..处的权限被拒绝

另一个问题是我没有使用命令生成所有表,但是必须生成执行所有查询的表,真是太奇怪了...

谢谢,问候

Cos*_*age 9

postgresGoogle Cloud Platform(GCP)Cloud SQL(PostgreSQL)中的默认用户不是实例的超级用户(GCP docs链接):

当你创建一个新的Cloud SQL的PostgreSQL实例...该postgres用户是的一部分cloudsqlsuperuser作用,并具有以下属性(权限): ,CREATEROLE,CREATEDB和LOGIN。它没有SUPERUSER或REPLICATION属性。

superuser属性授予用户绕过所有权限检查的能力,因此,它可以进入数据库实例的任何位置以从任何数据库读取数据(PostgreSQL docs链接):

数据库超级用户会跳过所有权限检查,但登录权限除外。

在GCP之外的典型PostgreSQL部署中,postgres用户确实是超级用户。Cloud SQL中的这种偏离违反了Postgres的常规约定,即postgres用户始终可以凭借这些超级用户权限访问和更改集群中的任何对象。

没有此特权,您将需要在创建数据库对象时使用的角色以及在尝试访问它们时使用的角色(在Postgres Shell上以交互方式或在应用程序中以编程方式)更加小心。

我假设您正在为k8s部署使用一个单独的专用用户来连接数据库,而不是该postgres用户。默认情况下,该用户角色将拥有由架构填充操作创建的对象。根据GRANT文档,默认情况下,此所有者将拥有对该对象的全套特权:

如果给定对象的“访问特权”列为空,则表示该对象具有默认特权(即,其特权列为null)。默认特权始终包含所有者的所有特权...


备择方案

  • (推荐)创建一个专用角色,该角色可以在postgres用户和您用来登录数据库的任何其他用户之间共享。

    配置在架构创建操作中填充数据库对象的操作,以在将对象创建为共享角色之前设置其角色,以使所有用户都能够访问,管理和查看这些对象。默认情况下,新角色具有INHERIT属性集,这意味着将来该角色成员尝试访问由该角色创建的对象的尝试将成功。

    例如,您可以cloudsqlsuperuser为此使用角色,在控制台中创建的所有用户和postgres内置用户均自动成为该角色的成员。但是,我建议为此创建一个自定义角色:

    CREATE ROLE symfonyapp;
    GRANT symfonyapp TO postgres;
    GRANT symfonyapp TO <your_k8s_application_user>;
    
    Run Code Online (Sandbox Code Playgroud)

    稍后,在创建数据库对象时,请确保您symfonyapp先扮演角色。在控制台上,运行:

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

    以symfonyapp已授予角色的用户身份登录时。您应该查看正在使用的库的文档,以确定在以编程方式连接到数据库时如何设置角色。

  • 如上所述创建一个角色,并将其分配给postgres用户。另外,为角色提供LOGIN属性并设置密码,该密码使您可以直接使用角色名称和密码登录数据库实例。在这种情况下,postgres用户将继承角色(例如其拥有的对象)的特权,并且直接登录的能力消除了SET ROLE在第一个连接上进行调用的需要。

  • 对于已经创建的对象,您可以使用以下命令将其所有权调整为您的自定义角色ALTER <TYPE> <name> OWNER TO symfonyapp:例如:

    ALTER TABLE mytable OWNER TO symfonyapp;
    
    Run Code Online (Sandbox Code Playgroud)

无法直接将SUPERUSER角色属性授予postgres用户,因为您无权访问具有SUPERUSER特权的用户!(只有超级用户才能使其他用户成为超级用户。)Google Cloud SQL for Postgres 文档特别说明了对需要超级用户特权的所有功能的支持,因此您无法使用此路由。唯一的超级用户是cloudsqladmin用户,默认情况下已创建,并由Google用来代表您执行实例级管理操作的用户;您可以重设密码并以该帐户登录以授予超级用户权限,但我不建议您这样做,因为这样做很可能会破坏其他托管功能。


工作的例子

新建数据库集群中存在的默认角色集如下:

                                        List of roles
     Role name     |                         Attributes                         |      Member of
-------------------+------------------------------------------------------------+---------------------
 cloudsqladmin     | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
 cloudsqlagent     | Create role, Create DB                                     | {cloudsqlsuperuser}
 cloudsqlreplica   | Replication                                                | {}
 cloudsqlsuperuser | Create role, Create DB                                     | {}
 postgres          | Create role, Create DB                                     | {cloudsqlsuperuser}
Run Code Online (Sandbox Code Playgroud)

此外,默认情况下,使用Cloud Console中的“数据库”选项卡创建的新数据库已将所有权分配给该cloudsqlsuperuser角色。(如上面的角色列表所示,该cloudsqlsuperuser角色由postgres用户继承。)

                                  List of databases
  Name  |       Owner       | Encoding |  Collate   |   Ctype    | Access privileges
--------+-------------------+----------+------------+------------+-------------------
 testdb | cloudsqlsuperuser | UTF8     | en_US.UTF8 | en_US.UTF8 |
Run Code Online (Sandbox Code Playgroud)

因此,cloudsqlsuperuser默认情况下,角色成员将具有在数据库中创建对象的权限。但是,这样做时,默认情况下,会将其所有者设置为创建它们的用户,而不是父角色:

testdb=> CREATE TABLE sometable (id SERIAL NOT NULL);
CREATE TABLE
testdb=> \dt sometable
           List of relations
 Schema |   Name    | Type  |  Owner
--------+-----------+-------+----------
 public | sometable | table | testuser
Run Code Online (Sandbox Code Playgroud)

如果SET ROLE cloudsqlsuperuser在创建表之前调用,所有者现在将默认为cloudsqlsuperuser角色,这将默认情况下为角色postgres和角色的其他成员分配给角色:

您还可以使用触发器和其他方法在创建表时自动设置角色。

testdb=> SET ROLE cloudsqlsuperuser;
SET
testdb=> CREATE TABLE anothertable (id SERIAL NOT NULL);
CREATE TABLE
testdb=> \dt anothertable;
                 List of relations
 Schema |     Name     | Type  |       Owner
--------+--------------+-------+-------------------
 public | anothertable | table | cloudsqlsuperuser
(1 row)
Run Code Online (Sandbox Code Playgroud)

对于生产用途,如“替代”部分所述,我建议使用专用角色而不是内置cloudsqlsuperuser角色。