Skip to content

Remove SAM translator dependency, validate SAM templates via schemas - #4491

Merged
kddejong merged 1 commit into
aws-cloudformation:mainfrom
kddejong:remove-sam-translator
Aug 3, 2026
Merged

Remove SAM translator dependency, validate SAM templates via schemas#4491
kddejong merged 1 commit into
aws-cloudformation:mainfrom
kddejong:remove-sam-translator

Conversation

@kddejong

@kddejong kddejong commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

Summary

Replace the aws-sam-translator runtime dependency with direct JSON Schema validation of SAM resource types. SAM templates are now validated against schemas from the enhanced schemas service, using the same provider schema infrastructure as CloudFormation resources.

Changes

  • Remove _sam.py transform module and aws-sam-translator dependency
  • Add _sam_globals.py to merge Globals section properties into SAM resources
  • E3724: Validates Globals section structure against the SAM Globals schema
  • E3066: Validates that Connectors and IgnoreGlobals require the SAM transform
  • Lambda rule keywords: Extended Lambda rules (E2531, E2533, etc.) to also match AWS::Serverless::Function paths
  • Sub-resource wildcard: SAM resources use the same module wildcard mechanism for Ref/GetAtt
  • Implicit resource injection: SAM-generated resources (roles, versions, aliases, stages, permissions, etc.) are injected for validation
  • GetAtt resilience: Handle unresolvable schema pointers gracefully instead of crashing

Behavioral Notes

  • Input validation: SAM resource properties, Globals, events, and policies are validated against SAM schemas from the enhanced schemas service
  • Output validation: We no longer validate the transformed CFN output (generated IAM roles, API Gateway stages, etc.). SAM owns that correctness
  • Sub-resources: !Ref MyFunctionRole and !GetAtt MyFunction.Arn pass via the wildcard mechanism

Testing

  • Unit tests for globals merging, implicit resource injection, and new rules
  • Integration tests for good/bad SAM templates, IgnoreGlobals interaction
  • All existing integration tests pass
  • Verified no false positives on real-world SAM templates

Fixes #4556

@codecov

codecov Bot commented Apr 30, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.85714% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 94.44%. Comparing base (5faa41e) to head (6409d21).

Files with missing lines Patch % Lines
src/cfnlint/rules/functions/GetAtt.py 60.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4491      +/-   ##
==========================================
- Coverage   94.48%   94.44%   -0.04%     
==========================================
  Files         430      432       +2     
  Lines       15190    15214      +24     
  Branches     2921     2929       +8     
==========================================
+ Hits        14352    14369      +17     
- Misses        459      463       +4     
- Partials      379      382       +3     
Flag Coverage Δ
unittests 94.44% <98.85%> (-0.04%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@kddejong
kddejong force-pushed the remove-sam-translator branch 5 times, most recently from fdb75ab to aefb4dc Compare May 13, 2026 20:23
@kddejong kddejong changed the title WIP: Remove SAM translator dependency, validate SAM templates via schemas Remove SAM translator dependency, validate SAM templates via schemas May 13, 2026
@kddejong
kddejong force-pushed the remove-sam-translator branch from aefb4dc to 054499d Compare May 13, 2026 22:43
@kddejong
kddejong marked this pull request as ready for review May 14, 2026 15:48
@kddejong
kddejong force-pushed the remove-sam-translator branch 2 times, most recently from d0b4e98 to ca2ffa8 Compare June 25, 2026 22:58
@kddejong
kddejong force-pushed the remove-sam-translator branch 5 times, most recently from 5e771ed to 3ca222c Compare July 20, 2026 15:49
@kddejong
kddejong force-pushed the remove-sam-translator branch from 3ca222c to c1cc597 Compare July 20, 2026 16:20
Replace the aws-sam-translator runtime dependency with direct JSON Schema
validation of SAM resource types. SAM templates are now validated against
schemas from the enhanced schemas service using the same provider schema
infrastructure as CloudFormation resources.

- Remove _sam.py transform module and aws-sam-translator dependency
- Add _sam_globals.py to merge Globals section into SAM resources
- Add E3724 rule for Globals section validation
- Add E3066 rule for SAM resource attributes (Connectors, IgnoreGlobals)
- Extend Lambda rules to also match AWS::Serverless::Function paths
- Treat SAM resources as module-like for sub-resource Ref/GetAtt wildcard
- Handle unresolvable schema pointers gracefully in GetAtt validation
- Inject SAM implicit resources (roles, versions, aliases, stages, etc.)

Fixes aws-cloudformation#4556
@kddejong
kddejong force-pushed the remove-sam-translator branch from c1cc597 to 6409d21 Compare August 3, 2026 15:50
@kddejong
kddejong merged commit e00c456 into aws-cloudformation:main Aug 3, 2026
22 checks passed
@kddejong
kddejong deleted the remove-sam-translator branch August 3, 2026 20:00
@paul-uz

paul-uz commented Aug 6, 2026

Copy link
Copy Markdown

@kddejong I think this has broken something. 1.54.0 now reports E3001 Additional properties are not allowed ('Description' was unexpected) when an AWS::Serverless::Function resource has a Description. 1.53.0 did not have this issue.

@kddejong

kddejong commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

@paul-uz Thanks for reporting this. I've tracked it in #4606.

The issue is that Description is at the resource level (sibling of Type/Properties) rather than inside Properties. While this template does deploy successfully, the SAM transform silently drops the Description — your Lambda function ends up with an empty description.

Workaround: Move Description inside Properties:

Resources:
  MyFunction:
    Type: AWS::Serverless::Function
    Properties:
      Description: "Your description here"  # ✅ Correct location
      Runtime: python3.12
      ...

cfn-lint 1.54 is flagging this as an error, but since the template does technically deploy (just with the field silently ignored), we'll look at downgrading this to a warning for SAM resources.

kddejong added a commit that referenced this pull request Aug 10, 2026
Extend E3043 (NestedStackParameters) to also validate
AWS::Serverless::Application resources with local template
references. After PR #4491 removed the SAM translator, these
resources persist unexpanded and were no longer validated.

Changes:
- Add AWS::Serverless::Application to resource_property_types
- Handle Location property (local path, S3 URL, or SAR dict)
- Skip validation for remote URLs and SAR references
- Add type hints and refactor validation into shared method

Fixes #4612
@ashu99883

Copy link
Copy Markdown

Hi @kddejong I have created an issue for W3694 can you please check. I believe it may be due to this PR

kddejong added a commit that referenced this pull request Aug 11, 2026
* feat(lambda): require Handler/Runtime on Zip Serverless::Function in W2533

Extends rule W2533 (ZipPackageRequiredProperties) to also check
AWS::Serverless::Function resources for missing Handler and Runtime
properties when the package type is Zip.

Since PR #4491 removed the SAM translator, AWS::Serverless::Function
resources persist unexpanded in the template, and their schema does not
require Handler/Runtime. This change ensures Zip-package SAM functions
are validated the same way as AWS::Lambda::Function.

For SAM functions, Zip package is detected when:
- PackageType is "Zip" (authoritative, even if ImageUri also present)
- PackageType is absent AND ImageUri is NOT present, with CodeUri or
  InlineCode indicating zip deployment

Image-package SAM functions (PackageType: Image or ImageUri present
without explicit PackageType: Zip) are correctly excluded.

#4613

* test(W2533): cover SAM package-type branches

Add parametrized unit tests to cover all SAM package-type detection
branches in ZipPackageRequiredProperties:

- Bare SAM function (else: pass default Zip branch)
- Non-dict Properties guard (lines 163-164, 178-179)
- SAM Image via PackageType (line 107-108)
- SAM Image via ImageUri (line 112-114)
- SAM Zip via CodeUri (line 115-117)
- SAM Zip via InlineCode (line 118-120)
- SAM explicit PackageType: Zip (line 109-111)
- Lambda explicit PackageType: Zip (line 45-46)
- Lambda ZipFile/S3Key detection (line 47-48)
- Lambda Image function (line 49-50)

These tests call rule.match() directly with Template objects, covering
code paths that were missed by the fixture-based BaseRuleTestCase tests.
kddejong added a commit that referenced this pull request Aug 11, 2026
* feat(lambda): count SAM CloudWatchLogs events in E2529

Extend E2529 to also enumerate AWS::Serverless::Function CloudWatchLogs
events toward the 2-subscription-filter-per-log-group limit. Previously
only AWS::Logs::SubscriptionFilter resources were counted; since PR
#4491 removed the SAM translator, SAM resources persist unexpanded and
their CloudWatchLogs events were not flagged.

Changes:
- Add iteration over AWS::Serverless::Function resources in
  __get_log_group_name_list
- Extract LogGroupName from Events entries with Type: CloudWatchLogs
- Merge counts with explicit SubscriptionFilter resources
- Guard against non-dict/intrinsic values (Events, event, Properties)
- Report match at SAM function's real path:
  Resources/<Fn>/Properties/Events/<EventId>/Properties/LogGroupName
- Restore test expectation to 1 error for bad fixture
- Add comprehensive unit tests for SAM events, mixed scenarios, and
  edge cases (non-dict, missing properties, non-CloudWatchLogs events)

#4609

* test(E2529): cover SAM CloudWatchLogs guard branches

Add tests that exercise the defensive guard branches in the SAM
CloudWatchLogs event enumeration code to achieve 100% patch coverage.

New tests in TestEventsLogGroupNameGuardBranches class:
- test_subscription_filter_non_dict_properties: covers line 60
- test_sam_function_non_dict_properties: covers line 76
- test_sam_function_non_dict_events: covers line 79
- test_sam_function_non_dict_event_entry: covers line 83
- test_sam_cloudwatchlogs_non_dict_event_properties: covers line 88
- test_sam_cloudwatchlogs_missing_loggroupname: covers line 91
- test_sam_cloudwatchlogs_null_loggroupname: covers line 91

Removed redundant tests that didn't actually hit the guard branches
(they used intrinsic function dicts which pass isinstance(x, dict)).

#4609
kddejong added a commit that referenced this pull request Aug 18, 2026
#4636)

* fix: Validate Fn::Sub variable refs in schemaless regions (E1019)

E1019 was a metadata-only stub: `${Var}` validation ran solely on the
schema pipeline's `fn_sub` keyword, which is schema-guided and never
descends into schemaless object properties (e.g. an ApiGateway
`Body`/OpenAPI blob typed `{"type": ["object","string"]}`). Python
cfn-lint's validator recurses into such objects by default, so it flagged
`${Var}` references there and v2 under-reported (SAM
http_api_existing_openapi*).

The walker already visits every node and dispatches the `Fn/Sub` keyword
for each `Fn::Sub` at any depth (that is how W1019 works). Make E1019 a
real `Fn/Sub` walker rule that validates `${Var}` references against the
template's resources, parameters, pseudo-parameters, and the sub's own
local variables. Overlap with the schema-pipeline findings on
schema-covered subs is collapsed by the existing E1019 span+message dedup
in `engine::validate`, so this only adds findings the pipeline cannot
reach; the message format is kept byte-identical for that dedup.

Mirror the pipeline's bail-out: when a Fn::Sub's local-variable map holds
a `Ref` to an undefined target the value is unresolvable, so the whole
Fn::Sub is left unvalidated (Python does the same) — otherwise the
remaining `${Var}` references would be false positives (caught on
bad/functions_ref.yaml and bad/refs.yaml in the vs-python group).

SAM parity: matched 493 -> 496, python-only 7 -> 4, parity 98.6% -> 99.2%;
all six parity groups green. Ratchet min_matched 493 -> 496. Regression
tests cover schemaless-region reach, the invalid-localvar bail, valid
local vars, and resource-ref validity.

* fix: Attribute Output Refs to E6101 and report dotted Refs (E1020)

The E1020 Ref-existence walk had two divergences from Python cfn-lint on
Ref values that don't resolve to a resource, parameter, or
pseudo-parameter:

  * a Ref inside an Output value was reported as E1020, but Python
    attributes it to E6101 (the Outputs-value rule);
  * any Ref whose value contained a dot was skipped wholesale as a
    "SAM artifact", which also swallowed genuinely-invalid dotted Refs
    (e.g. `FunctionWithoutAlias.Version` — dots are not valid in a Ref).

Walk `Outputs` with rule id E6101 and the rest of the template with
E1020, and drop the blanket dot-skip: MODULE/Serverless dotted outputs
are already covered by the `is_module_sub` prefix check, and SAM
templates are excluded up front by `is_sam_template`, so the only Refs
the dot-skip was still hiding were real errors.

Fixes the SAM function_with_resource_refs E6101 under-report. Combined
with the E1019 walker fix in this branch: SAM matched 493 -> 497,
python-only 7 -> 3, parity 98.6% -> 99.4%; ratchet min_matched -> 497.
All six parity groups stay green. Regression tests cover output E6101
attribution and dotted-ref reporting.

* feat(sam): validate SAM templates via schemas (v1.54.0+v1.55.0 parity)

Bring cfn-lint v2 to parity with cfn-lint v1's SAM support after v1 dropped the
aws-sam-translator dependency (v1.54.0 #4491 + v1.55.0 follow-ups). SAM templates
are validated directly against SAM provider schemas instead of being transformed
to CloudFormation.

- Validate AWS::Serverless::* properties against SAM provider schemas (fix
  provider load when only SAM schemas present; add has_cfn_schemas guard)
- Merge SAM Globals into resources before validation (sam_globals)
- Inject SAM implicit resources (Function role/version/alias/url, API/HttpApi
  stages, CodeDeploy, StateMachine role, per-event permissions) and re-enable
  Ref/Sub validation for SAM templates (remove E1020/W1020 opt-out)
- E3066: validate SAM resource attributes (Connectors, IgnoreGlobals shape) and
  IgnoreGlobals key names against the Globals schema (E3724 parity)
- W3001: warn (not error) on ignored SAM resource-level attributes
- Extend rules to Serverless paths: E2529/W2530/W2533/E3043 plus the lambda
  family already covered (E2531/W2531/E2533/E3663/E3677/E3678/E3685/E3696/E3697)
- Align Globals schema key set

* test(sam): register E3066/W3001 in rule snapshot; nudge parity_good floor

The SAM work adds two rules (E3066 SAM attributes, W3001 ignored SAM
resource-level attributes) — record them in registered_rules.txt.

parity_good min_matched 49->48: one good SAM fixture
(relationship_conditions_sam.yaml) now correctly emits W2531 for the
newly-deprecated provided.al2 runtime (matches Python cfn-lint 1.55.0),
so it leaves the zero-findings set. Verified no new false positives
(max_rust_only unchanged).
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.

Using an Intrinsic Function in !Ref with LanguageExtensions and Serverless Transform results in an error

3 participants