flovouin / terraform-provider-metabase

A Terraform provider for the Metabase service. Also provides a utility to import dashboards and cards as Terraform definitions.
21 stars 6 forks source link

produced an unexpected new value: .custom_details: inconsistent values for sensitive attribute #40

Closed jstet closed 6 months ago

jstet commented 6 months ago

Hey there, thank you for developing this provider. Id like to report a bug:

When applying changes to metabase_database.custom, provider "provider[\"registry.terraform.io/flovouin/metabase\"]" produced an unexpected new value: .custom_details: inconsistent values for sensitive attribute.

This is a bug in the provider, which should be reported in the provider's own issue tracker.

Terraform Code:

metabase = {
      source  = "flovouin/metabase"
      version = "0.4.0"
    }

provider "metabase" {
  endpoint = "https://${local.metabase_domain}/api"
  username = terraform_data.wait_for_metabase.input
  password = var.metabase_admin_pw
}

resource "metabase_database" "custom" {
  name       = "Warehouse"
  depends_on = [kubectl_manifest.letsencrypt_issuer_production]
  custom_details = {
    engine = "postgres"

    details_json = jsonencode({
      host             = "cluster-rw.${kubernetes_namespace.warehouse.metadata[0].name}"
      port             = data.kubernetes_secret.warehouse.data["port"]
      dbname           = data.kubernetes_secret.warehouse.data["dbname"]
      user             = data.kubernetes_secret.warehouse.data["username"]
      password         = data.kubernetes_secret.warehouse.data["password"]
      ssl              = false
      tunnel-enabled   = false
      advanced-options = false
    })

    redacted_attributes = [
      "password", 
    ]
  }

}

I have tried with both metabase 0.48 and 0.49

jstet commented 6 months ago

When i add all credential values to redacted_attributes, it works. Mabye because I am retrieving data from a k8 secret?

flovouin commented 6 months ago

Hey @jstet, thanks for your message. The error is not directly linked to using sensitive values, however it makes debugging harder.

The reason you're getting this error is that upon database creation, the Metabase API is returning a database configuration which is probably slightly different from what the Terraform provider sent. This means that the content of details_json is changed by the Metabase API, which produces an inconsistent result when trying to save it back into the Terraform state.

The behaviour of the Metabase API is why I added the redacted_attributes field. The password is never returned by the Metabase API, and should therefore be ignored from the response.

When i add all credential values to redacted_attributes, it works.

By adding all values to redacted_attributes, you ignore all those values from the Metabase API response. It means Terraform will no longer detect any future changes on those fields. If nobody ever changes the database configuration in the Metabase UI, maybe this solution is good enough. However it'd be nice knowing exactly what the Metabase API returns (or actually doesn't return), such that I can at least document it. Or maybe I do need to fix something.

Could you get the database object from the Metabase API, and tell me if you see any difference with the configuration in details_json? You can also just "inspect" network calls using any browser when looking at the database details in the Metabase UI. If you see any difference, is it that the field is simply redacted by the Metabase API? Or is it changed to a different, meaningful value?

jstet commented 6 months ago

Hey, thank you so much for the detailed explanation! Unfortunately, I have switched to using a bash script with local exec and recreated my infra multiple times, so that I cant retrieve the information you requested anymore. Sorry for that, I needed to get it to work fast :S

flovouin commented 6 months ago

Okay, thanks for your reply. I will close this for now then. But feel free to re-open if you encounter this problem again, and can check what Metabase actually stores/returns for the database configuration.