cyrilgdn / terraform-provider-postgresql

Terraform PostgreSQL provider
https://www.terraform.io/docs/providers/postgresql/
Mozilla Public License 2.0
395 stars 200 forks source link

postgresql_grant persistent plan drift even without underlying terraform code changed #197

Open bfox1793 opened 2 years ago

bfox1793 commented 2 years ago

Terraform Version

1.1.3

Affected Resource(s)

postgresql_grant

Terraform Configuration Files

required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "= 3.71.0"
    }
    postgresql = {
      source  = "cyrilgdn/postgresql"
      version = "1.15.0"
    }
  }

Debug Output

N/A

Panic Output

N/A

Expected Behavior

Having a postgresql_grant object with privileges SELECT, UPDATE, INSERT without any changes reflects as much on subsequent terraform plan runs.

Actual Behavior

terraform plan detects constant drift between INSERT grants being either removed, and so it attempts to add it, or it says it was added and needs to remove the INSERT privilege (though I want the insert to be added).

These subsequent applies don't appear to affect the underlying resources, just the terraform state detection. The terraform configs are putting grants on the DB as-expected.

Steps to Reproduce

  1. terraform apply > creates the postgresql_grant with SELECT, UPDATE, INSERT access
  2. terraform plan > expect no drift since underlying TF code wasn't touched, but instead it detects that the grant's INSERT either needs to be added or removed from the grant.

Important Factoids

N/A

References

N/A

cyrilgdn commented 2 years ago

Hi @bfox1793 ,

Could you provide example of Terraform resources to reproduce this behavior? I'm not able to reproduce it with a simple test.

yaronmahat commented 2 years ago

Hi @cyrilgdn , This happens to me also. I think I have pin-pointed the cause of it:

This happens when using default privileges. when a new table is created, privileges on it will be granted according to defaults and will reflect on information_schema.role_table_grants table. However, they will not reflect in pg_class column relacl which is used by the TF provider. Only when the table will be issued one grant command, even if unrelated to the default privileges, the relacl column in pg_class will be populated.

A small example:

1) create user yaron with password 'yaron'; 2) ALTER DEFAULT PRIVILEGES FOR ROLE yaron grant select,insert,update,delete on tables to yaron; 3)connect as yaron 4)create table test(x int);

postgres=> select*from information_schema.role_table_grants where table_name='test'; (privileges are shown)

grantor | grantee | table_catalog | table_schema | table_name | privilege_type | is_grantable | with_hierarchy ---------+---------+---------------+--------------+------------+----------------+--------------+---------------- yaron | yaron | postgres | public | test | INSERT | YES | NO yaron | yaron | postgres | public | test | SELECT | YES | YES yaron | yaron | postgres | public | test | UPDATE | YES | NO yaron | yaron | postgres | public | test | DELETE | YES | NO yaron | yaron | postgres | public | test | TRUNCATE | YES | NO yaron | yaron | postgres | public | test | REFERENCES | YES | NO yaron | yaron | postgres | public | test | TRIGGER | YES | NO

postgres=> select relacl from pg_class where relname='test'; (relacl is empty) relacl

(1 row)

now, grant select to some other user on the new table:

postgres=> grant select on test to yaron2; GRANT postgres=> select relacl from pg_class where relname='test'; relacl

{yaron=arwdDxt/yaron,yaron2=r/yaron}

grants are now shown in relacl on yaron user,

This causes the provider to re-grant the privileges on the new tables which updates relacl, so after the apply there is no drift until the next table is created.

Hope this helps.

bfox1793 commented 1 year ago

@cyrilgdn - I think @yaronmahat 's details above provides a more concise example of this behavior. Let me know if you need any additional information!

n1ngu commented 1 year ago

This simple config granting a role all privileges on a DB schema

terraform {
  required_providers {
    postgresql = {
      source = "cyrilgdn/postgresql"
    }
  }
  required_version = ">= 1.0"
}

provider "postgresql" {
  host            = var.psql_host
  port            = 5432
  database        = "postgres"
  username        = var.psql_username
  password        = var.psql_password
  sslmode         = "require"
  connect_timeout = 15
  superuser       = false  # It's an AWS RDS
}

resource "postgresql_role" "app_role" {
  name  = "app"
  login = false
}

resource "postgresql_database" "app" {
  name              = "app"
  owner             = postgresql_role.app.name
  template          = "template0"
  lc_collate        = "en_US.UTF-8"
  connection_limit  = -1
  allow_connections = true
}

resource "postgresql_grant" "app_tables" {
  database    = postgresql_database.app.name
  role        = postgresql_role.app.name
  schema      = "public"
  object_type = "table"
  privileges  = ["SELECT", "INSERT", "UPDATE", "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER"]
}

resource "postgresql_grant" "app_sequences" {
  database    = postgresql_database.app.name
  role        = postgresql_role.app.name
  schema      = "public"
  object_type = "sequence"
  privileges  = ["USAGE", "SELECT", "UPDATE"]
}

resource "postgresql_role" "app_user" {
  name  = "app-user"
  login = true
  roles = [postgresql_role.app_role.name]
}

regularly detects a drift in the granted privileges and requires a new apply

  # postgresql_grant.app_sequence will be updated in-place
  ~ resource "postgresql_grant" "app_sequences" {
        id                = "app_public_sequence"
      ~ privileges        = [
          + "SELECT",
          + "UPDATE",
          + "USAGE",
        ]
        # (5 unchanged attributes hidden)
    }
Plan: 0 to add, 1 to change, 0 to destroy.

despite nobody tampered the privileges and the application works just right.

This happens from time to time and causes some noise in terraform plans.

FWIW: all my DB services are AWS RDS, so I haven't tested this on a bare postgresql.

nocive commented 1 year ago

bump

shawon-crosen commented 1 year ago

Any updates on this? I am seeing the same thingas @n1ngu , also with AWS RDS postgres instances

steintore commented 1 year ago

Seems like the same issue as here https://github.com/cyrilgdn/terraform-provider-postgresql/issues/303

We're having the same issue and we do experience 1-2 seconds where the user looses access to tables etc.

Any updates on this?

a-nldisr commented 10 months ago

Similar behavior on AWS Aurora and RDS.

jalitzinger commented 8 months ago

In more recent versions, https://github.com/cyrilgdn/terraform-provider-postgresql/pull/135/files#diff-df65aafa037f8919594f7968b37996a7cb876d3a94de44286f83bd81288fd159L40 will cause recreations, not just updates.

rmihael commented 4 months ago

I also experience the same behavior with version 1.22.0. I have the following resource definition

resource postgresql_grant connect_privilege {
  for_each = toset(var.database_users_roles)

  database = var.database
  object_type = "database"
  privileges = ["CONNECT"]
  role = each.value
}

Every time I run apply it wants to change it:

  # module.database_config.postgresql_grant.connect_privilege["users-qntpm-dev-2/qntpmdev"] must be replaced
-/+ resource "postgresql_grant" "connect_privilege" {
      ~ id                = "users-qntpm-dev-2/qntpmdev_qntpmdev_database" -> (known after apply)
      ~ privileges        = [ # forces replacement
          + "CONNECT",
        ]
        # (4 unchanged attributes hidden)
    }

I run Terraform with TF_LOG=INFO and this part seems to be relevant:

module.database_config.postgresql_grant.connect_privilege["users-qntpm-dev-2/qntpmdev"]: Refreshing state... [id=users-qntpm-dev-2/qntpmdev_qntpmdev_database]
2024-07-23T14:20:19.248+0300 [WARN]  Provider "registry.terraform.io/cyrilgdn/postgresql" produced an unexpected new value for module.database_config.postgresql_grant.connect_privilege["users-qntpm-dev-2/qntpmdev"] during refresh.
      - .privileges: planned set element cty.StringVal("CONNECT") does not correlate with any element in actual
andersthorbeck commented 5 days ago

Is anyone looking into this issue? The Terraform plans have been consistently misleading on postgresql_grant resources for several years now.