hashicorp / terraform-provider-aws

The AWS Provider enables Terraform to manage AWS resources.
https://registry.terraform.io/providers/hashicorp/aws
Mozilla Public License 2.0
9.8k stars 9.15k forks source link

[Bug]: `aws_directory_service_radius_settings` updates the `shared_secret` on every run, even if the `shared_secret` has not changed #30457

Open matthewbarreiro opened 1 year ago

matthewbarreiro commented 1 year ago

Terraform Core Version

1.3.6

AWS Provider Version

4.58.0

Affected Resource(s)

Expected Behavior

Terraform should only update the resources provisioned by aws_directory_service_radius_settings if the shared_secret value actually changes.

Actual Behavior

Terraform updates the resources provisioned by aws_directory_service_radius_settings on each terraform apply. Not only does this unnecessarily increase the apply time by 1-2 minutes, but it may also lead to race conditions. E.g. when trying to deploy a workspace immediately after the RADIUS settings update, I receive an error that the directory is unavailable.

Relevant Error/Panic Output Snippet

│ Error: creating WorkSpaces Workspace: ResourceUnavailable.Directory: The specified directory is not available.
│ 
│   with module.workspace_REMOVED_02.aws_workspaces_workspace.workspaces,
│   on .terraform/modules/workspace_REMOVED_02/workspaces/workspace/main.tf line 1, in resource "aws_workspaces_workspace" "workspaces":
│    1: resource "aws_workspaces_workspace" "workspaces" {
│

Terraform Configuration Files

Note I am including my exact configuration, however the same behavior was tested to work with a sensitive variable for shared_secret, and presumably would then occur with all other values being defined directly.

resource "aws_directory_service_directory" "connector" {
  name     = "REMOVED.lan"
  password = jsondecode(data.aws_ssm_parameter.directory_service_bind_service_account.value).password
  size     = "Small"
  type     = "ADConnector"

  connect_settings {
    customer_dns_ips  = var.ad_dns_servers
    customer_username = jsondecode(data.aws_ssm_parameter.directory_service_bind_service_account.value).username
    subnet_ids        = nonsensitive(jsondecode(data.aws_ssm_parameter.vpc_workload_subnet_ids.value))
    vpc_id            = nonsensitive(data.aws_ssm_parameter.vpc_id.value)
  }
}

resource "aws_directory_service_radius_settings" "connector" {
  directory_id = aws_directory_service_directory.connector.id

  authentication_protocol = "PAP"
  display_label           = "foo"
  radius_port             = 1812
  radius_retries          = 1
  radius_servers          = var.radius_servers
  radius_timeout          = 20
  shared_secret           = data.aws_ssm_parameter.directory_service_radius_shared_secret.value
}

Steps to Reproduce

Debug Output

No response

Panic Output

No response

Important Factoids

I am able to work around this by adding a lifecycle to the resource, however this will prevent me from actually updating the secret (without first removing the lifecycle)

  lifecycle {
    ignore_changes = [
      shared_secret
    ]
  }

References

No response

Would you like to implement a fix?

No

github-actions[bot] commented 1 year ago

Community Note

Voting for Prioritization

Volunteering to Work on This Issue

ilifuservices commented 11 months ago

I'm experiencing exactly this issue. Definitely needs looking into. Thanks.

dthvt commented 8 months ago

While the API for DescribeDirectories includes a SharedSecret attribute, in practice it appears AWS returns an empty string for this value. This makes drift detection impossible. So in the short term, I think you have to just use the lifecycle block to ignore it, or put up with the constant refreshing.

What would be the preferred solution from the perspective of the provider coders? I am thinking the API could return a salted hash of the current value or something similar that would allow comparison w/o directly returning the value in the API.