From c9ef8d2ce684728fbc3eb6bd5f91d928976afb13 Mon Sep 17 00:00:00 2001 From: Mehmet Nuri Deveci <5735811+mndeveci@users.noreply.github.com> Date: Thu, 25 Nov 2021 16:13:25 -0800 Subject: [PATCH] fix: open api set_path_default_authorizer (#2248) Co-authored-by: Wing Fung Lau <4760060+hawflau@users.noreply.github.com> --- samtranslator/open_api/open_api.py | 2 +- .../input/http_api_multiple_authorizers.yaml | 61 ++++ .../aws-cn/http_api_multiple_authorizers.json | 287 ++++++++++++++++++ .../http_api_multiple_authorizers.json | 287 ++++++++++++++++++ .../output/http_api_multiple_authorizers.json | 287 ++++++++++++++++++ tests/translator/test_translator.py | 1 + 6 files changed, 924 insertions(+), 1 deletion(-) create mode 100644 tests/translator/input/http_api_multiple_authorizers.yaml create mode 100644 tests/translator/output/aws-cn/http_api_multiple_authorizers.json create mode 100644 tests/translator/output/aws-us-gov/http_api_multiple_authorizers.json create mode 100644 tests/translator/output/http_api_multiple_authorizers.json diff --git a/samtranslator/open_api/open_api.py b/samtranslator/open_api/open_api.py index 54e00ed05..9639a5baf 100644 --- a/samtranslator/open_api/open_api.py +++ b/samtranslator/open_api/open_api.py @@ -358,7 +358,7 @@ def set_path_default_authorizer(self, path, default_authorizer, authorizers, api continue existing_security = method_definition.get("security", []) if existing_security: - return + continue authorizer_list = [] if authorizers: authorizer_list.extend(authorizers.keys()) diff --git a/tests/translator/input/http_api_multiple_authorizers.yaml b/tests/translator/input/http_api_multiple_authorizers.yaml new file mode 100644 index 000000000..d23a443ce --- /dev/null +++ b/tests/translator/input/http_api_multiple_authorizers.yaml @@ -0,0 +1,61 @@ +Resources: + HttpApiFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: s3://sam-demo-bucket/todo_list.zip + Handler: index.restapi + Runtime: python3.7 + Events: + HelloGet: + Type: HttpApi + Properties: + Path: /hello + Method: get + ApiId: !Ref MyApi + HelloPut: + Type: HttpApi + Properties: + Path: /hello + Method: put + ApiId: !Ref MyApi + Auth: + Authorizer: MyOauth2Authorizer + HelloPost: + Type: HttpApi + Properties: + Path: /hello + Method: post + ApiId: !Ref MyApi + SimpleCase: # path exists, integration doesn't + Type: HttpApi + Properties: + ApiId: !Ref MyApi + + MyAuthFn: + Type: AWS::Serverless::Function + Properties: + CodeUri: s3://bucket/key + Handler: index.handler + Runtime: nodejs12.x + + MyApi: + Type: AWS::Serverless::HttpApi + Properties: + Tags: + Tag1: value1 + Tag2: value2 + Auth: + Authorizers: + LambdaAuth: + FunctionArn: !GetAtt MyAuthFn.Arn + AuthorizerPayloadFormatVersion: 1.0 + MyOauth2Authorizer: + AuthorizationScopes: + - scope + IdentitySource: $request.header.Authorization + JwtConfiguration: + audience: + - audience1 + - audience2 + issuer: "https://www.example.com/v1/connect/oidc" + DefaultAuthorizer: LambdaAuth \ No newline at end of file diff --git a/tests/translator/output/aws-cn/http_api_multiple_authorizers.json b/tests/translator/output/aws-cn/http_api_multiple_authorizers.json new file mode 100644 index 000000000..97e5c2493 --- /dev/null +++ b/tests/translator/output/aws-cn/http_api_multiple_authorizers.json @@ -0,0 +1,287 @@ +{ + "Resources": { + "HttpApiFunction": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "todo_list.zip" + }, + "Handler": "index.restapi", + "Role": { + "Fn::GetAtt": [ + "HttpApiFunctionRole", + "Arn" + ] + }, + "Runtime": "python3.7", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "HttpApiFunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "HttpApiFunctionSimpleCasePermission": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "HttpApiFunction" + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:${AWS::Partition}:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/*", + { + "__ApiId__": { + "Ref": "MyApi" + }, + "__Stage__": "*" + } + ] + } + } + }, + "MyAuthFn": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": "bucket", + "S3Key": "key" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "MyAuthFnRole", + "Arn" + ] + }, + "Runtime": "nodejs12.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyAuthFnRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyApi": { + "Type": "AWS::ApiGatewayV2::Api", + "Properties": { + "Body": { + "openapi": "3.0.1", + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/hello": { + "get": { + "x-amazon-apigateway-integration": { + "type": "aws_proxy", + "httpMethod": "POST", + "payloadFormatVersion": "2.0", + "uri": { + "Fn::Sub": "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HttpApiFunction.Arn}/invocations" + } + }, + "responses": {}, + "security": [ + { + "LambdaAuth": [] + } + ] + }, + "put": { + "x-amazon-apigateway-integration": { + "type": "aws_proxy", + "httpMethod": "POST", + "payloadFormatVersion": "2.0", + "uri": { + "Fn::Sub": "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HttpApiFunction.Arn}/invocations" + } + }, + "responses": {}, + "security": [ + { + "MyOauth2Authorizer": [ + "scope" + ] + } + ] + }, + "post": { + "x-amazon-apigateway-integration": { + "type": "aws_proxy", + "httpMethod": "POST", + "payloadFormatVersion": "2.0", + "uri": { + "Fn::Sub": "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HttpApiFunction.Arn}/invocations" + } + }, + "responses": {}, + "security": [ + { + "LambdaAuth": [] + } + ] + } + }, + "$default": { + "x-amazon-apigateway-any-method": { + "x-amazon-apigateway-integration": { + "type": "aws_proxy", + "httpMethod": "POST", + "payloadFormatVersion": "2.0", + "uri": { + "Fn::Sub": "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HttpApiFunction.Arn}/invocations" + } + }, + "isDefaultRoute": true, + "responses": {}, + "security": [ + { + "LambdaAuth": [] + } + ] + } + } + }, + "components": { + "securitySchemes": { + "LambdaAuth": { + "type": "apiKey", + "name": "Unused", + "in": "header", + "x-amazon-apigateway-authorizer": { + "type": "request", + "authorizerUri": { + "Fn::Sub": [ + "arn:aws-cn:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${__FunctionArn__}/invocations", + { + "__FunctionArn__": { + "Fn::GetAtt": [ + "MyAuthFn", + "Arn" + ] + } + } + ] + }, + "authorizerPayloadFormatVersion": 1.0 + } + }, + "MyOauth2Authorizer": { + "type": "oauth2", + "x-amazon-apigateway-authorizer": { + "jwtConfiguration": { + "audience": [ + "audience1", + "audience2" + ], + "issuer": "https://www.example.com/v1/connect/oidc" + }, + "identitySource": "$request.header.Authorization", + "type": "jwt" + } + } + } + }, + "tags": [ + { + "name": "Tag1", + "x-amazon-apigateway-tag-value": "value1" + }, + { + "name": "Tag2", + "x-amazon-apigateway-tag-value": "value2" + }, + { + "name": "httpapi:createdBy", + "x-amazon-apigateway-tag-value": "SAM" + } + ] + } + } + }, + "MyApiApiGatewayDefaultStage": { + "Type": "AWS::ApiGatewayV2::Stage", + "Properties": { + "ApiId": { + "Ref": "MyApi" + }, + "StageName": "$default", + "Tags": { + "Tag1": "value1", + "Tag2": "value2", + "httpapi:createdBy": "SAM" + }, + "AutoDeploy": true + } + } + } +} \ No newline at end of file diff --git a/tests/translator/output/aws-us-gov/http_api_multiple_authorizers.json b/tests/translator/output/aws-us-gov/http_api_multiple_authorizers.json new file mode 100644 index 000000000..cf32096be --- /dev/null +++ b/tests/translator/output/aws-us-gov/http_api_multiple_authorizers.json @@ -0,0 +1,287 @@ +{ + "Resources": { + "HttpApiFunction": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "todo_list.zip" + }, + "Handler": "index.restapi", + "Role": { + "Fn::GetAtt": [ + "HttpApiFunctionRole", + "Arn" + ] + }, + "Runtime": "python3.7", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "HttpApiFunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "HttpApiFunctionSimpleCasePermission": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "HttpApiFunction" + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:${AWS::Partition}:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/*", + { + "__ApiId__": { + "Ref": "MyApi" + }, + "__Stage__": "*" + } + ] + } + } + }, + "MyAuthFn": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": "bucket", + "S3Key": "key" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "MyAuthFnRole", + "Arn" + ] + }, + "Runtime": "nodejs12.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyAuthFnRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyApi": { + "Type": "AWS::ApiGatewayV2::Api", + "Properties": { + "Body": { + "openapi": "3.0.1", + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/hello": { + "get": { + "x-amazon-apigateway-integration": { + "type": "aws_proxy", + "httpMethod": "POST", + "payloadFormatVersion": "2.0", + "uri": { + "Fn::Sub": "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HttpApiFunction.Arn}/invocations" + } + }, + "responses": {}, + "security": [ + { + "LambdaAuth": [] + } + ] + }, + "put": { + "x-amazon-apigateway-integration": { + "type": "aws_proxy", + "httpMethod": "POST", + "payloadFormatVersion": "2.0", + "uri": { + "Fn::Sub": "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HttpApiFunction.Arn}/invocations" + } + }, + "responses": {}, + "security": [ + { + "MyOauth2Authorizer": [ + "scope" + ] + } + ] + }, + "post": { + "x-amazon-apigateway-integration": { + "type": "aws_proxy", + "httpMethod": "POST", + "payloadFormatVersion": "2.0", + "uri": { + "Fn::Sub": "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HttpApiFunction.Arn}/invocations" + } + }, + "responses": {}, + "security": [ + { + "LambdaAuth": [] + } + ] + } + }, + "$default": { + "x-amazon-apigateway-any-method": { + "x-amazon-apigateway-integration": { + "type": "aws_proxy", + "httpMethod": "POST", + "payloadFormatVersion": "2.0", + "uri": { + "Fn::Sub": "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HttpApiFunction.Arn}/invocations" + } + }, + "isDefaultRoute": true, + "responses": {}, + "security": [ + { + "LambdaAuth": [] + } + ] + } + } + }, + "components": { + "securitySchemes": { + "LambdaAuth": { + "type": "apiKey", + "name": "Unused", + "in": "header", + "x-amazon-apigateway-authorizer": { + "type": "request", + "authorizerUri": { + "Fn::Sub": [ + "arn:aws-us-gov:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${__FunctionArn__}/invocations", + { + "__FunctionArn__": { + "Fn::GetAtt": [ + "MyAuthFn", + "Arn" + ] + } + } + ] + }, + "authorizerPayloadFormatVersion": 1.0 + } + }, + "MyOauth2Authorizer": { + "type": "oauth2", + "x-amazon-apigateway-authorizer": { + "jwtConfiguration": { + "audience": [ + "audience1", + "audience2" + ], + "issuer": "https://www.example.com/v1/connect/oidc" + }, + "identitySource": "$request.header.Authorization", + "type": "jwt" + } + } + } + }, + "tags": [ + { + "name": "Tag1", + "x-amazon-apigateway-tag-value": "value1" + }, + { + "name": "Tag2", + "x-amazon-apigateway-tag-value": "value2" + }, + { + "name": "httpapi:createdBy", + "x-amazon-apigateway-tag-value": "SAM" + } + ] + } + } + }, + "MyApiApiGatewayDefaultStage": { + "Type": "AWS::ApiGatewayV2::Stage", + "Properties": { + "ApiId": { + "Ref": "MyApi" + }, + "StageName": "$default", + "Tags": { + "Tag1": "value1", + "Tag2": "value2", + "httpapi:createdBy": "SAM" + }, + "AutoDeploy": true + } + } + } +} \ No newline at end of file diff --git a/tests/translator/output/http_api_multiple_authorizers.json b/tests/translator/output/http_api_multiple_authorizers.json new file mode 100644 index 000000000..39eee42e4 --- /dev/null +++ b/tests/translator/output/http_api_multiple_authorizers.json @@ -0,0 +1,287 @@ +{ + "Resources": { + "HttpApiFunction": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "todo_list.zip" + }, + "Handler": "index.restapi", + "Role": { + "Fn::GetAtt": [ + "HttpApiFunctionRole", + "Arn" + ] + }, + "Runtime": "python3.7", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "HttpApiFunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "HttpApiFunctionSimpleCasePermission": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "HttpApiFunction" + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:${AWS::Partition}:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/*", + { + "__ApiId__": { + "Ref": "MyApi" + }, + "__Stage__": "*" + } + ] + } + } + }, + "MyAuthFn": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": "bucket", + "S3Key": "key" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "MyAuthFnRole", + "Arn" + ] + }, + "Runtime": "nodejs12.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyAuthFnRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyApi": { + "Type": "AWS::ApiGatewayV2::Api", + "Properties": { + "Body": { + "openapi": "3.0.1", + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/hello": { + "get": { + "x-amazon-apigateway-integration": { + "type": "aws_proxy", + "httpMethod": "POST", + "payloadFormatVersion": "2.0", + "uri": { + "Fn::Sub": "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HttpApiFunction.Arn}/invocations" + } + }, + "responses": {}, + "security": [ + { + "LambdaAuth": [] + } + ] + }, + "put": { + "x-amazon-apigateway-integration": { + "type": "aws_proxy", + "httpMethod": "POST", + "payloadFormatVersion": "2.0", + "uri": { + "Fn::Sub": "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HttpApiFunction.Arn}/invocations" + } + }, + "responses": {}, + "security": [ + { + "MyOauth2Authorizer": [ + "scope" + ] + } + ] + }, + "post": { + "x-amazon-apigateway-integration": { + "type": "aws_proxy", + "httpMethod": "POST", + "payloadFormatVersion": "2.0", + "uri": { + "Fn::Sub": "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HttpApiFunction.Arn}/invocations" + } + }, + "responses": {}, + "security": [ + { + "LambdaAuth": [] + } + ] + } + }, + "$default": { + "x-amazon-apigateway-any-method": { + "x-amazon-apigateway-integration": { + "type": "aws_proxy", + "httpMethod": "POST", + "payloadFormatVersion": "2.0", + "uri": { + "Fn::Sub": "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HttpApiFunction.Arn}/invocations" + } + }, + "isDefaultRoute": true, + "responses": {}, + "security": [ + { + "LambdaAuth": [] + } + ] + } + } + }, + "components": { + "securitySchemes": { + "LambdaAuth": { + "type": "apiKey", + "name": "Unused", + "in": "header", + "x-amazon-apigateway-authorizer": { + "type": "request", + "authorizerUri": { + "Fn::Sub": [ + "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${__FunctionArn__}/invocations", + { + "__FunctionArn__": { + "Fn::GetAtt": [ + "MyAuthFn", + "Arn" + ] + } + } + ] + }, + "authorizerPayloadFormatVersion": 1.0 + } + }, + "MyOauth2Authorizer": { + "type": "oauth2", + "x-amazon-apigateway-authorizer": { + "jwtConfiguration": { + "audience": [ + "audience1", + "audience2" + ], + "issuer": "https://www.example.com/v1/connect/oidc" + }, + "identitySource": "$request.header.Authorization", + "type": "jwt" + } + } + } + }, + "tags": [ + { + "name": "Tag1", + "x-amazon-apigateway-tag-value": "value1" + }, + { + "name": "Tag2", + "x-amazon-apigateway-tag-value": "value2" + }, + { + "name": "httpapi:createdBy", + "x-amazon-apigateway-tag-value": "SAM" + } + ] + } + } + }, + "MyApiApiGatewayDefaultStage": { + "Type": "AWS::ApiGatewayV2::Stage", + "Properties": { + "ApiId": { + "Ref": "MyApi" + }, + "StageName": "$default", + "Tags": { + "Tag1": "value1", + "Tag2": "value2", + "httpapi:createdBy": "SAM" + }, + "AutoDeploy": true + } + } + } +} \ No newline at end of file diff --git a/tests/translator/test_translator.py b/tests/translator/test_translator.py index 59d8d7c67..fdc5d0ad8 100644 --- a/tests/translator/test_translator.py +++ b/tests/translator/test_translator.py @@ -514,6 +514,7 @@ def test_transform_success(self, testcase, partition_with_region): "http_api_description", "http_api_lambda_auth", "http_api_lambda_auth_full", + "http_api_multiple_authorizers", ], [ ("aws", "ap-southeast-1"),