Skip to content

aws_cloudwatch_event_target.rule uses .id, which is invalid under the aws 6.x provider the module requires #630

Description

@jayyousi

Summary

Two aws_cloudwatch_event_target resources set rule from aws_cloudwatch_event_rule.<name>.id. Under the AWS provider 6.x generation that AFT itself requires, that attribute resolves to <bus>/<rule> — and the rule argument's own validator rejects the /.

The result is that terraform plan fails on a module version whose declared provider constraint is the very thing that breaks it.

Still present in 1.21.1.

Affected lines

modules/aft-account-request-framework/eventbridge.tf

# line 34
resource "aws_cloudwatch_event_target" "aft_management_event_bus" {
  provider = aws.ct_management
  arn      = aws_cloudwatch_event_bus.aft_from_ct_management.arn
  rule     = aws_cloudwatch_event_rule.aft_control_tower_events.id   # <-- .id
  role_arn = aws_iam_role.aft_control_tower_events.arn
}

# line 73
resource "aws_cloudwatch_event_target" "aft_account_request_processor" {
  arn  = aws_lambda_function.aft_account_request_processor.arn
  rule = aws_cloudwatch_event_rule.aft_account_request_processor.id   # <-- .id
}

Error

Error: invalid value for rule (must be 1-64 characters, matching [0-9A-Za-z_.-]+)

…with the offending value being e.g. default/aft-capture-ct-events — the bus name, a slash, then the rule name.

Why it is a module-side issue rather than a user misconfiguration

versions.tf in both 1.20.0 and 1.21.1 declares:

aws = {
  source  = "hashicorp/aws"
  version = ">= 6.0.0, < 7.0.0"
}

So provider 6.x is mandated, not chosen. Within 6.x, aws_cloudwatch_event_rule.id is the composite <bus>/<rule> form, while aws_cloudwatch_event_target.rule validates ^[0-9A-Za-z_.-]+$. The module therefore feeds a value into an argument that its own required provider generation makes invalid.

Users pinned to a late 6.x cannot work around it by downgrading the provider if their state was written by that later version — Terraform refuses to let an older provider read newer state.

Suggested fix

Use .name, which is what the argument expects and what the other targets in the same file already do:

rule = aws_cloudwatch_event_rule.aft_control_tower_events.name
rule = aws_cloudwatch_event_rule.aft_account_request_processor.name

modules/aft-code-repositories/codepipeline.tf (lines 105 and 352) already uses .name, as do aft_controltower_event_logger and aft_invoke_aft_account_provisioning_framework in this same file — so this looks like two occurrences that were simply missed rather than a deliberate difference.

Impact

Consumers currently have to patch the downloaded module source after every terraform init, since init re-downloads and reverts the change. That means the module running in production is not the module you published, and the divergence lives in an operator's script.

Happy to raise a PR with the two-line change if that is useful.

Versions

  • AFT: 1.20.0 and 1.21.1 (both affected; verified against the 1.21.1 source)
  • AWS provider: 6.46.0
  • Terraform: 1.15.x

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions