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

时间:2018-09-09 10:39:18

标签: php postgresql symfony google-cloud-platform google-cloud-sql

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

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

  1. 创建Cloud SQL Postgres实例
  2. 将代理添加到k8s容器以使用所有凭据连接到Cloud SQL实例,如GCP documentation
  3. 中所述
  4. 输入我的Symfony(phpfpm)窗格并运行命令php bin/console doctrine:schema:update --force以更新架构。查询在数据库中执行,因此创建了架构,依此类推。
  5. 我尝试使用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用户登录我的数据库symfony可以正常工作:

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

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

  

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

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

谢谢,问候

1 个答案:

答案 0 :(得分:6)

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

  

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

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

  

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

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

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

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

  

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


替代项

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

    配置在架构创建操作中填充数据库对象的操作,以在将对象创建为共享角色之前设置其角色,以便所有用户都能够访问,管理和查看这些对象。默认情况下,新角色设置了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的需要。

    < / li>
  • 对于已经创建的对象,可以使用命令SET ROLE将其所有权调整为您的自定义角色。例如:

    ALTER <TYPE> <name> OWNER TO symfonyapp

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


可行的示例

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

cloudsqladmin

此外,默认情况下,使用Cloud Console中“数据库”标签创建的新数据库的所有权已分配给 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和该角色的其他成员赋予分配给默认情况下的角色:

您还可以在创建表时使用触发器和其他方法来documentation

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) 角色。