terraform-provider-postgresql: postgresql_grant failing to grant "public" schema privileges with Postgres 14+
Terraform Version
v1.4.5
Affected Resource(s)
postgresql_grant
Terraform Configuration Files
provider "postgresql" {
alias = "postgres_user"
host = var.db.forwarded_host
port = var.db.forwarded_port
username = 'postgres'
password = var.db.master_password
sslmode = "require"
superuser = false
}
resource "postgresql_database" "db_api" {
provider = postgresql.postgres_user
name = "api"
owner = postgresql_role.db_role_api.name
template = "template1"
}
resource "postgresql_role" "db_role_api" {
provider = postgresql.postgres_user
name = "api"
password = aws_secretsmanager_secret_version.db_password.secret_string
login = true
}
resource "postgresql_grant" "db_role_api_all_schema_access" {
provider = postgresql.postgres_user
database = postgresql_database.db_api.name
role = "api"
schema = "public"
object_type = "schema"
privileges = ["CREATE", "USAGE"]
}
Expected Behavior
Role ‘api’ should be granted CREATE and USAGE permissions for the ‘public’ schema in the ‘api’ database.
Actual Behavior
When terraform reaches the resource postgresql_grant.db_role_api_all_schema_access, it fails with the error below. Note that Postgres added a new role called pg_database_owner and this appears to be the role that is responsible for creating the postgresql_grant resource.
module.api.postgresql_grant.db_role_api_all_schema_access: Creating...
Error: Error granting role pg_database_owner to postgres: pq: role "pg_database_owner" cannot have explicit members
with module.api.postgresql_grant.db_role_api_all_schema_access,
on api/main.tf line 95, in resource "postgresql_grant" "db_role_api_all_schema_access":
Steps to Reproduce
terraform apply
Important Factoids
Attempting to grant permissions to the ‘public’ role also fails with the same issue above.
In PostgresSQL 14+, the default privileges of the “public” schema for newly created databases were modified to just “UPDATE”. With PostgresSQL 13-, the ‘public’ schema was granted both "UPDATE’ and “CREATE” privileges by default.
In PostgreSQL 14+, a new role called pg_database_owner was introduced and this appears to be the role that is responsible for executing the postgresql_role resource above.
References
About this issue
- Original URL
- State: closed
- Created a year ago
- Reactions: 27
- Comments: 17
This is related to the
pg_database_ownerrole added in Postgres 15+ that has default ownership of thepublicschema.What seems to actually be happening is this provider queries the owner of the
publicschema (pg_database_owner) and tries to temporarily assign that role to whatever role the provider is running as: https://github.com/cyrilgdn/terraform-provider-postgresql/blob/c34742da8ad861b03e27e8aff4ab613990999aa0/postgresql/helpers.go#L125-L128.pg_database_owneris a “magic” role that refers to the owner of the current database, so it cannot have any members. When the provider tries to assignpg_database_ownerto the current role (eg.postgres), this error is thrown.Any progress on this?
Hi @kylejohnson the “secret ingredient” for reproducing the problem are the privileges of the user that is used for connecting to the database. In your case, you are using the
postgresuser who has the superuser privileges. However, in case of AWS RDS, you are connecting with a non-superuser admin, see https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.MasterAccounts.html for the background. Having said that, I was able to reproduce the problem locally using the following two scripts:Create the Postgres container + a non-superuser admin
Use the non-superuser admin to connect to Postgres + Create the database + Grant / revoke privileges for the public schema in the database
Hi @hogolestan I’m just another user of the Terraform provider who shared his workaround 😉 But as I stated in my original post, my scenario was exactly to prevent other database users from creating tables in the public schema of my database. The following snippet achieved that in my case: