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
Summary
Two
aws_cloudwatch_event_targetresources setrulefromaws_cloudwatch_event_rule.<name>.id. Under the AWS provider 6.x generation that AFT itself requires, that attribute resolves to<bus>/<rule>— and theruleargument's own validator rejects the/.The result is that
terraform planfails 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.tfError
…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.tfin both 1.20.0 and 1.21.1 declares:So provider 6.x is mandated, not chosen. Within 6.x,
aws_cloudwatch_event_rule.idis the composite<bus>/<rule>form, whileaws_cloudwatch_event_target.rulevalidates^[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:modules/aft-code-repositories/codepipeline.tf(lines 105 and 352) already uses.name, as doaft_controltower_event_loggerandaft_invoke_aft_account_provisioning_frameworkin 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