我正在努力用谷歌云平台的云SQL组件解决这个问题。我的技术堆栈包括在Google Kubernetes Engine(GKE)部署中托管我的应用程序,使用Cloud SQL代理sidecar连接到pod中的数据库。后端是一个Symfony项目。
我按照以下步骤创建和填充数据库(没有成功):
- 创建云SQL Postgres实例
- 如GCP文档中所述,将代理添加到k8s容器,以使用所有凭据连接到云SQL实例
- 进入我的Symfony(
phpfpm
)pod并运行命令php bin/console doctrine:schema:update --force
来更新模式。查询是在数据库中执行的,因此会创建模式,依此类推 - 我尝试从GCP中与
postgres
用户的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错误:拒绝关系的权限。。在
另一个问题是,我没有用命令生成所有的表,但我必须生成它来执行所有的查询,所以很奇怪。。。
谢谢,
谷歌云平台(GCP)云SQL(PostgreSQL)中的默认postgres
用户不是实例的超级用户(GCP文档链接):
当您为PostgreSQL创建一个新的Cloud SQL实例时。。。
postgres
用户是cloudsqlsuperuser
角色的一部分,具有以下属性(权限):CREATEROLE
、CREATEDB
和LOGIN
。它不具有SUPERUSER
或REPLICATION
属性。
superuser属性赋予用户绕过所有权限检查的能力,因此,它可以去数据库实例中的任何地方从任何数据库读取数据(PostgreSQL文档链接):
数据库超级用户绕过所有权限检查,登录权限除外。
在GCP之外的典型PostgreSQL部署中,postgres
用户实际上是超级用户。Cloud SQL中的这种偏差打破了Postgres的正常约定,即postgres
用户始终可以凭借这些超级用户权限访问和更改集群中的任何对象。
如果没有此权限,您将需要更加小心创建数据库对象时使用的角色以及尝试访问数据库对象时所使用的角色,无论是在Postgres shell中以交互方式还是在应用程序中以编程方式。
我假设您正在为k8s部署使用一个单独的专用用户来连接到数据库,而不是postgres
用户。默认情况下,该用户的角色将拥有由模式填充操作创建的对象。根据GRANT
文档,默认情况下,该所有者将对对象拥有全套权限:
如果给定对象的"访问权限"列为空,则表示该对象具有默认权限(即其权限列为空)。默认权限始终包括所有者的所有权限。。。
备选方案
-
(推荐)创建一个专用角色,该角色可以在
postgres
用户和您登录数据库以填充其模式的任何其他用户之间共享。配置在架构创建操作中填充数据库对象的操作,以便在将对象创建为此共享角色之前设置其角色,以便所有用户都能够访问、管理和查看这些对象。默认情况下,新角色具有
INHERIT
属性集,这意味着将来该角色的成员将成功尝试访问该角色创建的对象。例如,您可以将
cloudsqlsuperuser
角色用于此目的,在控制台中创建的所有用户和内置的postgres
都自动成为该角色的成员。然而,我建议为此目的创建一个自定义角色:CREATE ROLE symfonyapp; GRANT symfonyapp TO postgres; GRANT symfonyapp TO <your_k8s_application_user>;
稍后,在创建数据库对象时,请确保在创建之前担任
symfonyapp
角色SET ROLE symfonyapp;
当作为已被授予CCD_ 25角色的用户登录时。您应该查看正在使用的库的文档,以确定在以编程方式连接到数据库时如何设置角色。
-
如上所述创建一个角色,并将其分配给
postgres
用户。此外,为角色赋予LOGIN
属性并设置密码,这样您就可以直接使用角色名称和密码登录数据库实例。在这种情况下,postgres
用户继承了角色的权限(例如它拥有的对象),并且直接登录的能力消除了在第一次连接时调用SET ROLE
的需要。 -
对于已经创建的对象,可以使用命令
ALTER <TYPE> <name> OWNER TO symfonyapp
将其所有权调整为您的自定义角色;例如:ALTER TABLE mytable OWNER TO symfonyapp;
无法直接将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}
此外,使用云控制台中的"数据库"选项卡创建的新数据库的所有权默认分配给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
和该角色的其他成员获得默认分配给该角色的默认权限:
您还可以使用触发器和其他方法在创建表时自动设置角色。
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)
对于生产用途,如"Alternatives"部分所述,我建议使用专用角色,而不是内置的cloudsqlsuperuser
角色。