-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Fix: SAM crashes method_definition for path is invalid #1802
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -534,6 +534,14 @@ def set_path_default_authorizer( | |
for method_definition in self.get_method_contents(self.get_path(path)[normalized_method_name]): | ||
|
||
# If no integration given, then we don't need to process this definition (could be AWS::NoValue) | ||
if not isinstance(method_definition, dict): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we start refactoring these branches? The patterns are essentially identical, but takes 8 LoC for a single check. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. irrelevant: we should have mypy to end this manual type check nightmare! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if we define the possible types of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the challenge right now and itself could be a lot of work (of course worth doing) which is to assess and note every parameter's data type. If we can do that then it would solve all current and future SAM crashes as well. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @prenx4x There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And more generally, this sort of "lazy" checking doesn't seem to be ideal; maybe we can validate up-front what needs to be validated, and use EAFP elsewhere. This would reduce complexity and improve maintainability. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see. One thing to note here is that the errors could be similar, but the message (or cause) is very different. This message is seen by the user and it should be clear enough to point out the issue in their template. We we find same errors with same cause at multiple places we can refactor it, but if causes are different then they should be separate exceptions. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right, and that's fine; messages can be custom. But we should still be continuously improving our codebase. This doesn't mean refactoring everything at once, but if we recognize common patterns that can benefit from refactoring in new code, we should go ahead and do it, and ensure that in the long term our quality keeps increasing. |
||
raise InvalidDocumentException( | ||
[ | ||
InvalidTemplateException( | ||
"{} for path {} is not a valid dictionary.".format(method_definition, path) | ||
) | ||
] | ||
) | ||
if not self.method_definition_has_integration(method_definition): | ||
continue | ||
existing_security = method_definition.get("security", []) | ||
|
@@ -548,6 +556,14 @@ def set_path_default_authorizer( | |
# (e.g. sigv4 (AWS_IAM), api_key (API Key/Usage Plans), NONE (marker for ignoring default)) | ||
# We want to ensure only a single Authorizer security entry exists while keeping everything else | ||
for security in existing_security: | ||
if not isinstance(security, dict): | ||
raise InvalidDocumentException( | ||
[ | ||
InvalidTemplateException( | ||
"{} in Security for path {} is not a valid dictionary.".format(security, path) | ||
) | ||
] | ||
) | ||
if authorizer_names.isdisjoint(security.keys()): | ||
existing_non_authorizer_security.append(security) | ||
else: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
Globals: | ||
Api: | ||
Name: "some api" | ||
CacheClusterEnabled: True | ||
CacheClusterSize: "1.6" | ||
Auth: | ||
DefaultAuthorizer: MyCognitoAuth | ||
Authorizers: | ||
MyCognitoAuth: | ||
UserPoolArn: !GetAtt MyUserPool.Arn | ||
Variables: | ||
SomeVar: Value | ||
|
||
Resources: | ||
ImplicitApiFunction: | ||
Type: AWS::Serverless::Function | ||
Properties: | ||
CodeUri: s3://sam-demo-bucket/member_portal.zip | ||
Handler: index.gethtml | ||
Runtime: nodejs12.x | ||
Events: | ||
GetHtml: | ||
Type: Api | ||
Properties: | ||
Path: / | ||
Method: get | ||
|
||
ExplicitApi: | ||
Type: AWS::Serverless::Api | ||
Properties: | ||
StageName: SomeStage | ||
DefinitionBody: | ||
swagger: 2.0 | ||
info: | ||
version: '1.0' | ||
title: !Ref AWS::StackName | ||
paths: | ||
"/": | ||
parameters: | ||
- name: domain | ||
in: path | ||
description: Application domain | ||
type: string | ||
required: true | ||
tags: | ||
- InvalidMethodDefinition | ||
get: | ||
x-amazon-apigateway-integration: | ||
httpMethod: POST | ||
type: aws_proxy | ||
uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ImplicitApiFunction.Arn}/invocations | ||
responses: {} | ||
|
||
MyUserPool: | ||
Type: AWS::Cognito::UserPool | ||
Properties: | ||
UserPoolName: UserPoolName | ||
Policies: | ||
PasswordPolicy: | ||
MinimumLength: 8 | ||
UsernameAttributes: | ||
Schema: | ||
- AttributeDataType: String | ||
Name: email | ||
Required: false |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
Mappings: | ||
|
||
Parameters: | ||
Stage: | ||
Type: String | ||
Default: 'beta' | ||
Deployment: | ||
Type: String | ||
Default: 'AllAtOnce' | ||
Custom: | ||
Type: String | ||
Default: 'CustomDeployment' | ||
|
||
Resources: | ||
MinimalFunction: | ||
Type: 'AWS::Serverless::Function' | ||
Properties: | ||
CodeUri: s3://sam-demo-bucket/hello.zip | ||
Handler: hello.handler | ||
Runtime: python2.7 | ||
AutoPublishAlias: live | ||
DeploymentPreference: | ||
Type: TestDeploymentConfiguration |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
transformId: AWS::Serverless-2016-10-31 | ||
AWSTemplateFormatVersion: '2010-09-09' | ||
Resources: | ||
AuthFunction: | ||
Type: AWS::Serverless::Function | ||
AccessingPartyAPI: | ||
Type: AWS::Serverless::Api | ||
Properties: | ||
EndpointConfiguration: REGIONAL | ||
StageName: demo | ||
Auth: | ||
DefaultAuthorizer: CustomAuthorizer | ||
Authorizers: | ||
CustomAuthorizer: | ||
FunctionPayloadType: TOKEN | ||
FunctionArn: | ||
Fn::GetAtt: | ||
- AuthFunction | ||
- Arn | ||
AddDefaultAuthorizerToCorsPreflight: false | ||
DefinitionBody: | ||
paths: | ||
"/path": | ||
put: | ||
responses: | ||
'201': | ||
content: | ||
application/json: | ||
schema: | ||
"$ref": "abcd" | ||
x-amazon-apigateway-integration: | ||
contentHandling: CONVERT_TO_TEXT | ||
responses: | ||
default: | ||
statusCode: '200' | ||
uri: | ||
Fn::Sub: foobar | ||
httpMethod: POST | ||
passthroughBehavior: when_no_match | ||
type: aws_proxy | ||
requestBody: | ||
content: | ||
application/json: | ||
schema: | ||
required: | ||
- readoutId | ||
- status | ||
type: object | ||
security: | ||
CustomAuthorizer: [] | ||
|
||
openapi: 3.0.3 | ||
components: | ||
securitySchemes: | ||
CustomAuthorizer: | ||
in: header | ||
type: apiKey | ||
name: Authorization | ||
|
||
AccessingPartyAPIFunction: | ||
Type: AWS::Serverless::Function | ||
Properties: | ||
Events: | ||
PutReservation: | ||
Type: Api | ||
Properties: | ||
Path: "/path" | ||
RestApiId: | ||
Ref: AccessingPartyAPI | ||
Method: put |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{"errorMessage":"Invalid Serverless Application Specification document. Number of errors found: 1. Structure of the SAM template is invalid. ['InvalidMethodDefinition'] for path / is not a valid dictionary."} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{"errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. Structure of the SAM template is invalid. 'Mappings' or 'Parameters' is either null or not a valid dictionary."} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. Structure of the SAM template is invalid. CustomAuthorizer in Security for path /path is not a valid dictionary." | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is
TypeError
causes 500 errors?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry, what?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we raise
TypeError
instead ofInvalidDocumentException
, will it cause 500 server error on lambda execution? Is that the reason we changed the type of the exception here?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ohh i see. yes TypeError causes 500 server error.