Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

fix(custom-resource-handlers): deterministic asset hashes for generated lambdas#37634

Merged
mergify[bot] merged 6 commits into
aws:mainaws/aws-cdk:mainfrom
clayrosenthal:fix-custom-resource-handlers-deterministic-asset-hashesclayrosenthal/aws-cdk:fix-custom-resource-handlers-deterministic-asset-hashesCopy head branch name to clipboard
May 22, 2026
Merged

fix(custom-resource-handlers): deterministic asset hashes for generated lambdas#37634
mergify[bot] merged 6 commits into
aws:mainaws/aws-cdk:mainfrom
clayrosenthal:fix-custom-resource-handlers-deterministic-asset-hashesclayrosenthal/aws-cdk:fix-custom-resource-handlers-deterministic-asset-hashesCopy head branch name to clipboard

Conversation

@clayrosenthal

Copy link
Copy Markdown
Contributor

Issue # (if applicable)

Closes #34307

Reason for this change

Custom-resource handler Lambdas generated by the handler framework (e.g., aws-ses drop-spam, aws-logs log-retention, many others) stage their code via:

code: lambda.Code.fromAsset(path.join(__dirname, 'handler'))

Because no explicit assetHash is provided, AssetStaging fingerprints the bundled directory at synth time and the fingerprint includes filesystem metadata (mtime, mode). Two synths of identical source on different machines therefore produce different S3 object keys, so cdk diff shows spurious Lambda asset updates against the cloud — even when the bundled bytes are byte-for-byte identical.

Description of changes

  • Added calculateDirectoryHash to packages/@aws-cdk/custom-resource-handlers/scripts/generate.ts. It walks the bundled handler directory deterministically (sorted entries, SHA-256 over relative paths + file content bytes) and computes a content-only hash.
  • Plumbed the hash through HandlerFrameworkModule.build → HandlerFrameworkClass via a new optional sourceHash field on HandlerFrameworkClassProps.
  • When sourceHash is supplied, the code generator emits Code.fromAsset(path, { assetHash: '<hash>' })AssetStaging then uses it as the CUSTOM fingerprint so the S3 object key depends only on the bundled bytes.
  • Applied only to FUNCTION and SINGLETON_FUNCTION components. CUSTOM_RESOURCE_PROVIDER is intentionally skipped because CustomResourceProviderBase mixes __entrypoint__.js into the staged directory at synth time, which would cause a generate-time hash to drift from the final bundle.

Description of how you validated changes

  • Added unit tests in packages/@aws-cdk/custom-resource-handlers/test/custom-resources-framework/framework.test.ts asserting that the generated TypeScript contains the expected assetHash for both FUNCTION and SINGLETON_FUNCTION components. All 11 tests in the file pass.
  • Rebuilt the custom-resource-handlers package and aws-cdk-lib, and synthesized a test stack containing s3.Bucket { autoDeleteObjects: true } (CRP-based, unchanged) and ses.ReceiptRuleSet { dropSpam: true } (singleton-based, hash-pinned). Confirmed:
    • the generated drop-spam-provider.generated.ts now emits a baked assetHash;
    • the S3 object key for the drop-spam asset is stable across multiple synths even after changing the handler file's mtime (2020 vs 2099) and mode (644 vs 755) — previously the fingerprint would have changed.

Checklist


By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license

@github-actions github-actions Bot added beginning-contributor [Pilot] contributed between 0-2 PRs to the CDK effort/medium Medium work item – several days of effort feature-request A feature should be added or improved. p2 labels Apr 18, 2026
@aws-cdk-automation
aws-cdk-automation requested a review from a team April 18, 2026 22:14

@aws-cdk-automation aws-cdk-automation left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

(This review is outdated)

@github-actions

github-actions Bot commented Apr 18, 2026

Copy link
Copy Markdown
Contributor

⚠️ Experimental Feature: This security report is currently in experimental phase. Results may include false positives and the rules are being actively refined.
This security report is NOT a review blocker. Please try merge from main to avoid findings unrelated to the PR.
To suppress a specific rule, see Suppressing Rules.


TestsPassed ☑️SkippedFailed ❌️
Security Guardian Results1128 ran1124 passed4 failed
TestResult
Security Guardian Results
packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.global-replicas-provisioned.js.snapshot/aws-cdk-dynamodb-global-replicas-provisioned.template.json
iam-no-wildcard-actions.guard❌ failure
packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.global.js.snapshot/cdk-dynamodb-global-20191121.template.json
iam-no-wildcard-actions.guard❌ failure
packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/integ-cognito.template.json
ec2-no-open-security-groups.guard❌ failure
packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.oidc.js.snapshot/IntegAlbOidc.template.json
ec2-no-open-security-groups.guard❌ failure

@github-actions

github-actions Bot commented Apr 18, 2026

Copy link
Copy Markdown
Contributor

⚠️ Experimental Feature: This security report is currently in experimental phase. Results may include false positives and the rules are being actively refined.
This security report is NOT a review blocker. Please try merge from main to avoid findings unrelated to the PR.
To suppress a specific rule, see Suppressing Rules.


TestsPassed ☑️SkippedFailed ❌️
Security Guardian Results with resolved templates1128 ran1122 passed6 failed
TestResult
Security Guardian Results with resolved templates
packages/@aws-cdk-testing/framework-integ/test/aws-codepipeline-actions/test/integ.pipeline-commands.js.snapshot/aws-cdk-codepipeline-commands.template.json
iam-role-root-principal-needs-conditions.guard❌ failure
packages/@aws-cdk-testing/framework-integ/test/aws-codepipeline-actions/test/integ.pipeline-ecr-image-scan-action.js.snapshot/codepipeline-ecr-image-scan-action.template.json
iam-role-root-principal-needs-conditions.guard❌ failure
packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.global-replicas-provisioned.js.snapshot/aws-cdk-dynamodb-global-replicas-provisioned.template.json
iam-no-wildcard-actions.guard❌ failure
packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.global.js.snapshot/cdk-dynamodb-global-20191121.template.json
iam-no-wildcard-actions.guard❌ failure
packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/integ-cognito.template.json
ec2-no-open-security-groups.guard❌ failure
packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.oidc.js.snapshot/IntegAlbOidc.template.json
ec2-no-open-security-groups.guard❌ failure

…ed lambdas

Custom-resource handler Lambdas generated by the handler framework previously
staged their code via `lambda.Code.fromAsset(path)` with no explicit asset hash,
so `AssetStaging` fingerprinted the bundled directory at synth time. Because
that fingerprint depends on filesystem metadata (mtime, mode), the resulting
S3 object key differed between machines even when the bundled bytes were
identical — causing `cdk diff` to show spurious Lambda asset updates when
comparing a local synth to what was previously uploaded to S3.

Compute a content-only SHA-256 of each bundled handler directory at generation
time (in `scripts/generate.ts`) and bake it into the generated framework class
as `Code.fromAsset(path, { assetHash })`. The value depends only on file
names and bytes, so the S3 object key is now stable across machines.

The new `sourceHash` option on `HandlerFrameworkClassProps` is optional and
only emitted for `FUNCTION` and `SINGLETON_FUNCTION` components.
`CUSTOM_RESOURCE_PROVIDER` components are left untouched because
`CustomResourceProviderBase` mixes `__entrypoint__.js` into the staged
directory at synth time, so a hash pinned at generate time would drift from
the final bundle.

Closes aws#34307

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@clayrosenthal
clayrosenthal force-pushed the fix-custom-resource-handlers-deterministic-asset-hashes branch from e51c338 to 178b111 Compare April 20, 2026 23:57
The deterministic asset hashes emitted by the generated custom-resource
handler classes produce new S3 object keys, so every integ snapshot that
exercises an affected handler needs its asset directory renamed and its
JSON manifests rewritten to reference the new hash.

Updated by renaming the asset directories and replacing the old hash
with the new hash in the snapshot JSON files. No other snapshot content
is changed.
@clayrosenthal
clayrosenthal force-pushed the fix-custom-resource-handlers-deterministic-asset-hashes branch from 178b111 to 0a98f55 Compare April 21, 2026 01:42
otaviomacedo
otaviomacedo previously approved these changes Apr 22, 2026
…s-framework/classes.ts

Co-authored-by: Otavio Macedo <288203+otaviomacedo@users.noreply.github.com>
…generation

Pass the source hash through expr.lit so expr.object receives an
Expression instead of a raw string, and apply the same expr.object form
to the SingletonFunction call site for consistency. Update the two
framework tests to match the multi-line rendering that expr.object
produces.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@aws-cdk-automation

Copy link
Copy Markdown
Collaborator

This PR has been in the CHANGES REQUESTED state for 3 weeks, and looks abandoned. Note that PRs with failing linting check or builds are not reviewed, please ensure your build is passing

To prevent automatic closure:

  • Resume work on the PR
  • OR request an exemption by adding a comment containing 'Exemption Request' with justification e.x "Exemption Request: "
  • OR request clarification by adding a comment containing 'Clarification Request' with a question e.x "Clarification Request: "

This PR will automatically close in 14 days if no action is taken.

@clayrosenthal

Copy link
Copy Markdown
Contributor Author

I've made loads of changes since the changes were requested, the bot never re-reviewed. @aws-cdk-automation I've added integ tests now!

@clayrosenthal

Copy link
Copy Markdown
Contributor Author

@otaviomacedo do these security guardian results need to be fixed or not? Most are not changes I made

… snapshots

Security Guardian flagged pre-existing findings in integ snapshots that
this PR's deterministic-asset-hash change brought into scope (the asset
hash field changed, so Security Guardian re-scanned the templates).

Fixes the three findings that are addressable in test code:

- aws-events-targets integ.log-group: enable SQS-managed encryption on
  the integ test's DLQ.
- aws-logs-destinations integ.lambda: enable SQS-managed encryption on
  the integ test's destination queue.
- custom-resources integ.aws-custom-resource: replace ssm:* with the
  specific actions the test exercises (GetParameter, GetParameters,
  GetParametersByPath, DescribeParameters).

The four remaining Security Guardian findings come from CDK framework
defaults (DynamoDB replication policy, ALB internet-facing ingress,
CodePipeline cross-account action role trust) and are pre-existing on
main. Addressing them requires feature-flagged framework changes and
belongs in separate PRs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@aws-cdk-automation
aws-cdk-automation dismissed their stale review May 21, 2026 20:31

✅ Updated pull request passes all PRLinter validations. Dismissing previous PRLinter review.

@mergify

mergify Bot commented May 21, 2026

Copy link
Copy Markdown
Contributor

Thank you for contributing! Your pull request will be updated from main and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork).

@mergify

mergify Bot commented May 21, 2026

Copy link
Copy Markdown
Contributor

Merge Queue Status

  • Entered queue2026-05-21 21:02 UTC · Rule: default-squash
  • 🚫 Left the queue2026-05-21 21:33 UTC · at 2b056652b71c1cbcee6a350ac4d94a103bd374ee

This pull request spent 31 minutes 40 seconds in the queue, with no time running CI.

Reason

The pull request can't be updated

For security reasons, Mergify can't update this pull request. Try updating locally.
GitHub response: refusing to allow a GitHub App to create or update workflow .github/workflows/agent-docs-sync-reminder.yml without workflows permission

Hint

You should update or rebase your pull request manually. If you do, this pull request will automatically be requeued once the queue conditions match again.
If you think this was a flaky issue, you can requeue the pull request, without updating it, by posting a @mergifyio queue comment.

@mergify
mergify Bot dismissed otaviomacedo’s stale review May 22, 2026 08:16

Pull request has been modified.

@mergify

mergify Bot commented May 22, 2026

Copy link
Copy Markdown
Contributor

Thank you for contributing! Your pull request will be updated from main and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork).

@mergify

mergify Bot commented May 22, 2026

Copy link
Copy Markdown
Contributor

Merge Queue Status

  • Entered queue2026-05-22 09:01 UTC · Rule: default-squash
  • Checks skipped · PR is already up-to-date
  • Merged2026-05-22 09:01 UTC · at f520ccc041b43c79ea751c6bf5c7c7c0f3976471 · squash

This pull request spent 26 seconds in the queue, including 4 seconds running CI.

Required conditions to merge

@mergify
mergify Bot merged commit 6c3d5bc into aws:main May 22, 2026
23 of 27 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

Comments on closed issues and PRs are hard for our team to see.
If you need help, please open a new issue that references this one.

@github-actions github-actions Bot locked as resolved and limited conversation to collaborators May 22, 2026
@clayrosenthal
clayrosenthal deleted the fix-custom-resource-handlers-deterministic-asset-hashes branch May 26, 2026 20:19
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

beginning-contributor [Pilot] contributed between 0-2 PRs to the CDK effort/medium Medium work item – several days of effort feature-request A feature should be added or improved. p2

Projects

None yet

Development

Successfully merging this pull request may close these issues.

(custom-resource-handlers): Add hashes to generated lambdas

4 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.