Skip to content

fix: resolve for_each and data references - #285

Merged
ajkerrigan merged 6 commits into
cloud-custodian:mainfrom
ajkerrigan:ajk/fix/for-each-and-data-references
Sep 21, 2026
Merged

ajkerrigan merged 6 commits into
cloud-custodian:mainfrom
ajkerrigan:ajk/fix/for-each-and-data-references

Conversation

@ajkerrigan

Copy link
Copy Markdown
Member

Address 2 cases where we weren't properly tracking or resolving references:

  1. Module references when combined with for_each (see each.value.<attr> unresolved when the for_each collection contains a module output reference #283)
  2. References to data attributes (see References to data sources aren't fully tracked #277)

Ideally we'll land cloud-custodian/trivy#22 before merging this.

Closes #277
Closes #283

ajkerrigan and others added 4 commits September 10, 2026 13:31
Reference paths came from Reference.String(), which keeps any trailing
attribute names. A reference such as `data.aws_x.example.offering_id`
therefore never matched the path of the block it points at,
`data.aws_x.example`, so the reference was dropped from block metadata.

Resource references worked only by accident: their block type is left
out of the path, which shifts every part up by one and leaves the common
`type.name.attr` form with nothing trailing to drop. A resource
reference that did reach into a nested attribute, such as
`aws_x.one.tags.Name`, was dropped in the same way.

Trim the remainder off when building the lookup path.

Fixes cloud-custodian#277

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A resource whose for_each collection held a module output was never
expanded, leaving each.key/each.value unbound in its body. Two shapes
are covered: the collection built in the root module, and the collection
passed into a sibling module that gets evaluated before the one
producing the output.

The fix is in the trivy parser (cloud-custodian/trivy#21); these tests
need that change pinned in gotfparse/go.mod to pass.

Fixes cloud-custodian#283

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Points at the head of cloud-custodian/trivy#22, which makes the cloud-custodian#283
tests pass. Repin to a merge commit on main once that PR lands.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Re-run tfparse/c7n-left tests following tweaks to
cloud-custodian/trivy#22
With cloud-custodian/trivy#22 merged, pin to the squashed commit on
main.
Go's module proxy was pulling a previous commit from main. I sorted it
out locally but somehow pushed the wrong one anyway. Wheeeeeee.

@tvansteenburgh tvansteenburgh left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks @ajkerrigan.

@ajkerrigan
ajkerrigan merged commit 6e480c2 into cloud-custodian:main Sep 21, 2026
15 checks passed
@ajkerrigan
ajkerrigan deleted the ajk/fix/for-each-and-data-references branch September 21, 2026 16:43
tvansteenburgh pushed a commit to stacklet/sinistral-cli that referenced this pull request Oct 5, 2026
[ENG-8511](https://stacklet.atlassian.net/browse/ENG-8511)

Release PR for 0.5.39. Picks up the c7n-left release that fixes
unresolved `for_each` values
when the collection contains a module output reference.

### what

Upgrades c7n-left from 0.3.38 to 0.3.39, which brings c7n 0.9.53,
tfparse 0.6.22 and
python-hcl2 8.1.4, and bumps the package version to 0.5.39.

The boto3/botocore pins move from 1.43.78 to 1.43.103. As with the last
release, this is
required: c7n 0.9.53 pins `boto3==1.43.103`. The lockfile refresh also
pulls in minor
transitive and development updates.

python-hcl2 jumps a major version (4.3.5 to 8.1.4). It's pinned by
c7n-left and not
imported by sinistral directly.

### why

tfparse 0.6.22 fixes `each.value.<attr>` resolution when a `for_each`
collection contains a
module output reference. Previously the `for_each` didn't expand at all:
the scan saw a
single bare `aws_sqs_queue.x` with attributes like `tags` left as an
unresolved
`each.value.tags` marker. Policies then evaluated the marker instead of
the real value.
That produced false positives on compliant resources and reported
findings against the
wrong address.

It also tracks references from resources to `data` source attributes.

Upstream: cloud-custodian/tfparse#283,
cloud-custodian/tfparse#277 and
cloud-custodian/tfparse#285

### testing

Lint and the test suite pass.

Adds a regression test (`test_submit_run_foreach_module_output`) with a
fixture whose
`for_each` mixes a compliant entry tagged via a module output and a
static entry missing
the required tag. Only the static entry should be reported:

| c7n-left | scan result |
| --- | --- |
| 0.3.38 | one finding on bare `aws_sqs_queue.x`, tags
`{"__attribute__": "each.value.tags", ...}` (test fails) |
| 0.3.39 | one finding on `aws_sqs_queue.x["untagged"]`, tags `{"Team":
"platform"}` (test passes) |

### docs

Release notes updated.

Note for reviewers: merging this does not publish anything. The
`v0.5.39` tag push is
what triggers the release workflow, and CI does not run on tag pushes,
so this PR is the
only gate.

[ENG-8511]:
https://stacklet.atlassian.net/browse/ENG-8511?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

each.value.<attr> unresolved when the for_each collection contains a module output reference References to data sources aren't fully tracked

2 participants