Skip to content

fix(cloudformation): keep CloudFront CustomErrorResponses through provisioning - #2561

Open
Sorttech wants to merge 1 commit into
faiscadev:mainfrom
Sorttech:fix/cfn-cloudfront-custom-error-responses
Open

Sorttech wants to merge 1 commit into
faiscadev:mainfrom
Sorttech:fix/cfn-cloudfront-custom-error-responses

Conversation

@Sorttech

@Sorttech Sorttech commented Sep 25, 2026 •

Copy link
Copy Markdown

Two fidelity mismatches on the same block, both of which left a
CFN-provisioned SPA distribution with no deep-link fallback.

Translating the CFN block ran each rule through serde_json::from_value
into the wire struct and dropped anything that failed. CloudFormation
types ResponseCode as an Integer while the CloudFront API carries it as
a string, so every rule failed to deserialize and the distribution came
out with Quantity: 0. Map the fields explicitly instead, coercing the
number and accepting the quoted form YAML templates and resolved
intrinsics produce. A rule missing the required ErrorCode is skipped
rather than defaulted to a code that would match nothing.

ErrorCachingMinTTL then still failed to round-trip: rename_all = "PascalCase" renders it ErrorCachingMinTtl, so the field was mis-named
on the wire and dropped on parse from real SDK requests. Pin the AWS
spelling, as WebACLId in the same file already does.

Test plan

Regression test: cfn_provisions_spa_custom_error_responses in crates/fakecloud-e2e/tests/cloudformation_cloudfront.rs

Verification

On this exact head, rebased onto current main:

  • cargo fmt --all --check - clean.
  • cargo clippy --workspace --all-targets -- -D warnings - clean.
  • cargo test --workspace excluding fakecloud-e2e, fakecloud-conformance,
    fakecloud-tfacc and fakecloud-parity (the same set CI's test job runs),
    plus cargo test -p fakecloud-conformance --lib - 9836 passed, 1 failed
    (--no-fail-fast, --test-threads=4). The failure is in fakecloud-ssm
    (service::tests::send_command_completion_persists_success); an earlier run
    of the same command failed its sibling
    rearm_in_flight_commands_settles_restored_pending instead. Both read the
    last durable snapshot right after the in-memory status flips to Success
    while the save is asynchronous, and they fail 4 of 11 runs on untouched
    main on this machine. This branch does not touch SSM.
  • cargo test -p fakecloud-e2e --test cloudformation_cloudfront - the
    regression test above passes against a freshly built target/debug/fakecloud.

Found by deploying a CDK CloudFront + S3 SPA against fakecloud.


Summary by cubic

Fixes CloudFormation provisioning so CloudFront distributions keep their CustomErrorResponses (the SPA deep-link fallback) instead of provisioning with Quantity: 0.

Two mismatches caused the loss:

  • CloudFormation types ResponseCode as an Integer while the CloudFront API carries it as a string, so translating each rule through serde_json::from_value into the wire struct failed and silently dropped every rule. Fields are now mapped explicitly, coercing the number and accepting quoted values from YAML templates and resolved intrinsics.
  • ErrorCachingMinTTL was emitted as ErrorCachingMinTtl by rename_all = "PascalCase" and dropped on parse; the AWS spelling is now pinned, as WebACLId already is.

Rules missing the required ErrorCode are skipped rather than defaulted to a code that would match nothing. Adds a regression test.

Written for commit a951ab7. Summary will update on new commits.

Review in cubic

…visioning

Two fidelity mismatches on the same block, both of which left a
CFN-provisioned SPA distribution with no deep-link fallback.

Translating the CFN block ran each rule through `serde_json::from_value`
into the wire struct and dropped anything that failed. CloudFormation
types `ResponseCode` as an Integer while the CloudFront API carries it as
a string, so every rule failed to deserialize and the distribution came
out with `Quantity: 0`. Map the fields explicitly instead, coercing the
number and accepting the quoted form YAML templates and resolved
intrinsics produce. A rule missing the required `ErrorCode` is skipped
rather than defaulted to a code that would match nothing.

`ErrorCachingMinTTL` then still failed to round-trip: `rename_all =
"PascalCase"` renders it `ErrorCachingMinTtl`, so the field was mis-named
on the wire and dropped on parse from real SDK requests. Pin the AWS
spelling, as `WebACLId` in the same file already does.

This branch has not been deployed

No deployments
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.

1 participant