Closed y0zg closed 2 years ago
That's said, I can login with user test_readonly
but it doesn't have required role
I also tried to add this part but it didn't help to revoke default public permissions
resource "postgresql_grant" "revoke_public" {
database = "test"
role = "test_readonly"
schema = "public"
object_type = "schema"
privileges = []
with_grant_option = true
}
Hi @y0zg,
I'm not sure the example code you put in the issue is complete because regarding:
When I run below query, I don't see any roles assigned after terraform apply. it takes effect only if I grant permissions manually via GRANT readonly TO test_readonly;
I don't see any reference of readonly
role in:
resource "postgresql_role" "test_readonly" {
name = "test_readonly"
login = true
password = var.test_db_password
}
resource "postgresql_grant" "grant_ro_sequence" {
database = "test"
role = "test_readonly"
schema = "public"
object_type = "sequence"
privileges = ["USAGE", "SELECT"]
}
resource "postgresql_grant" "grant_ro_tables" {
database = "test"
role = "test_readonly"
schema = "public"
object_type = "table"
privileges = ["SELECT"]
}
resource "postgresql_default_privileges" "alter_ro_tables" {
database = "test"
owner = "test"
role = "test_readonly"
schema = "public"
object_type = "table"
privileges = ["SELECT"]
}
resource "postgresql_default_privileges" "alter_ro_sequence" {
database = "test"
owner = "test"
role = "test_readonly"
schema = "public"
object_type = "sequence"
privileges = ["USAGE", "SELECT"]
}
About this Terraform code, I can see a potential problem though. You didn't set the dependencies between resources so first apply may not properly set the grant/default privileges if they are created before the associated role.
It reproduced your example but with the right dependencies between resources here: https://github.com/cyrilgdn/terraform-provider-postgresql/blob/604f1f7031d00a07e7f12534f0c8f3100c64e21e/examples/issues/75/test.tf#L28-L74
And after applying this code, it correctly created the default privileges:
psql -h xxx -U postgres -d test -c "\ddp"
Default access privileges
Owner | Schema | Type | Access privileges
-------+--------+----------+-----------------------
test | public | sequence | test_readonly=rU/test
test | public | table | test_readonly=r/test
(2 rows)
And if create a table in the test database:
$ psql -h xxx -U postgres -d test -c "create table test (id serial);"
CREATE TABLE
And apply again it will grant the privileges to the role:
$ terraform apply
postgresql_database.test: Refreshing state... [id=test]
postgresql_role.test: Refreshing state... [id=test]
postgresql_role.test_readonly: Refreshing state... [id=test_readonly]
postgresql_grant.grant_ro_tables: Refreshing state... [id=test_readonly_test_public_table]
postgresql_grant.grant_ro_sequence: Refreshing state... [id=test_readonly_test_public_sequence]
postgresql_default_privileges.alter_ro_sequence: Refreshing state... [id=test_readonly_test_public_test_sequence]
postgresql_default_privileges.alter_ro_tables: Refreshing state... [id=test_readonly_test_public_test_table]
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
~ update in-place
Terraform will perform the following actions:
# postgresql_grant.grant_ro_sequence will be updated in-place
~ resource "postgresql_grant" "grant_ro_sequence" {
id = "test_readonly_test_public_sequence"
~ privileges = [
+ "SELECT",
+ "USAGE",
]
# (5 unchanged attributes hidden)
}
# postgresql_grant.grant_ro_tables will be updated in-place
~ resource "postgresql_grant" "grant_ro_tables" {
id = "test_readonly_test_public_table"
~ privileges = [
+ "SELECT",
]
# (5 unchanged attributes hidden)
}
Plan: 0 to add, 2 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
postgresql_grant.grant_ro_tables: Modifying... [id=test_readonly_test_public_table]
postgresql_grant.grant_ro_sequence: Modifying... [id=test_readonly_test_public_sequence]
postgresql_grant.grant_ro_tables: Modifications complete after 1s [id=test_readonly_test_public_table]
postgresql_grant.grant_ro_sequence: Modifications complete after 1s [id=test_readonly_test_public_sequence]
Apply complete! Resources: 0 added, 2 changed, 0 destroyed.
And I can connect as test_readonly
to verify it has read privileges
$ psql -h xxx -U test_readonly -d test -c "select count(*) from test"
count
-------
0
(1 row)
I also tried to add this part but it didn't help to revoke default public permissions
And about this point, you actually to revoke these privileges from public
role which is a special group that includes all roles.
See in my example:
hi @cyrilgdn ! Thanks for the prompt reply! I amended the config a bit and can see the role is there
test=> \ddp
Default access privileges
Owner | Schema | Type | Access privileges
-------+--------+----------+----------------------------
test | public | sequence | test_readonly_role=rU/test
test | public | table | test_readonly_role=r/test
(2 rows)
but still wonder why user test_readonly_user
can create tables in public
schema
I believe this step is missing REVOKE CREATE ON SCHEMA public FROM PUBLIC;
# ROLE
resource "postgresql_role" "role_ro" {
name = "test_readonly_role"
login = false
superuser = false
inherit = true
create_database = false
create_role = false
replication = false
skip_reassign_owned = true
}
# USER
resource "postgresql_role" "user_ro" {
name = "test_readonly_user"
login = true
superuser = false
create_database = false
create_role = false
inherit = true
replication = false
connection_limit = -1
skip_reassign_owned = true
password = "password"
roles = [postgresql_role.role_ro.name]
depends_on = [postgresql_role.role_ro]
}
resource "postgresql_role" "additional_user_ro" {
name = "test_readonly_user2"
login = true
superuser = false
create_database = false
create_role = false
inherit = true
replication = false
connection_limit = -1
skip_reassign_owned = true
password = "password"
roles = [postgresql_role.role_ro.name]
depends_on = [postgresql_role.role_ro]
}
resource "postgresql_grant" "grant_ro_tables" {
database = "test"
role = "test_readonly_role"
schema = "public"
object_type = "table"
privileges = ["SELECT"]
depends_on = [postgresql_role.role_ro]
}
resource "postgresql_grant" "grant_ro_sequence" {
database = "test"
role = "test_readonly_role"
schema = "public"
object_type = "sequence"
privileges = ["USAGE", "SELECT"]
depends_on = [postgresql_role.role_ro]
}
resource "postgresql_default_privileges" "alter_ro_tables" {
database = "test"
owner = "test"
role = "test_readonly_role"
schema = "public"
object_type = "table"
privileges = ["SELECT"]
depends_on = [postgresql_role.role_ro]
}
resource "postgresql_default_privileges" "alter_ro_sequence" {
database = "test"
owner = "test"
role = "test_readonly_role"
schema = "public"
object_type = "sequence"
privileges = ["USAGE", "SELECT"]
depends_on = [postgresql_role.role_ro]
}
resource "postgresql_grant" "revoke_public" {
database = "test"
role = postgresql_role.role_ro.name
schema = "public"
object_type = "schema"
privileges = []
with_grant_option = true
}
Also with above config user test_readonly_user2
cannot do SELECT
on tables created by user test_readonly_user
despite they are both belong to the same role, probably I'm missing something fundamental, but with SQL commands this works for me
@cyrilgdn please let me know what are your thoughts regarding this :)
@y0zg We ran into this same issue and the fix for us was specifying the template
when creating the database:
resource "postgresql_database" "database" {
name = var.name
owner = var.db_owner
template = "template1"
}
It appears this provider defaults to template0 which creates some public
schema ownership issues according to this AWS support article.
Although I think there’s two separate issues here:
template0
by default, whereas the CREATE DATABASE
statement uses template1
by default (see docs here). There might be some complexities there that I'm not aware of.grant
resources are silently failing with this message WARNING: no privileges were granted for "public”
. It seems that, in order to alter public
permissions you need to use template1
and the master-user
role (or transfer ownership to another user). Maybe the provider could error when it sees this WARNING
message.Hopefully that helps!
@y0zg Sorry to have been silenced, I was a bit off the project for a while.
@alec-rabold Thanks for your help, indeed the provider uses template0
by default and to be honest I don't know why (it was the case before I started to work on this provider).
In RDS, the owner of template0
's public schema is rdsamin
so we don't have the privileges to alter the schema privileges where the owner of template1
's public schema is postgres
(actually the admin username you set at the cluster creation).
You should always set template="template1"
for RDS.
I'm thinking changing this default value but it's an important breaking change (and will force recreate resources unless if not specified unless we set it to compute) so I'm not sure yet.
@y0zg Did you manage to solve your problem with this solution?
Sorry, I didn't have a time to test, but I believe your last comment should solve the issue, so closing this
Hi there,
I'm about to assign proper readonly permission for user in
public
schema.After reading this page https://aws.amazon.com/blogs/database/managing-postgresql-users-and-roles/ and checking https://github.com/cyrilgdn/terraform-provider-postgresql/issues/33#issuecomment-757512759 I expected to configure everything as planned, but after some simple testing I see that role isn't assigned properly.
Basically I'd like to apply the following config:
Terraform Version
Terraform v0.13.6
Terraform Configuration Files
Database is created via aws module https://registry.terraform.io/modules/terraform-aws-modules/rds/aws/latest
When I run below query, I don't see any roles assigned after
terraform apply
.it takes effect only if I grant permissions manually via
GRANT readonly TO test_readonly;
Debug Output
Please provider a link to a GitHub Gist containing the complete debug output: https://www.terraform.io/docs/internals/debugging.html. Please do NOT paste the debug output in the issue; just paste a link to the Gist.
Expected Behavior
What should have happened?
Role should be assigned with appropriate permissions
Actual Behavior
What actually happened?
Role isn't assigned to user
Steps to Reproduce
Please list the steps required to reproduce the issue, for example:
terraform apply