Skip to content

fix: keep literal lambda ARNs account/region-portable (#170)#180

Merged
awsandy merged 1 commit into
aws-samples:masterfrom
ecukalla:fix/lambda-policy-arn-portable
Jul 15, 2026
Merged

fix: keep literal lambda ARNs account/region-portable (#170)#180
awsandy merged 1 commit into
aws-samples:masterfrom
ecukalla:fix/lambda-policy-arn-portable

Conversation

@ecukalla

Copy link
Copy Markdown
Contributor

Follow-up to the caveat noted on #172 (which fixed #170) — awsandy asked to fix it if I got the chance.

Problem

globals_replace keeps certain lambda ARNs literal rather than de-referencing them to aws_lambda_function.<name>.arn:

In every one of those the ARN was emitted with the account id and region hard-coded inline:

"aws:SourceArn" = "arn:aws:lambda:<region>:<account>:function:my-function"

This is the caveat #172 called out: the lambda branch returns before reaching the account/region format(...) substitution that other ARN types get, so these ARNs are not account/region-portable.

Fix

Route those literals through a new sub_acct_region() helper that substitutes this account's id/region with data.aws_caller_identity.current.account_id / data.aws_region.current.region — the same substitution the tail of globals_replace already applies to other ARN types:

"aws:SourceArn" = format("arn:aws:lambda:%s:%s:function:my-function", data.aws_region.current.region, data.aws_caller_identity.current.account_id)

The function name stays literal, so the #172 cycle fix is preserved (the role still does not depend on the lambda). An ARN in a different account (this account's id not present) is left fully literal — de-referencing it to data.aws_caller_identity would be wrong.

Behaviour change beyond the SourceArn case

#172 fixed only the aws:SourceArn cycle. This change also makes the policy Resource, wildcard and cross-region lambda literals account/region-portable — cases that previously kept account/region inline and worked, but were not portable. They now render as format(...) with data sources. The value produced at apply time is identical, so terraform plan shows no diff; flagging it because it is a behaviour change on paths that already worked.

Testing

Environment: python 3.12, AWS provider 6.53.0.

  • globals_replace exercised standalone against 7 line shapes: aws:SourceArn / policy Resource / wildcard / cross-region / uncollected-function all become portable format(...) literals with the function name kept literal; a different-account ARN stays fully literal; and an ordinary attribute for a collected function still de-references to aws_lambda_function.<name>.arn (unchanged). All 7 pass.
  • Reproduced end-to-end on a real, vendor-supplied lambda execution role whose trust policy restricts assumption to its own function via an aws:SourceArn condition (the exact Lambda execution role trust policy with aws:SourceArn creates a terraform cycle - run aborts at exit 020 #170 shape). Imported the function and its role: terraform validate passes (no cycle), plan is 0 to add, 0 to change, 0 to destroy, and the generated trust policy renders the condition as
    "aws:SourceArn" = format("arn:aws:lambda:%s:%s:function:<name>", data.aws_region.current.region, data.aws_caller_identity.current.account_id)
    account/region portable, function name literal.

globals_replace keeps some lambda ARNs literal instead of de-referencing
them to aws_lambda_function.<name>.arn: an aws:SourceArn policy condition or
a policy Resource naming the function that owns the role (de-referencing
those cycles - aws-samples#170/aws-samples#172), a wildcard, a cross-region function, or a
function not collected in this run. Those literals were emitted with the
account id and region hard-coded inline.

Route them through a new sub_acct_region() helper that substitutes this
account's id/region with data.aws_caller_identity / data.aws_region - the
same substitution other ARN types already get later in globals_replace. The
function name stays literal, so the aws-samples#172 cycle fix is preserved; an ARN in a
different account (this account's id absent) is left fully literal.
@awsandy
awsandy merged commit c8960ea into aws-samples:master Jul 15, 2026
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.

Lambda execution role trust policy with aws:SourceArn creates a terraform cycle - run aborts at exit 020

2 participants