我正在努力使用Google Cloud Platform的Cloud SQL组件解决此问题。我的技术栈包括将我的应用程序托管在Google Kubernetes Engine(GKE)部署中,使用Cloud SQL代理sidecar连接到Pod中的数据库。后端是一个Symfony项目。
我按照以下步骤创建和填充数据库(没有成功):
phpfpm
)窗格并运行命令php bin/console doctrine:schema:update --force
以更新架构。查询在数据库中执行,因此创建了架构,依此类推。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处的关系..的权限被拒绝
另一个问题是我没有使用命令生成所有表,但是我必须生成它来执行所有查询,所以很奇怪...
谢谢,问候
答案 0 :(得分:6)
Google Cloud Platform(GCP)Cloud SQL(PostgreSQL)中的默认postgres
用户不是实例(GCP docs link)的超级用户:
当您为PostgreSQL实例创建新的Cloud SQL时...
postgres
用户是cloudsqlsuperuser
角色的一部分,并且具有以下属性(特权):CREATEROLE
,{ {1}}和CREATEDB
。它没有LOGIN
或SUPERUSER
属性。
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
的需要。
对于已经创建的对象,可以使用命令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)
角色。