diff --git a/requirements/base.txt b/requirements/base.txt index 454be09c9f..b0b0b07a1a 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -5,7 +5,7 @@ boto3~=1.10, >=1.10.29 jmespath~=0.9.4 PyYAML~=5.1 cookiecutter~=1.6.0 -aws-sam-translator==1.18.0 +aws-sam-translator==1.19.0 docker~=4.0 dateparser~=0.7 python-dateutil~=2.6, <2.8.1 diff --git a/tests/functional/commands/validate/lib/models/explicit_http_api.yaml b/tests/functional/commands/validate/lib/models/explicit_http_api.yaml new file mode 100644 index 0000000000..afab76416e --- /dev/null +++ b/tests/functional/commands/validate/lib/models/explicit_http_api.yaml @@ -0,0 +1,43 @@ +Resources: + HttpApiFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: s3://sam-demo-bucket/todo_list.zip + Handler: index.restapi + Runtime: python3.7 + Events: + SimpleCase: + Type: HttpApi + Properties: + ApiId: !Ref MyApi + SimpleCase2: + Type: HttpApi + Properties: + ApiId: !Ref MyApi2 + MyApi: + Type: AWS::Serverless::HttpApi + Properties: + Auth: + Authorizers: + OAuth2: + AuthorizationScopes: + - scope4 + JwtConfiguration: + issuer: "https://www.example.com/v1/connect/oidc" + audience: + - MyApi + IdentitySource: "$request.querystring.param" + DefaultAuthorizer: OAuth2 + + MyApi2: + Type: AWS::Serverless::HttpApi + Properties: + Auth: + Authorizers: + OAuth2: + JwtConfiguration: + issuer: "https://www.example.com/v1/connect/oidc" + audience: + - MyApi + IdentitySource: "$request.querystring.param" + DefaultAuthorizer: OAuth2 \ No newline at end of file diff --git a/tests/functional/commands/validate/lib/models/explicit_http_api_minimum.yaml b/tests/functional/commands/validate/lib/models/explicit_http_api_minimum.yaml new file mode 100644 index 0000000000..9a968d22a4 --- /dev/null +++ b/tests/functional/commands/validate/lib/models/explicit_http_api_minimum.yaml @@ -0,0 +1,12 @@ +Resources: + Api: + Type: AWS::Serverless::HttpApi + Function: + Type: AWS::Serverless::Function + Properties: + Handler: index.handler + CodeUri: s3://bucket/key + Runtime: python3.7 + Events: + Api: + Type: HttpApi \ No newline at end of file diff --git a/tests/functional/commands/validate/lib/models/http_api_def_uri.yaml b/tests/functional/commands/validate/lib/models/http_api_def_uri.yaml new file mode 100644 index 0000000000..4e6c80316d --- /dev/null +++ b/tests/functional/commands/validate/lib/models/http_api_def_uri.yaml @@ -0,0 +1,34 @@ +Resources: + MyApi: + Type: AWS::Serverless::HttpApi + Properties: + DefinitionUri: s3://bucket/key + Tags: + Tag: value + StageName: !Join ["", ["Stage", "Name"]] + + MyApi2: + Type: AWS::Serverless::HttpApi + Properties: + DefinitionUri: + Bucket: bucket + Key: key + Version: version + Tags: + Tag: value + + Function: + Type: AWS::Serverless::Function + Properties: + Runtime: python3.7 + Handler: index.handler + CodeUri: s3://bucket/key + Events: + Api: + Type: HttpApi + Properties: + ApiId: MyApi + Api2: + Type: HttpApi + Properties: + ApiId: !Ref MyApi2 \ No newline at end of file diff --git a/tests/functional/commands/validate/lib/models/http_api_existing_openapi.yaml b/tests/functional/commands/validate/lib/models/http_api_existing_openapi.yaml new file mode 100644 index 0000000000..42df713cef --- /dev/null +++ b/tests/functional/commands/validate/lib/models/http_api_existing_openapi.yaml @@ -0,0 +1,94 @@ +Resources: + HttpApiFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: s3://sam-demo-bucket/todo_list.zip + Handler: index.restapi + Runtime: nodejs4.3 + Policies: AmazonDynamoDBFullAccess + Events: + Basic: # integration exists + Type: HttpApi + Properties: + Path: /basic + Method: post + ApiId: !Ref MyApi + SimpleCase: # path exists, integration doesn't + Type: HttpApi + Properties: + ApiId: !Ref MyApi + MyApi: + Type: AWS::Serverless::HttpApi + Properties: + DefinitionBody: + info: + version: '1.0' + title: + Ref: AWS::StackName + paths: + "/basic": + post: + x-amazon-apigateway-integration: + httpMethod: POST + type: aws_proxy + uri: + Fn::Sub: arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${DifferentFunction.Arn}/invocations + payloadFormatVersion: '1.0' + security: + - OpenIdAuth: + - scope3 + responses: {} + "/integration": + post: + x-amazon-apigateway-integration: + httpMethod: POST + type: aws_proxy + uri: + Fn::Sub: arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HttpApiFunction.Arn}/invocations + payloadFormatVersion: '1.0' + security: + - OpenIdAuth: + - scope1 + - scope2 + responses: {} + "$default": + x-amazon-apigateway-any-method: + isDefaultRoute: true + security: + - OpenIdAuth: + - scope1 + - scope2 + responses: {} + "/oauth2": + post: + x-amazon-apigateway-integration: + httpMethod: POST + type: aws_proxy + uri: + Fn::Sub: arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HttpApiFunction.Arn}/invocations + payloadFormatVersion: '1.0' + security: + - oauth2Auth: + - scope4 + responses: {} + openapi: 3.0.1 + securitySchemes: + oauth2Auth: + type: oauth2 + x-amazon-apigateway-authorizer: + identitySource: "$request.querystring.param" + type: jwt + jwtConfiguration: + audience: + - MyApi + issuer: https://www.example.com/v1/connect/oidc + OpenIdAuth: + type: openIdConnect + x-amazon-apigateway-authorizer: + identitySource: "$request.querystring.param" + type: jwt + jwtConfiguration: + audience: + - MyApi + issuer: https://www.example.com/v1/connect/oidc + openIdConnectUrl: https://www.example.com/v1/connect diff --git a/tests/functional/commands/validate/lib/models/http_api_existing_openapi_conditions.yaml b/tests/functional/commands/validate/lib/models/http_api_existing_openapi_conditions.yaml new file mode 100644 index 0000000000..056fef67b9 --- /dev/null +++ b/tests/functional/commands/validate/lib/models/http_api_existing_openapi_conditions.yaml @@ -0,0 +1,128 @@ +Conditions: + condition: + Fn::Equals: + - true + - true +Resources: + HttpApiFunction: + Condition: condition + Type: AWS::Serverless::Function + Properties: + CodeUri: s3://sam-demo-bucket/todo_list.zip + Handler: index.restapi + Runtime: python3.7 + Events: + Basic: # integration exists + Type: HttpApi + Properties: + Path: /basic + Method: post + ApiId: !Ref MyApi + Basic2: # integration exists, auth doesn't + Type: HttpApi + Properties: + Path: /basic + Method: get + ApiId: !Ref MyApi + Auth: + Authorizer: OAuth2 + AuthorizationScopes: + - basic + SimpleCase: # path exists, integration doesn't + Type: HttpApi + Properties: + ApiId: !Ref MyApi + MyApi: + Type: AWS::Serverless::HttpApi + Properties: + Auth: + Authorizers: + OAuth2: + AuthorizationScopes: + - scope4 + JwtConfiguration: + issuer: "https://www.example.com/v1/connect/oidc" + audience: + - MyApi + IdentitySource: "$request.querystring.param" + DefaultAuthorizer: OAuth2 + DefinitionBody: + info: + version: '1.0' + title: + Ref: AWS::StackName + paths: + "/basic": + post: + x-amazon-apigateway-integration: + httpMethod: POST + type: aws_proxy + uri: + Fn::Sub: arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${DifferentFunction.Arn}/invocations + payloadFormatVersion: '1.0' + security: + - OpenIdAuth: + - scope3 + responses: {} + get: + x-amazon-apigateway-integration: + httpMethod: POST + type: aws_proxy + uri: + Fn::Sub: arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${DifferentFunction.Arn}/invocations + payloadFormatVersion: '1.0' + responses: {} + "/integration": + post: + x-amazon-apigateway-integration: + httpMethod: POST + type: aws_proxy + uri: + Fn::Sub: arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HttpApiFunction.Arn}/invocations + payloadFormatVersion: '1.0' + security: + - OpenIdAuth: + - scope1 + - scope2 + responses: {} + "$default": + x-amazon-apigateway-any-method: + isDefaultRoute: true + security: + - OpenIdAuth: + - scope1 + - scope2 + responses: {} + "/oauth2": + post: + x-amazon-apigateway-integration: + httpMethod: POST + type: aws_proxy + uri: + Fn::Sub: arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HttpApiFunction.Arn}/invocations + payloadFormatVersion: '1.0' + security: + - oauth2Auth: + - scope4 + responses: {} + openapi: 3.0.1 + securitySchemes: + oauth2Auth: + type: oauth2 + x-amazon-apigateway-authorizer: + identitySource: "$request.querystring.param" + type: jwt + jwtConfiguration: + audience: + - MyApi + issuer: https://www.example.com/v1/connect/oidc + OpenIdAuth: + type: openIdConnect + x-amazon-apigateway-authorizer: + identitySource: "$request.querystring.param" + type: jwt + jwtConfiguration: + audience: + - MyApi + issuer: https://www.example.com/v1/connect/oidc + openIdConnectUrl: https://www.example.com/v1/connect diff --git a/tests/functional/commands/validate/lib/models/http_api_explicit_stage.yaml b/tests/functional/commands/validate/lib/models/http_api_explicit_stage.yaml new file mode 100644 index 0000000000..82455541d1 --- /dev/null +++ b/tests/functional/commands/validate/lib/models/http_api_explicit_stage.yaml @@ -0,0 +1,16 @@ +Resources: + HttpApiFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: s3://sam-demo-bucket/todo_list.zip + Handler: index.restapi + Runtime: nodejs4.3 + Events: + SimpleCase: + Type: HttpApi + Properties: + ApiId: !Ref MyApi + MyApi: + Type: AWS::Serverless::HttpApi + Properties: + StageName: Prod \ No newline at end of file diff --git a/tests/functional/commands/validate/lib/models/implicit_http_api.yaml b/tests/functional/commands/validate/lib/models/implicit_http_api.yaml new file mode 100644 index 0000000000..545d5a3706 --- /dev/null +++ b/tests/functional/commands/validate/lib/models/implicit_http_api.yaml @@ -0,0 +1,30 @@ +Resources: + HttpApiFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: s3://sam-demo-bucket/todo_list.zip + Handler: index.restapi + Runtime: nodejs4.3 + Policies: AmazonDynamoDBFullAccess + Events: + Basic: + Type: HttpApi + Properties: + Path: /basic + Method: post + SimpleCase: + Type: HttpApi + + HttpApiFunction2: + Type: AWS::Serverless::Function + Properties: + CodeUri: s3://sam-demo-bucket/todo_list.zip + Handler: index.restapi + Runtime: nodejs4.3 + Policies: AmazonDynamoDBFullAccess + Events: + Basic2: + Type: HttpApi + Properties: + Path: /basic2 + Method: post diff --git a/tests/functional/commands/validate/lib/models/implicit_http_api_auth_and_simple_case.yaml b/tests/functional/commands/validate/lib/models/implicit_http_api_auth_and_simple_case.yaml new file mode 100644 index 0000000000..c617e7d243 --- /dev/null +++ b/tests/functional/commands/validate/lib/models/implicit_http_api_auth_and_simple_case.yaml @@ -0,0 +1,69 @@ +Resources: + RestApiFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: s3://sam-demo-bucket/todo_list.zip + Handler: index.restapi + Runtime: nodejs4.3 + Policies: AmazonDynamoDBFullAccess + Events: + DefaultAuth: + Type: HttpApi + Properties: + Path: /defaultauth + Method: post + NoneAuth: + Type: HttpApi + Properties: + Path: /noneauth + Method: post + Auth: + Authorizer: NONE + ScopeOverride: + Type: HttpApi + Properties: + Path: /scope3 + Method: post + Auth: + AuthorizationScopes: + - scope3 + SomeAuth: + Type: HttpApi + Properties: + Path: /someauth + Method: post + Auth: + Authorizer: OpenIdAuth + oauth2Path: + Type: HttpApi + Properties: + Path: /oauth2 + Method: post + Auth: + Authorizer: oauth2Auth + SimpleCase: + Type: HttpApi + +Globals: + HttpApi: + Auth: + Authorizers: + OpenIdAuth: + AuthorizationScopes: + - scope1 + - scope2 + OpenIdConnectUrl: "https://www.example.com/v1/connect" + JwtConfiguration: + issuer: "https://www.example.com/v1/connect/oidc" + audience: + - MyApi + IdentitySource: "$request.querystring.param" + oauth2Auth: + AuthorizationScopes: + - scope4 + JwtConfiguration: + issuer: "https://www.example.com/v1/connect/oidc" + audience: + - MyApi + IdentitySource: "$request.querystring.param" + DefaultAuthorizer: OpenIdAuth diff --git a/tests/functional/commands/validate/lib/models/implicit_http_api_with_many_conditions.yaml b/tests/functional/commands/validate/lib/models/implicit_http_api_with_many_conditions.yaml new file mode 100644 index 0000000000..1fd8f9735c --- /dev/null +++ b/tests/functional/commands/validate/lib/models/implicit_http_api_with_many_conditions.yaml @@ -0,0 +1,242 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: 'AWS::Serverless-2016-10-31' +Description: A template to test for implicit HttpApi condition handling. +Conditions: + MyCondition: + Fn::Equals: + - true + - false + Cond: + Fn::Equals: + - true + - false + Cond1: + Fn::Equals: + - true + - false + Cond2: + Fn::Equals: + - true + - false + Cond3: + Fn::Equals: + - true + - false + Cond4: + Fn::Equals: + - true + - false + Cond5: + Fn::Equals: + - true + - false + Cond6: + Fn::Equals: + - true + - false + Cond7: + Fn::Equals: + - true + - false + Cond8: + Fn::Equals: + - true + - false + Cond9: + Fn::Equals: + - true + - false +Globals: + HttpApi: + Auth: + Authorizers: + oauth2: + AuthorizationScopes: + - scope4 + JwtConfiguration: + issuer: "https://www.example.com/v1/connect/oidc" + audience: + - MyApi + IdentitySource: "$request.querystring.param" +Resources: + hello: + Type: 'AWS::Serverless::Function' + Condition: MyCondition + Properties: + Handler: index.handler + Runtime: nodejs8.10 + MemorySize: 128 + Timeout: 3 + InlineCode: | + exports.handler = async () => ‘Hello World!' + Events: + HttpApiEvent: + Type: HttpApi + Properties: + Path: /sub + Method: get + helloworld1099: + Type: 'AWS::Serverless::Function' + Condition: Cond + Properties: + Handler: index.handler + Runtime: nodejs8.10 + MemorySize: 128 + Timeout: 3 + InlineCode: | + exports.handler = async () => ‘Hello World!' + Events: + HttpApiEvent: + Type: HttpApi + Properties: + Auth: + Authorizer: oauth2 + HttpApiEvent2: + Type: HttpApi + Properties: + Path: /hello/again + Method: get + helloworld1: + Type: 'AWS::Serverless::Function' + Condition: Cond1 + Properties: + Handler: index.handler + Runtime: nodejs8.10 + MemorySize: 128 + Timeout: 3 + InlineCode: | + exports.handler = async () => ‘Hello World!' + Events: + HttpApiEvent: + Type: HttpApi + Properties: + Path: /sub1 + Method: post + helloworld2: + Type: 'AWS::Serverless::Function' + Condition: Cond2 + Properties: + Handler: index.handler + Runtime: nodejs8.10 + MemorySize: 128 + Timeout: 3 + InlineCode: | + exports.handler = async () => ‘Hello World!' + Events: + HttpApiEvent: + Type: HttpApi + Properties: + Path: /sub2 + Method: post + helloworld3: + Type: 'AWS::Serverless::Function' + Condition: Cond3 + Properties: + Handler: index.handler + Runtime: nodejs8.10 + MemorySize: 128 + Timeout: 3 + InlineCode: | + exports.handler = async () => ‘Hello World!' + Events: + HttpApiEvent: + Type: HttpApi + Properties: + Path: /sub3 + Method: post + helloworld4: + Type: 'AWS::Serverless::Function' + Condition: Cond4 + Properties: + Handler: index.handler + Runtime: nodejs8.10 + MemorySize: 128 + Timeout: 3 + InlineCode: | + exports.handler = async () => ‘Hello World!' + Events: + HttpApiEvent: + Type: HttpApi + Properties: + Path: /sub4 + Method: post + helloworld5: + Type: 'AWS::Serverless::Function' + Condition: Cond5 + Properties: + Handler: index.handler + Runtime: nodejs8.10 + MemorySize: 128 + Timeout: 3 + InlineCode: | + exports.handler = async () => ‘Hello World!' + Events: + HttpApiEvent: + Type: HttpApi + Properties: + Path: /sub5 + Method: post + helloworld6: + Type: 'AWS::Serverless::Function' + Condition: Cond6 + Properties: + Handler: index.handler + Runtime: nodejs8.10 + MemorySize: 128 + Timeout: 3 + InlineCode: | + exports.handler = async () => ‘Hello World!' + Events: + HttpApiEvent: + Type: HttpApi + Properties: + Path: /sub6 + Method: post + helloworld7: + Type: 'AWS::Serverless::Function' + Condition: Cond7 + Properties: + Handler: index.handler + Runtime: nodejs8.10 + MemorySize: 128 + Timeout: 3 + InlineCode: | + exports.handler = async () => ‘Hello World!' + Events: + HttpApiEvent: + Type: HttpApi + Properties: + Path: /sub7 + Method: post + helloworld8: + Type: 'AWS::Serverless::Function' + Condition: Cond8 + Properties: + Handler: index.handler + Runtime: nodejs8.10 + MemorySize: 128 + Timeout: 3 + InlineCode: | + exports.handler = async () => ‘Hello World!' + Events: + HttpApiEvent: + Type: HttpApi + Properties: + Path: /sub8 + Method: post + helloworld9: + Type: 'AWS::Serverless::Function' + Condition: Cond9 + Properties: + Handler: index.handler + Runtime: nodejs8.10 + MemorySize: 128 + Timeout: 3 + InlineCode: | + exports.handler = async () => ‘Hello World!' + Events: + HttpApiEvent: + Type: HttpApi + Properties: + Path: /sub9 + Method: post diff --git a/tests/functional/commands/validate/lib/test_sam_template_validator.py b/tests/functional/commands/validate/lib/test_sam_template_validator.py index 284cc754a3..e64995c640 100644 --- a/tests/functional/commands/validate/lib/test_sam_template_validator.py +++ b/tests/functional/commands/validate/lib/test_sam_template_validator.py @@ -84,6 +84,8 @@ class TestValidate(TestCase): ("tests/functional/commands/validate/lib/models/explicit_api.yaml"), ("tests/functional/commands/validate/lib/models/explicit_api_openapi_3.yaml"), ("tests/functional/commands/validate/lib/models/explicit_api_with_invalid_events_config.yaml"), + ("tests/functional/commands/validate/lib/models/explicit_http_api.yaml"), + ("tests/functional/commands/validate/lib/models/explicit_http_api_minimum.yaml"), ("tests/functional/commands/validate/lib/models/function_concurrency.yaml"), ("tests/functional/commands/validate/lib/models/function_event_conditions.yaml"), ("tests/functional/commands/validate/lib/models/function_managed_inline_policy.yaml"), @@ -127,11 +129,18 @@ class TestValidate(TestCase): ("tests/functional/commands/validate/lib/models/globals_for_function.yaml"), ("tests/functional/commands/validate/lib/models/globals_for_function_path.yaml"), ("tests/functional/commands/validate/lib/models/globals_for_simpletable.yaml"), + ("tests/functional/commands/validate/lib/models/http_api_def_uri.yaml"), + ("tests/functional/commands/validate/lib/models/http_api_existing_openapi.yaml"), + ("tests/functional/commands/validate/lib/models/http_api_existing_openapi_conditions.yaml"), + ("tests/functional/commands/validate/lib/models/http_api_explicit_stage.yaml"), ("tests/functional/commands/validate/lib/models/implicit_and_explicit_api_with_conditions.yaml"), ("tests/functional/commands/validate/lib/models/implicit_api.yaml"), ("tests/functional/commands/validate/lib/models/implicit_api_with_auth_and_conditions_max.yaml"), ("tests/functional/commands/validate/lib/models/implicit_api_with_many_conditions.yaml"), ("tests/functional/commands/validate/lib/models/implicit_api_with_serverless_rest_api_resource.yaml"), + ("tests/functional/commands/validate/lib/models/implicit_http_api.yaml"), + ("tests/functional/commands/validate/lib/models/implicit_http_api_auth_and_simple_case.yaml"), + ("tests/functional/commands/validate/lib/models/implicit_http_api_with_many_conditions.yaml"), ("tests/functional/commands/validate/lib/models/intrinsic_functions.yaml"), ("tests/functional/commands/validate/lib/models/iot_rule.yaml"), ("tests/functional/commands/validate/lib/models/layers_all_properties.yaml"),