Пользователь по умолчанию postgres
в облачном SQL (GCP) Google Cloud Platform (PostgreSQL) не является суперпользователем экземпляра ( ссылка на документы GCP ):
При создании нового экземпляра Cloud SQL для PostgreSQL ... пользователь postgres
входит в роль cloudsqlsuperuser
и имеет следующие атрибуты (привилегии): CREATEROLE
, CREATEDB
и LOGIN
. Он не имеет атрибутов SUPERUSER
или REPLICATION
.
Атрибут superuser дает пользователю возможность обойти все проверки разрешений и, соответственно, он может перейти в любое место в экземпляре базы данных для чтения данных из любой базы данных ( Ссылка на документацию PostgreSQL ):
Суперпользователь базы данных обходит все проверки разрешений, кроме права на вход.
В типичном развертывании PostgreSQL вне GCP пользователь postgres
действительно является суперпользователем. Это отклонение в облачном SQL нарушает обычное соглашение, ожидаемое от Postgres, что пользователь postgres
всегда может получить доступ и изменить любой объект в кластере в силу этих прав суперпользователя.
Без этой привилегии вам нужно будет более внимательно относиться к ролям, используемым при создании объектов базы данных, и роли, используемой при попытке доступа к ним, либо в интерактивном режиме в оболочке Postgres, либо программно в вашем приложении.
Я предполагаю, что вы используете отдельного выделенного пользователя для своего развертывания 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;
при входе в систему как пользователь, которому предоставлена роль symfonyapp
. Вам следует просмотреть документацию библиотек, которые вы используете, чтобы выяснить, как установить роль при программном подключении к базе данных.
Создайте роль, как указано выше, и назначьте ее пользователю postgres
. Кроме того, присвойте роли атрибут LOGIN
и установите пароль, который позволит вам войти в экземпляр базы данных, используя имя роли и пароль напрямую. В этом случае пользователь postgres
наследует привилегии роли (например, принадлежащие ему объекты), а возможность входа в систему напрямую устраняет необходимость вызова SET ROLE
при первом подключении.
Для уже созданных объектов вы можете настроить их владельца в соответствии с пользовательской ролью с помощью команды ALTER <TYPE> <name> OWNER TO symfonyapp
; например:
ALTER TABLE mytable OWNER TO symfonyapp;
Невозможно напрямую предоставить атрибут роли SUPERUSER
пользователю postgres
, поскольку у вас нет доступа к пользователю с правами SUPERUSER
для этого! (Только суперпользователи могут делать других пользователей суперпользователями.) Google Cloud SQL для 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}
Кроме того, новым базам данных, созданным с помощью вкладки «Базы данных» в Cloud Console, по умолчанию назначено право собственности на роль 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)
Для производственного использования, как отмечено в разделе «Альтернативы», я рекомендую использовать выделенную роль, а не встроенную роль cloudsqlsuperuser
.