Skip to content

fix: stackset template asset keys diverge from the objects the asset bucket deployment uploads#896

Open
dannysteenman wants to merge 1 commit into
cdklabs:mainfrom
dannysteenman:fix/file-asset-object-key-mismatch
Open

fix: stackset template asset keys diverge from the objects the asset bucket deployment uploads#896
dannysteenman wants to merge 1 commit into
cdklabs:mainfrom
dannysteenman:fix/file-asset-object-key-mismatch

Conversation

@dannysteenman

Copy link
Copy Markdown

Fixes #895

Problem

Deploying a StackSet whose StackSetStack contains an AwsCustomResource (or any construct backed by an aws-cdk-lib custom-resource handler) fails on every stack instance with:

ResourceType:AWS::Lambda::Function, ResourceStatusReason:Resource handler returned message:
"Error occurred while GetObject. S3 Error Code: NoSuchKey. ..."

StackSetStackSynthesizer.addFileAsset() derives the template's S3 object key from the hash embedded in the staged asset file name:

const assetFileBaseName = path.basename(asset.fileName);
const s3Filename = assetFileBaseName.split('.')[1] + '.zip';

But the object that actually lands in the asset bucket is uploaded by the BucketDeployment created in the same method: Source.asset(assetPath) re-stages the staged asset and computes a fresh content fingerprint, and with extract: false the destination object key is that fingerprint — not the hash in the staged file name.

These two keys are only identical when the original asset's hash is the plain content fingerprint. That implicit assumption broke with aws-cdk-lib 2.258.0: aws/aws-cdk#37634 ("custom-resource-handlers: deterministic asset hashes for generated lambdas") stages all generated custom-resource handler assets with an explicit assetHash, e.g.:

code: lambda.Code.fromAsset(path.join(__dirname, "aws-custom-resource-handler"), {
  assetHash: "048c51b339711116c3b9feefa3c6aff37c49dba2a4d0f1f531fa8337d9602d82"
}),

I verified the regression window release by release: the generated handlers in aws-cdk-lib 2.254.0–2.257.0 contain no assetHash; 2.258.0 is the first version that does. Concrete values from a real deployment on 2.258.1:

  • staged folder: cdk.out/asset.8b1c21ef... (derived from the custom assetHash)
  • template Code.S3Key: 8b1c21ef....zipnever uploadedNoSuchKey
  • key actually uploaded by the BucketDeployment: 0528c009....zip (= FileSystem.fingerprint() of the staged directory)

Fix

Derive the template's object key the same way Source.asset() does, so the two can never diverge:

const objectKey = `${FileSystem.fingerprint(assetPath)}.zip`;

For assets whose hash already is the content fingerprint (plain directory assets, pre-zipped bundled assets such as NodejsFunction output), this produces the exact same key as before — no template churn, no re-uploads. Only custom-hash assets, which were broken, change key.

Testing

  • New regression test lambda asset keys in the stackset template match the bucket deployment uploads synthesizes a StackSetStack containing a Lambda asset with an explicit assetHash and asserts every Code.S3Key in the stackset template appears in the parent stack's Custom::CDKBucketDeployment SourceObjectKeys. It fails against the previous implementation and passes with this change.
  • Full suite: 20/20 tests, eslint, and the integ.stack-set snapshot pass unchanged.
  • Verified end to end in a real AWS Organization: a landing-zone deployment that consistently failed with NoSuchKey on aws-cdk-lib 2.258.1 deploys successfully with this fix applied.

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

…bucket deployment uploads

The template's S3 object key was derived from the hash embedded in the
staged asset file name, while the BucketDeployment uploads the asset under
the re-staged content fingerprint (Source.asset + extract: false). For
assets staged with an explicit assetHash - such as the aws-cdk-lib
custom-resource handler assets since v2.258.0 (aws/aws-cdk#37634) - the two
hashes diverge and stack instances fail with S3 NoSuchKey. Derive the
template key from the same content fingerprint the upload uses.

Fixes cdklabs#895
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.

StackSetStack file assets fail with S3 NoSuchKey when assets are staged with a custom assetHash (aws-cdk-lib >= 2.254 custom-resource handlers)

1 participant