terraform-provider-aws: [Bug]: aws_grafana_workspace_api_key doesn't renew

Terraform Core Version

1.3.0

AWS Provider Version

4.32.0

Affected Resource(s)

  • aws_grafana_workspace_api_key
  • grafana provider

Expected Behavior

New key is created and terraform shows plan

Actual Behavior

Error: Invalid provider configuration
│ 
│ Provider "registry.terraform.io/grafana/grafana" requires explicit configuration. Add a provider block to the root module and configure the provider's required arguments as described in the provider
│ documentation.
│ 
╵
╷
│ Error: Missing required argument
│ 
│   with provider["registry.terraform.io/grafana/grafana"],
│   on <empty> line 0:
│   (source code not available)
│ 
│ "auth": one of `auth,cloud_api_key,oncall_access_token,sm_access_token` must be specified

Or if i have the grafana_data_source block also:

│ Error: the Grafana client is required for `grafana_data_source`. Set the auth and url provider attributes
│ 
│   with grafana_data_source.prometheus,
│   on main.tf line 50, in resource "grafana_data_source" "prometheus":
│   50: resource "grafana_data_source" "prometheus" {
│ 

Relevant Error/Panic Output Snippet

No response

Terraform Configuration Files

provider "aws" {
  region = "us-west-1"
}

provider "grafana" {
  alias = "my_grafana"
  url   = "https://${aws_grafana_workspace.my_aws_grafana.endpoint}"
  auth  = aws_grafana_workspace_api_key.my_aws_grafana_key.key
}

resource "aws_grafana_workspace" "my_aws_grafana" {
  // timestamp needed to work around duplicate workspace bug in aws managed grafana
  // https://stackoverflow.com/a/73411011/20103507
  description              = "My grafana ${formatdate("YYYYMMDDhhmmss", timestamp())}"
  account_access_type      = "CURRENT_ACCOUNT"
  authentication_providers = ["SAML"]
  permission_type          = "SERVICE_MANAGED"
  role_arn                 = "<replaced role arn here>"
  data_sources             = ["PROMETHEUS"]
}

resource "aws_grafana_workspace_api_key" "my_aws_grafana_key" {
  key_name        = "config-key"
  key_role        = "ADMIN"
  seconds_to_live = 3600
  workspace_id    = aws_grafana_workspace.my_aws_grafana.id
}

# Optionally also
resource "grafana_data_source" "prometheus" {
...
}

Steps to Reproduce

terraform apply wait for the key to expire terraform plan

Debug Output

No response

Panic Output

No response

Important Factoids

I’m using terraform to create aws_managed_grafana, and then creating an api key there that is required to have an expiration date. Once it expires, the grafana provider that i’m trying to use to configure this aws_managed_grafana instance, stops working. The whole plan stops working.

References

No response

Would you like to implement a fix?

No

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Reactions: 26
  • Comments: 17 (1 by maintainers)

Most upvoted comments

watch out with these workarounds - as mentioned here, AWS will charge you a monthly fee for each API key, so $8 per terraform run.

@dievri it’s just a custom python script takes in the inputs defined in query to make boto3 calls to delete the existing key and create + return a fresh one with the same name

Any progress on the issue?

a workaround i’ve resorted to is an external data source that runs a script to create a key before each run. (deleting a key with the same name first, if one exists)

resource "aws_grafana_workspace" "grafana-workspace" {
  count                    = var.create_grafana_workspace
  name                     = "example-grafana-workspace"
  account_access_type      = "CURRENT_ACCOUNT"
  authentication_providers = ["SAML"]
  data_sources   = ["CLOUDWATCH"]
  permission_type          = "CUSTOMER_MANAGED"
  role_arn                 = aws_iam_role.grafana_cloudwatch_role.arn
}

# get the aws_grafana_workspace data if the above workspace resource is available 
# OR if a grafana_workspace_id output exists in the remote state data
data "aws_grafana_workspace" "optional_grafana_workspace" {
  count = length(aws_grafana_workspace.grafana-workspace) > 0 || try(data.terraform_remote_state.state.outputs.grafana_workspace_id, null) != null ? 1 : 0
  workspace_id = try(aws_grafana_workspace.grafana-workspace.id, try(data.terraform_remote_state.state.outputs.grafana_workspace_id, null))
}

data "external" "grafana_credentials" {
  count = length(data.aws_grafana_workspace.optional_grafana_workspace)
  program    = ["python3", "./scripts/api_key.py"]
  query      = {
    workspace_id          = data.aws_grafana_workspace.optional_grafana_workspace[0].workspace_id
    workspace_endpoint    = format("https://%s", data.aws_grafana_workspace.optional_grafana_workspace[0].endpoint)
    api_key_name          = "terraform"
    aws_region            = var.aws_region
    seconds_to_live       = 3600
  }
}

provider grafana {
  url  = try(data.external.grafana_credentials[0].result.endpoint, "https://unused")
  auth = try(data.external.grafana_credentials[0].result.key, "unused")
}

additionally, in the above example, if var.create_grafana_workspace = true, the plan sets an output value of the grafana workspace id, which can then be referenced in a future plan that may want to destroy the workspace by setting var.create_grafana_workspace = false. in this scenario, the workspace information isn’t available from the previously created resource because the count is now 0. and we need the workspace id in order to create a new key to initialize the grafana provider, so that it can read and destroy any resources that use this provider.

so this works around expiring keys, and the case where you want to destroy a workspace that also had additional things added to the workspace by the grafana provider. but it’s definitely not ideal