diff --git a/cfn-lint-serverless/cfn_lint_serverless/rules/api_gateway.py b/cfn-lint-serverless/cfn_lint_serverless/rules/api_gateway.py index b24d2d9..602afd7 100644 --- a/cfn-lint-serverless/cfn_lint_serverless/rules/api_gateway.py +++ b/cfn-lint-serverless/cfn_lint_serverless/rules/api_gateway.py @@ -72,8 +72,15 @@ def _check_log_format(self, log_format: str) -> bool: As users can use non-string keys like '$context.integration.latency', we need to transform the log format into something that can be decoded into JSON first. + + If the log format is not a string (e.g., it's an intrinsic function like + !Ref or !Sub), we skip validation and return True. """ + # Skip validation when Format is an intrinsic function (Ref/Sub/etc.) + if not isinstance(log_format, str): + return True + # Strip any leading/trailing quotes and whitespace that might be in the string log_format = log_format.strip() if (log_format.startswith("'") and log_format.endswith("'")) or ( diff --git a/cfn-lint-serverless/tests/templates/ws2001-http-sub-format.pass.yaml b/cfn-lint-serverless/tests/templates/ws2001-http-sub-format.pass.yaml new file mode 100644 index 0000000..98559d4 --- /dev/null +++ b/cfn-lint-serverless/tests/templates/ws2001-http-sub-format.pass.yaml @@ -0,0 +1,23 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: Test WS2001 when Format is !Sub for HTTP APIs + +Resources: + HttpApi: + Type: AWS::ApiGatewayV2::Api + Properties: + Name: test-http-api + ProtocolType: HTTP + + HttpApiStage: + Type: AWS::ApiGatewayV2::Stage + Properties: + ApiId: !Ref HttpApi + StageName: prod + AutoDeploy: true + AccessLogSettings: + DestinationArn: !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/apigateway/http' + Format: !Sub '{"requestId":"$context.requestId","ip":"$context.identity.sourceIp","requestTime":"$context.requestTime","httpMethod":"$context.httpMethod","routeKey":"$context.routeKey","status":"$context.status","protocol":"$context.protocol","responseLength":"$context.responseLength"}' + DefaultRouteSettings: + ThrottlingBurstLimit: 1000 + ThrottlingRateLimit: 10 diff --git a/cfn-lint-serverless/tests/templates/ws2001-rest-ref-format.pass.yaml b/cfn-lint-serverless/tests/templates/ws2001-rest-ref-format.pass.yaml new file mode 100644 index 0000000..014f6ec --- /dev/null +++ b/cfn-lint-serverless/tests/templates/ws2001-rest-ref-format.pass.yaml @@ -0,0 +1,42 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: Test WS2001 when Format is !Ref + +Parameters: + LogFormat: + Type: String + Default: '{"requestId":"$context.requestId"}' + +Resources: + Api: + Type: AWS::Serverless::Api + Properties: + StageName: prod + AccessLogSetting: + DestinationArn: !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/apigateway' + Format: !Ref LogFormat + DefinitionBody: + openapi: "3.0.1" + info: + title: "test-api" + version: 1.0.0 + paths: + /: + get: + responses: + "200": + description: "OK" + x-amazon-apigateway-integration: + requestTemplates: + application/json: '{"statusCode": 200}' + passthroughBehavior: when_no_match + responses: + default: + statusCode: "200" + type: mock + MethodSettings: + - HttpMethod: "*" + ResourcePath: "/*" + ThrottlingRateLimit: 10 + ThrottlingBurstLimit: 1000 + TracingEnabled: true