devops-rob / terraform-provider-terracurl

A flexible Terraform provider for making API calls
https://www.hashicorp.com/blog/writing-terraform-for-unsupported-resources
Mozilla Public License 2.0
130 stars 10 forks source link

terracurl Destroy Operation Uses Stale ID Token from State File #83

Open amuware opened 2 months ago

amuware commented 2 months ago

Describe the issue We are encountering an issue when using the terracurl module to interact with our API hosted on GCP Cloud Run. Our Terraform module dynamically generates a GCP ID token using the google_service_account_id_token data source to authenticate API requests.

The terracurl resource works correctly when creating (PUT request) resources, using the freshly generated ID token. However, during the destroy operation (DELETE request), terracurl uses the ID token stored in the Terraform state file, which might have expired, leading to a 401 Unauthorized error from Cloud Run.

Steps to Reproduce

  1. Generate a dynamic ID token: Use google_service_account_id_token data source to generate a new GCP ID token each time the module is applied.

  2. Set the token in the terracurl headers: Use the generated ID token in the headers and destroy_headers of the terracurl_request resource.

  3. Run terraform apply: The resources are created successfully using the correct ID token.

  4. Wait for the token to expire: After approximately 1 hour, the generated ID token expires.

  5. Run terraform destroy: A new ID token is generated, but terracurl does not use it. Instead, it uses the expired token from the Terraform state, resulting in a 401 error during the destroy operation.

Expected Behavior

Current Behavior

data "google_service_account" "sa_id" {
  account_id = "sa-gcp"
  project    = var.project
}

data "google_service_account_id_token" "sa_gcp" {
  target_service_account = data.google_service_account.sa_id.email
  include_email          = true
  target_audience        = "https://test-dev-xcgee4a-us.a.run.app/"
}

resource "terracurl_request" "a_record" {
  for_each = length(var.public_type) > 0 ? { for rec in local.full_records : rec.sub => rec } : {}

  name    = "${var.env}_${each.key}_public_record"
  method  = "PUT"
  url     = "https://test-dev-xcgee4a-us.a.run.app/XXX/rec"

  headers = {
    "X-Serverless-Authorization" = "Bearer ${data.google_service_account_id_token.sa_gcp.id_token}"
    "Content-Type"               = "application/json"
  }

  request_body = jsonencode({
    ...
  })

  response_codes = [200]
  timeout        = 120

  destroy_timeout = 120
  destroy_url     = "https://test-dev-xcgee4a-us.a.run.app/XXX/rec"
  destroy_method  = "DELETE"
  destroy_headers = {
    "X-Serverless-Authorization" = "Bearer ${data.google_service_account_id_token.sa_gcp.id_token}"
    "Content-Type"               = "application/json"
  }
  destroy_request_body = jsonencode({
    ...
  })

  destroy_response_codes = [200, 401, 500]

  depends_on = [data.google_service_account_id_token.sa_gcp]
}

Further Explanation

Thank you for your attention to this matter, and I look forward to your guidance or an update to the terracurl module that addresses this issue.

amuware commented 2 months ago

Hello @devops-rob, any ideas regarding this issue ? Thanks