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

问题描述 投票:1回答:1

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

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

  1. 创建Cloud SQL Postgres实例
  2. 将代理添加到k8s容器以使用所有凭据连接到Cloud SQL实例,如GCP documentation中所述
  3. 输入我的Symfony(phpfpm)pod并运行命令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}

我在表格中有这种情况:

              List of relations
 Schema |      Name       | Type  |  Owner   
--------+-----------------+-------+----------
 public | article         | table | acando14

如果我使用postgres用户登录我的db symfony工作:

symfony => select * from article;
 id | model_id | code | size 
----+----------+------+------
(0 rows)

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

SQLSTATE [42501]:权限不足:7错误:PDOException上关系员工的权限被拒绝(代码:42501):SQLSTATE [42501]:权限不足:7错误:关系权限被拒绝.. at

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

谢谢,问候

php postgresql symfony google-cloud-platform google-cloud-sql
1个回答
6
投票

Google Cloud Platform(GCP)云端​​SQL(PostgreSQL)中的默认postgres用户不是该实例的超级用户(GCP docs link):

当您为PostgreSQL实例创建新的Cloud SQL时... postgres用户是cloudsqlsuperuser角色的一部分,并具有以下属性(特权):CREATEROLECREATEDBLOGIN。它没有SUPERUSERREPLICATION属性。

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

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

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

如果没有此权限,您需要更加小心创建数据库对象时使用的角色以及尝试访问它们时使用的角色,可以在Postgres shell上以交互方式进行,也可以在应用程序中以编程方式进行。

我假设您使用单独的专用用户来进行k8s部署以连接到数据库,而不是postgres用户。默认情况下,该用户的角色将拥有模式填充操作创建的对象。根据GRANT documentation,默认情况下,此所有者将拥有对该对象的完整特权:

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


Alternatives

  • (推荐)创建一个专用角色,可以在postgres用户和您登录数据库的任何其他用户之间共享,以填充其架构。 配置在模式创建操作中填充数据库对象的操作,以便在将对象创建到此共享角色之前设置其角色,以便所有用户都能够访问,管理和查看这些对象。默认情况下,新角色具有INHERIT属性集,这意味着将来角色成员访问该角色创建的对象的尝试将成功。 例如,您可以将cloudsqlsuperuser角色用于此目的,其中在控制台中创建的所有用户和内置的postgres都是自动成员。但是,我建议为此目的创建自定义角色: CREATE ROLE symfonyapp; GRANT symfonyapp TO postgres; GRANT symfonyapp TO <your_k8s_application_user>; 稍后,在创建数据库对象时,请确保在执行此操作之前采用symfonyapp角色。在控制台上,运行: SET ROLE symfonyapp; 以授予symfonyapp角色的用户身份登录时。您应该查看正在使用的库的文档,以确定在以编程方式连接到数据库时如何设置角色。
  • 创建一个角色,并将其分配给postgres用户。此外,为角色提供LOGIN属性并设置密码,这允许您直接使用角色名称和密码登录数据库实例。在这种情况下,postgres用户继承角色的权限(例如它拥有的对象),并且直接登录的能力消除了在第一次连接时调用SET ROLE的需要。
  • 对于已创建的对象,您可以使用命令ALTER <TYPE> <name> OWNER TO symfonyapp将其所有权调整为自定义角色;例如: ALTER TABLE mytable OWNER TO symfonyapp;

无法直接将SUPERUSER角色属性授予postgres用户,因为您无法访问具有SUPERUSER权限的用户这样做! (只有超级用户才能让其他用户成为超级用户。)适用于Postgres的Google Cloud SQL documentation注意到对任何需要超级用户权限的功能的特定排除,因此您无法使用此路由。唯一的超级用户是cloudsqladmin用户,默认情况下创建并由Google用于代表您执行实例级管理操作;您可以重置密码并以此帐户登录以授予超级用户权限,但我不建议这样做,因为这可能会破坏其他托管功能。


Worked example

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

                                        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}

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

                                  List of databases
  Name  |       Owner       | Encoding |  Collate   |   Ctype    | Access privileges
--------+-------------------+----------+------------+------------+-------------------
 testdb | cloudsqlsuperuser | UTF8     | en_US.UTF8 | en_US.UTF8 |

因此,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

如果我们在创建表之前调用SET ROLE cloudsqlsuperuser,则所有者现在默认使用cloudsqlsuperuser角色,这将允许postgres和该角色的其他成员默认为该角色分配默认权限:

您还可以在创建表时使用set the role automatically的触发器和其他方法。

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)

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

© www.soinside.com 2019 - 2024. All rights reserved.