diff --git a/bin/validate_schema.py b/bin/validate_schema.py index 0d2a6fdb28..e6a10f9531 100755 --- a/bin/validate_schema.py +++ b/bin/validate_schema.py @@ -26,6 +26,7 @@ def get_templates() -> Iterator[Path]: "resource_with_invalid_type", "state_machine_with_null_events", "state_machine_with_cwe", # Doesn't match schema at all... + "function_with_null_events", ] def should_skip(s: str) -> bool: diff --git a/samtranslator/schema/schema.json b/samtranslator/schema/schema.json index c0cb1d4428..a8272fff8f 100644 --- a/samtranslator/schema/schema.json +++ b/samtranslator/schema/schema.json @@ -330,6 +330,232 @@ ], "additionalProperties": false }, + "FunctionCodeUri": { + "title": "FunctionCodeUri", + "type": "object", + "properties": { + "Bucket": { + "title": "Bucket", + "anyOf": [ + { + "type": "string" + }, + { + "type": "object" + } + ] + }, + "Key": { + "title": "Key", + "anyOf": [ + { + "type": "string" + }, + { + "type": "object" + } + ] + }, + "Version": { + "title": "Version", + "anyOf": [ + { + "type": "string" + }, + { + "type": "object" + } + ] + } + }, + "required": [ + "Bucket", + "Key" + ], + "additionalProperties": false + }, + "FunctionDeadLetterQueue": { + "title": "FunctionDeadLetterQueue", + "type": "object", + "properties": { + "TargetArn": { + "title": "Targetarn", + "type": "string" + }, + "Type": { + "title": "Type", + "enum": [ + "SNS", + "SQS" + ], + "type": "string" + } + }, + "required": [ + "TargetArn", + "Type" + ], + "additionalProperties": false + }, + "FunctionDeploymentPreferenceHooks": { + "title": "FunctionDeploymentPreferenceHooks", + "type": "object", + "properties": { + "PostTraffic": { + "title": "Posttraffic", + "anyOf": [ + { + "type": "string" + }, + { + "type": "object" + } + ] + }, + "PreTraffic": { + "title": "Pretraffic", + "anyOf": [ + { + "type": "string" + }, + { + "type": "object" + } + ] + } + }, + "additionalProperties": false + }, + "FunctionDeploymentPreference": { + "title": "FunctionDeploymentPreference", + "type": "object", + "properties": { + "Alarms": { + "title": "Alarms", + "anyOf": [ + { + "type": "array", + "items": { + "type": "object" + } + }, + { + "type": "object" + } + ] + }, + "Enabled": { + "title": "Enabled", + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "object" + } + ] + }, + "Hooks": { + "$ref": "#/definitions/FunctionDeploymentPreferenceHooks" + }, + "PassthroughCondition": { + "title": "Passthroughcondition", + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "object" + } + ] + }, + "Role": { + "title": "Role", + "anyOf": [ + { + "type": "string" + }, + { + "type": "object" + } + ] + }, + "TriggerConfigurations": { + "title": "Triggerconfigurations" + }, + "Type": { + "title": "Type", + "anyOf": [ + { + "type": "string" + }, + { + "type": "object" + } + ] + } + }, + "additionalProperties": false + }, + "FunctionEventInvokeConfiguration": { + "title": "FunctionEventInvokeConfiguration", + "type": "object", + "properties": { + "DestinationConfig": { + "title": "Destinationconfig" + }, + "MaximumEventAgeInSeconds": { + "title": "Maximumeventageinseconds", + "type": "integer" + }, + "MaximumRetryAttempts": { + "title": "Maximumretryattempts", + "type": "integer" + } + }, + "additionalProperties": false + }, + "FunctionEvent": { + "title": "FunctionEvent", + "type": "object", + "properties": { + "Properties": { + "title": "Properties" + }, + "Type": { + "title": "Type", + "type": "string" + } + }, + "required": [ + "Type" + ], + "additionalProperties": false + }, + "FunctionUrlConfig": { + "title": "FunctionUrlConfig", + "type": "object", + "properties": { + "AuthType": { + "title": "Authtype", + "anyOf": [ + { + "type": "string" + }, + { + "type": "object" + } + ] + }, + "Cors": { + "title": "Cors" + } + }, + "required": [ + "AuthType" + ], + "additionalProperties": false + }, "FunctionProperties": { "title": "FunctionProperties", "description": "By default strict\nhttps://pydantic-docs.helpmanual.io/usage/model_config/#change-behaviour-globally", @@ -339,25 +565,66 @@ "title": "Architectures" }, "AssumeRolePolicyDocument": { - "title": "Assumerolepolicydocument" + "title": "Assumerolepolicydocument", + "type": "object" }, "AutoPublishAlias": { - "title": "Autopublishalias" + "title": "Autopublishalias", + "anyOf": [ + { + "type": "string" + }, + { + "type": "object" + } + ] }, "AutoPublishCodeSha256": { - "title": "Autopublishcodesha256" + "title": "Autopublishcodesha256", + "anyOf": [ + { + "type": "string" + }, + { + "type": "object" + } + ] }, "CodeSigningConfigArn": { - "title": "Codesigningconfigarn" + "title": "Codesigningconfigarn", + "anyOf": [ + { + "type": "string" + }, + { + "type": "object" + } + ] }, "CodeUri": { - "title": "Codeuri" + "title": "Codeuri", + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/FunctionCodeUri" + } + ] }, "DeadLetterQueue": { - "title": "Deadletterqueue" + "title": "Deadletterqueue", + "anyOf": [ + { + "type": "object" + }, + { + "$ref": "#/definitions/FunctionDeadLetterQueue" + } + ] }, "DeploymentPreference": { - "title": "Deploymentpreference" + "$ref": "#/definitions/FunctionDeploymentPreference" }, "Description": { "title": "Description" @@ -369,10 +636,14 @@ "title": "Ephemeralstorage" }, "EventInvokeConfig": { - "title": "Eventinvokeconfig" + "$ref": "#/definitions/FunctionEventInvokeConfiguration" }, "Events": { - "title": "Events" + "title": "Events", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/FunctionEvent" + } }, "FileSystemConfigs": { "title": "Filesystemconfigs" @@ -381,7 +652,7 @@ "title": "Functionname" }, "FunctionUrlConfig": { - "title": "Functionurlconfig" + "$ref": "#/definitions/FunctionUrlConfig" }, "Handler": { "title": "Handler" @@ -411,7 +682,28 @@ "title": "Permissionsboundary" }, "Policies": { - "title": "Policies" + "title": "Policies", + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object" + } + ] + } + }, + { + "type": "object" + } + ] }, "ProvisionedConcurrencyConfig": { "title": "Provisionedconcurrencyconfig" @@ -420,19 +712,36 @@ "title": "Reservedconcurrentexecutions" }, "Role": { - "title": "Role" + "title": "Role", + "anyOf": [ + { + "type": "string" + }, + { + "type": "object" + } + ] }, "Runtime": { "title": "Runtime" }, "Tags": { - "title": "Tags" + "title": "Tags", + "type": "object" }, "Timeout": { "title": "Timeout" }, "Tracing": { - "title": "Tracing" + "title": "Tracing", + "anyOf": [ + { + "type": "string" + }, + { + "type": "object" + } + ] }, "VersionDescription": { "title": "Versiondescription" diff --git a/samtranslator/schema/schema.py b/samtranslator/schema/schema.py index 818c87fb49..2f897d55d5 100644 --- a/samtranslator/schema/schema.py +++ b/samtranslator/schema/schema.py @@ -6,7 +6,6 @@ import pydantic from pydantic import Extra - # TODO: Get rid of this in favor of proper types Unknown = Optional[Any] @@ -52,42 +51,86 @@ class AwsServerlessConnector(BaseModel): Properties: ConnectorProperties +class FunctionCodeUri(BaseModel): + Bucket: Union[str, SamIntrinsic] + Key: Union[str, SamIntrinsic] + Version: Optional[Union[str, SamIntrinsic]] + + +class FunctionDeploymentPreferenceHooks(BaseModel): + PostTraffic: Optional[Union[str, SamIntrinsic]] + PreTraffic: Optional[Union[str, SamIntrinsic]] + + +class FunctionDeploymentPreference(BaseModel): + Alarms: Optional[Union[List[SamIntrinsic], SamIntrinsic]] + Enabled: Optional[Union[bool, SamIntrinsic]] + Hooks: Optional[FunctionDeploymentPreferenceHooks] + PassthroughCondition: Optional[Union[bool, SamIntrinsic]] + Role: Optional[Union[str, SamIntrinsic]] + TriggerConfigurations: Optional[PassThrough] + Type: Optional[ + Union[str, SamIntrinsic] + ] # TODO: Should investigate whether this is a required field. This is a required field on documentation. However, we don't seem to use this field. + + +class FunctionDeadLetterQueue(BaseModel): + TargetArn: str + Type: Literal["SNS", "SQS"] + + +class FunctionEventInvokeConfig(BaseModel): + DestinationConfig: Optional[PassThrough] + MaximumEventAgeInSeconds: Optional[int] + MaximumRetryAttempts: Optional[int] + + +class FunctionEvent(BaseModel): + Properties: Any + Type: str + + +class FunctionUrlConfig(BaseModel): + AuthType: Union[str, SamIntrinsic] + Cors: Optional[PassThrough] + + class FunctionProperties(BaseModel): - Architectures: Unknown - AssumeRolePolicyDocument: Unknown - AutoPublishAlias: Unknown - AutoPublishCodeSha256: Unknown - CodeSigningConfigArn: Unknown - CodeUri: Unknown - DeadLetterQueue: Unknown - DeploymentPreference: Unknown - Description: Unknown - Environment: Unknown - EphemeralStorage: Unknown - EventInvokeConfig: Unknown - Events: Unknown - FileSystemConfigs: Unknown - FunctionName: Unknown - FunctionUrlConfig: Unknown - Handler: Unknown - ImageConfig: Unknown - ImageUri: Unknown - InlineCode: Unknown - KmsKeyArn: Unknown - Layers: Unknown - MemorySize: Unknown - PackageType: Unknown - PermissionsBoundary: Unknown - Policies: Unknown - ProvisionedConcurrencyConfig: Unknown - ReservedConcurrentExecutions: Unknown - Role: Unknown - Runtime: Unknown - Tags: Unknown - Timeout: Unknown - Tracing: Unknown - VersionDescription: Unknown - VpcConfig: Unknown + Architectures: Optional[PassThrough] + AssumeRolePolicyDocument: Optional[Dict[str, Any]] + AutoPublishAlias: Optional[Union[str, SamIntrinsic]] + AutoPublishCodeSha256: Optional[Union[str, SamIntrinsic]] + CodeSigningConfigArn: Optional[Union[str, SamIntrinsic]] + CodeUri: Optional[Union[str, FunctionCodeUri]] + DeadLetterQueue: Optional[Union[SamIntrinsic, FunctionDeadLetterQueue]] + DeploymentPreference: Optional[FunctionDeploymentPreference] + Description: Optional[PassThrough] + Environment: Optional[PassThrough] + EphemeralStorage: Optional[PassThrough] + EventInvokeConfig: Optional[FunctionEventInvokeConfig] + Events: Optional[Dict[str, FunctionEvent]] + FileSystemConfigs: Optional[PassThrough] + FunctionName: Optional[PassThrough] + FunctionUrlConfig: Optional[FunctionUrlConfig] + Handler: Optional[PassThrough] + ImageConfig: Optional[PassThrough] + ImageUri: Optional[PassThrough] + InlineCode: Optional[PassThrough] + KmsKeyArn: Optional[PassThrough] + Layers: Optional[PassThrough] + MemorySize: Optional[PassThrough] + PackageType: Optional[PassThrough] + PermissionsBoundary: Optional[PassThrough] + Policies: Optional[Union[str, List[Union[str, SamIntrinsic]], SamIntrinsic]] + ProvisionedConcurrencyConfig: Optional[PassThrough] + ReservedConcurrentExecutions: Optional[PassThrough] + Role: Optional[Union[str, SamIntrinsic]] + Runtime: Optional[PassThrough] + Tags: Optional[Dict[str, Any]] + Timeout: Optional[PassThrough] + Tracing: Optional[Union[str, SamIntrinsic]] + VersionDescription: Optional[PassThrough] + VpcConfig: Optional[PassThrough] class AwsServerlessFunction(BaseModel): diff --git a/tests/translator/input/api_with_method_aws_iam_auth.yaml b/tests/translator/input/api_with_method_aws_iam_auth.yaml index dd2d10f5fc..eac22ae7e7 100644 --- a/tests/translator/input/api_with_method_aws_iam_auth.yaml +++ b/tests/translator/input/api_with_method_aws_iam_auth.yaml @@ -27,7 +27,7 @@ Resources: Method: post Auth: Authorizer: AWS_IAM - InvokeRole: rn:aws:iam::123:role/AUTH_AWS_IAM + InvokeRole: !Sub arn:${AWS::Partition}:iam::123:role/AUTH_AWS_IAM MyApiWithAwsIamAuthAndDefaultInvokeRole: Type: Api Properties: @@ -45,21 +45,21 @@ Resources: Method: any Auth: Authorizer: AWS_IAM - MyApiWithAwsIamAuthAndCustomInvokeRoleAnyMethod: - Type: Api - Properties: - RestApiId: !Ref MyApiWithoutAuth - Path: /any/two - Method: any - Auth: - Authorizer: AWS_IAM - InvokeRole: rn:aws:iam::123:role/AUTH_AWS_IAM - MyApiWithAwsIamAuthAndDefaultInvokeRoleAnyMethod: - Type: Api - Properties: - RestApiId: !Ref MyApiWithoutAuth - Path: /any/three - Method: any - Auth: - Authorizer: AWS_IAM - InvokeRole: CALLER_CREDENTIALS + MyApiWithAwsIamAuthAndCustomInvokeRoleAnyMethod: + Type: Api + Properties: + RestApiId: !Ref MyApiWithoutAuth + Path: /any/two + Method: any + Auth: + Authorizer: AWS_IAM + InvokeRole: !Sub arn:${AWS::Partition}:iam::123:role/AUTH_AWS_IAM + MyApiWithAwsIamAuthAndDefaultInvokeRoleAnyMethod: + Type: Api + Properties: + RestApiId: !Ref MyApiWithoutAuth + Path: /any/three + Method: any + Auth: + Authorizer: AWS_IAM + InvokeRole: CALLER_CREDENTIALS diff --git a/tests/translator/input/eventbridgerule_with_retry_policy.yaml b/tests/translator/input/eventbridgerule_with_retry_policy.yaml index f76f96dad1..9bee6265c2 100644 --- a/tests/translator/input/eventbridgerule_with_retry_policy.yaml +++ b/tests/translator/input/eventbridgerule_with_retry_policy.yaml @@ -10,8 +10,8 @@ Resources: Type: Schedule Properties: Schedule: rate(1 minute) - RetryPolicy: - MaximumRetryAttempts: 3 + RetryPolicy: + MaximumRetryAttempts: 3 TriggeredFunction: Type: AWS::Serverless::Function Properties: diff --git a/tests/translator/input/function_with_disabled_traffic_hook.yaml b/tests/translator/input/function_with_disabled_traffic_hook.yaml index 7977ff8772..d8efbc4b45 100644 --- a/tests/translator/input/function_with_disabled_traffic_hook.yaml +++ b/tests/translator/input/function_with_disabled_traffic_hook.yaml @@ -21,12 +21,12 @@ Resources: Hooks: PreTraffic: Ref: preTrafficHook - Events: - Api: - Type: Api - Properties: - Path: /test - Method: get + Events: + Api: + Type: Api + Properties: + Path: /test + Method: get preTrafficHook: Type: AWS::Serverless::Function diff --git a/tests/translator/output/api_with_method_aws_iam_auth.json b/tests/translator/output/api_with_method_aws_iam_auth.json index 482ee003d6..b563ceddc9 100644 --- a/tests/translator/output/api_with_method_aws_iam_auth.json +++ b/tests/translator/output/api_with_method_aws_iam_auth.json @@ -35,7 +35,9 @@ } ], "x-amazon-apigateway-integration": { - "credentials": "rn:aws:iam::123:role/AUTH_AWS_IAM", + "credentials": { + "Fn::Sub": "arn:${AWS::Partition}:iam::123:role/AUTH_AWS_IAM" + }, "httpMethod": "POST", "type": "aws_proxy", "uri": { @@ -77,6 +79,44 @@ } } } + }, + "/any/three": { + "x-amazon-apigateway-any-method": { + "responses": {}, + "security": [ + { + "AWS_IAM": [] + } + ], + "x-amazon-apigateway-integration": { + "credentials": "arn:aws:iam::*:user/*", + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyFunctionWithAwsIamAuth.Arn}/invocations" + } + } + } + }, + "/any/two": { + "x-amazon-apigateway-any-method": { + "responses": {}, + "security": [ + { + "AWS_IAM": [] + } + ], + "x-amazon-apigateway-integration": { + "credentials": { + "Fn::Sub": "arn:${AWS::Partition}:iam::123:role/AUTH_AWS_IAM" + }, + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyFunctionWithAwsIamAuth.Arn}/invocations" + } + } + } } }, "securityDefinitions": { @@ -92,9 +132,9 @@ }, "Type": "AWS::ApiGateway::RestApi" }, - "MyApiWithoutAuthDeployment917ecd4b70": { + "MyApiWithoutAuthDeploymente734a8a2b3": { "Properties": { - "Description": "RestApi deployment id: 917ecd4b7051b27ff6f3806a8cbfd2d2e8972dee", + "Description": "RestApi deployment id: e734a8a2b3a3909004d0c27ef3f4ba7dbf5964d6", "RestApiId": { "Ref": "MyApiWithoutAuth" }, @@ -105,7 +145,7 @@ "MyApiWithoutAuthProdStage": { "Properties": { "DeploymentId": { - "Ref": "MyApiWithoutAuthDeployment917ecd4b70" + "Ref": "MyApiWithoutAuthDeploymente734a8a2b3" }, "RestApiId": { "Ref": "MyApiWithoutAuth" @@ -137,6 +177,27 @@ }, "Type": "AWS::Lambda::Function" }, + "MyFunctionWithAwsIamAuthMyApiWithAwsIamAuthAndCustomInvokeRoleAnyMethodPermissionProd": { + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "MyFunctionWithAwsIamAuth" + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/*/any/two", + { + "__ApiId__": { + "Ref": "MyApiWithoutAuth" + }, + "__Stage__": "*" + } + ] + } + }, + "Type": "AWS::Lambda::Permission" + }, "MyFunctionWithAwsIamAuthMyApiWithAwsIamAuthAndCustomInvokeRolePermissionProd": { "Properties": { "Action": "lambda:InvokeFunction", @@ -158,6 +219,27 @@ }, "Type": "AWS::Lambda::Permission" }, + "MyFunctionWithAwsIamAuthMyApiWithAwsIamAuthAndDefaultInvokeRoleAnyMethodPermissionProd": { + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "MyFunctionWithAwsIamAuth" + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/*/any/three", + { + "__ApiId__": { + "Ref": "MyApiWithoutAuth" + }, + "__Stage__": "*" + } + ] + } + }, + "Type": "AWS::Lambda::Permission" + }, "MyFunctionWithAwsIamAuthMyApiWithAwsIamAuthAndDefaultInvokeRolePermissionProd": { "Properties": { "Action": "lambda:InvokeFunction", diff --git a/tests/translator/output/aws-cn/api_with_method_aws_iam_auth.json b/tests/translator/output/aws-cn/api_with_method_aws_iam_auth.json index 0b0babc403..08c33c2cf9 100644 --- a/tests/translator/output/aws-cn/api_with_method_aws_iam_auth.json +++ b/tests/translator/output/aws-cn/api_with_method_aws_iam_auth.json @@ -35,7 +35,9 @@ } ], "x-amazon-apigateway-integration": { - "credentials": "rn:aws:iam::123:role/AUTH_AWS_IAM", + "credentials": { + "Fn::Sub": "arn:${AWS::Partition}:iam::123:role/AUTH_AWS_IAM" + }, "httpMethod": "POST", "type": "aws_proxy", "uri": { @@ -77,6 +79,44 @@ } } } + }, + "/any/three": { + "x-amazon-apigateway-any-method": { + "responses": {}, + "security": [ + { + "AWS_IAM": [] + } + ], + "x-amazon-apigateway-integration": { + "credentials": "arn:aws:iam::*:user/*", + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws-cn:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyFunctionWithAwsIamAuth.Arn}/invocations" + } + } + } + }, + "/any/two": { + "x-amazon-apigateway-any-method": { + "responses": {}, + "security": [ + { + "AWS_IAM": [] + } + ], + "x-amazon-apigateway-integration": { + "credentials": { + "Fn::Sub": "arn:${AWS::Partition}:iam::123:role/AUTH_AWS_IAM" + }, + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws-cn:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyFunctionWithAwsIamAuth.Arn}/invocations" + } + } + } } }, "securityDefinitions": { @@ -100,9 +140,9 @@ }, "Type": "AWS::ApiGateway::RestApi" }, - "MyApiWithoutAuthDeployment467c912da1": { + "MyApiWithoutAuthDeployment3de35e9b3b": { "Properties": { - "Description": "RestApi deployment id: 467c912da1971538d628768c65d8008b454fdf27", + "Description": "RestApi deployment id: 3de35e9b3bf45c40811c36bd46b8e8513409c050", "RestApiId": { "Ref": "MyApiWithoutAuth" }, @@ -113,7 +153,7 @@ "MyApiWithoutAuthProdStage": { "Properties": { "DeploymentId": { - "Ref": "MyApiWithoutAuthDeployment467c912da1" + "Ref": "MyApiWithoutAuthDeployment3de35e9b3b" }, "RestApiId": { "Ref": "MyApiWithoutAuth" @@ -145,6 +185,27 @@ }, "Type": "AWS::Lambda::Function" }, + "MyFunctionWithAwsIamAuthMyApiWithAwsIamAuthAndCustomInvokeRoleAnyMethodPermissionProd": { + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "MyFunctionWithAwsIamAuth" + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:aws-cn:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/*/any/two", + { + "__ApiId__": { + "Ref": "MyApiWithoutAuth" + }, + "__Stage__": "*" + } + ] + } + }, + "Type": "AWS::Lambda::Permission" + }, "MyFunctionWithAwsIamAuthMyApiWithAwsIamAuthAndCustomInvokeRolePermissionProd": { "Properties": { "Action": "lambda:InvokeFunction", @@ -166,6 +227,27 @@ }, "Type": "AWS::Lambda::Permission" }, + "MyFunctionWithAwsIamAuthMyApiWithAwsIamAuthAndDefaultInvokeRoleAnyMethodPermissionProd": { + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "MyFunctionWithAwsIamAuth" + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:aws-cn:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/*/any/three", + { + "__ApiId__": { + "Ref": "MyApiWithoutAuth" + }, + "__Stage__": "*" + } + ] + } + }, + "Type": "AWS::Lambda::Permission" + }, "MyFunctionWithAwsIamAuthMyApiWithAwsIamAuthAndDefaultInvokeRolePermissionProd": { "Properties": { "Action": "lambda:InvokeFunction", diff --git a/tests/translator/output/aws-cn/eventbridgerule_with_retry_policy.json b/tests/translator/output/aws-cn/eventbridgerule_with_retry_policy.json index 9b8c5924e2..5099c56ed6 100644 --- a/tests/translator/output/aws-cn/eventbridgerule_with_retry_policy.json +++ b/tests/translator/output/aws-cn/eventbridgerule_with_retry_policy.json @@ -65,7 +65,10 @@ "Arn" ] }, - "Id": "ScheduledFunctionScheduleLambdaTarget" + "Id": "ScheduledFunctionScheduleLambdaTarget", + "RetryPolicy": { + "MaximumRetryAttempts": 3 + } } ] }, diff --git a/tests/translator/output/aws-cn/function_with_disabled_traffic_hook.json b/tests/translator/output/aws-cn/function_with_disabled_traffic_hook.json index 58326e9d1a..41d2f93d7a 100644 --- a/tests/translator/output/aws-cn/function_with_disabled_traffic_hook.json +++ b/tests/translator/output/aws-cn/function_with_disabled_traffic_hook.json @@ -50,6 +50,27 @@ } } }, + "FunctionApiPermissionProd": { + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "FunctionAliaslive" + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:aws-cn:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/test", + { + "__ApiId__": { + "Ref": "ServerlessRestApi" + }, + "__Stage__": "*" + } + ] + } + }, + "Type": "AWS::Lambda::Permission" + }, "FunctionDeploymentGroup": { "Properties": { "ApplicationName": { @@ -96,6 +117,64 @@ }, "Type": "AWS::CodeDeploy::Application" }, + "ServerlessRestApi": { + "Properties": { + "Body": { + "info": { + "title": { + "Ref": "AWS::StackName" + }, + "version": "1.0" + }, + "paths": { + "/test": { + "get": { + "responses": {}, + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws-cn:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${FunctionAliaslive}/invocations" + } + } + } + } + }, + "swagger": "2.0" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + }, + "Type": "AWS::ApiGateway::RestApi" + }, + "ServerlessRestApiDeploymente37a6dc25c": { + "Properties": { + "Description": "RestApi deployment id: e37a6dc25c3196733b0aa6c46749485fab444ab1", + "RestApiId": { + "Ref": "ServerlessRestApi" + }, + "StageName": "Stage" + }, + "Type": "AWS::ApiGateway::Deployment" + }, + "ServerlessRestApiProdStage": { + "Properties": { + "DeploymentId": { + "Ref": "ServerlessRestApiDeploymente37a6dc25c" + }, + "RestApiId": { + "Ref": "ServerlessRestApi" + }, + "StageName": "Prod" + }, + "Type": "AWS::ApiGateway::Stage" + }, "preTrafficHook": { "Properties": { "Code": { diff --git a/tests/translator/output/aws-us-gov/api_with_method_aws_iam_auth.json b/tests/translator/output/aws-us-gov/api_with_method_aws_iam_auth.json index 2ae607d45c..e299710781 100644 --- a/tests/translator/output/aws-us-gov/api_with_method_aws_iam_auth.json +++ b/tests/translator/output/aws-us-gov/api_with_method_aws_iam_auth.json @@ -35,7 +35,9 @@ } ], "x-amazon-apigateway-integration": { - "credentials": "rn:aws:iam::123:role/AUTH_AWS_IAM", + "credentials": { + "Fn::Sub": "arn:${AWS::Partition}:iam::123:role/AUTH_AWS_IAM" + }, "httpMethod": "POST", "type": "aws_proxy", "uri": { @@ -77,6 +79,44 @@ } } } + }, + "/any/three": { + "x-amazon-apigateway-any-method": { + "responses": {}, + "security": [ + { + "AWS_IAM": [] + } + ], + "x-amazon-apigateway-integration": { + "credentials": "arn:aws:iam::*:user/*", + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws-us-gov:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyFunctionWithAwsIamAuth.Arn}/invocations" + } + } + } + }, + "/any/two": { + "x-amazon-apigateway-any-method": { + "responses": {}, + "security": [ + { + "AWS_IAM": [] + } + ], + "x-amazon-apigateway-integration": { + "credentials": { + "Fn::Sub": "arn:${AWS::Partition}:iam::123:role/AUTH_AWS_IAM" + }, + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws-us-gov:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyFunctionWithAwsIamAuth.Arn}/invocations" + } + } + } } }, "securityDefinitions": { @@ -100,9 +140,9 @@ }, "Type": "AWS::ApiGateway::RestApi" }, - "MyApiWithoutAuthDeployment60e94c7d4c": { + "MyApiWithoutAuthDeployment54f5d55d46": { "Properties": { - "Description": "RestApi deployment id: 60e94c7d4c7027bdd55b188a3e78764ec1fe52da", + "Description": "RestApi deployment id: 54f5d55d468ea3230714ba75e1dbe2dda41795f3", "RestApiId": { "Ref": "MyApiWithoutAuth" }, @@ -113,7 +153,7 @@ "MyApiWithoutAuthProdStage": { "Properties": { "DeploymentId": { - "Ref": "MyApiWithoutAuthDeployment60e94c7d4c" + "Ref": "MyApiWithoutAuthDeployment54f5d55d46" }, "RestApiId": { "Ref": "MyApiWithoutAuth" @@ -145,6 +185,27 @@ }, "Type": "AWS::Lambda::Function" }, + "MyFunctionWithAwsIamAuthMyApiWithAwsIamAuthAndCustomInvokeRoleAnyMethodPermissionProd": { + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "MyFunctionWithAwsIamAuth" + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:aws-us-gov:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/*/any/two", + { + "__ApiId__": { + "Ref": "MyApiWithoutAuth" + }, + "__Stage__": "*" + } + ] + } + }, + "Type": "AWS::Lambda::Permission" + }, "MyFunctionWithAwsIamAuthMyApiWithAwsIamAuthAndCustomInvokeRolePermissionProd": { "Properties": { "Action": "lambda:InvokeFunction", @@ -166,6 +227,27 @@ }, "Type": "AWS::Lambda::Permission" }, + "MyFunctionWithAwsIamAuthMyApiWithAwsIamAuthAndDefaultInvokeRoleAnyMethodPermissionProd": { + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "MyFunctionWithAwsIamAuth" + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:aws-us-gov:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/*/any/three", + { + "__ApiId__": { + "Ref": "MyApiWithoutAuth" + }, + "__Stage__": "*" + } + ] + } + }, + "Type": "AWS::Lambda::Permission" + }, "MyFunctionWithAwsIamAuthMyApiWithAwsIamAuthAndDefaultInvokeRolePermissionProd": { "Properties": { "Action": "lambda:InvokeFunction", diff --git a/tests/translator/output/aws-us-gov/eventbridgerule_with_retry_policy.json b/tests/translator/output/aws-us-gov/eventbridgerule_with_retry_policy.json index f57680f110..bd2baebd16 100644 --- a/tests/translator/output/aws-us-gov/eventbridgerule_with_retry_policy.json +++ b/tests/translator/output/aws-us-gov/eventbridgerule_with_retry_policy.json @@ -65,7 +65,10 @@ "Arn" ] }, - "Id": "ScheduledFunctionScheduleLambdaTarget" + "Id": "ScheduledFunctionScheduleLambdaTarget", + "RetryPolicy": { + "MaximumRetryAttempts": 3 + } } ] }, diff --git a/tests/translator/output/aws-us-gov/function_with_disabled_traffic_hook.json b/tests/translator/output/aws-us-gov/function_with_disabled_traffic_hook.json index 58326e9d1a..f04a8ba961 100644 --- a/tests/translator/output/aws-us-gov/function_with_disabled_traffic_hook.json +++ b/tests/translator/output/aws-us-gov/function_with_disabled_traffic_hook.json @@ -50,6 +50,27 @@ } } }, + "FunctionApiPermissionProd": { + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "FunctionAliaslive" + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:aws-us-gov:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/test", + { + "__ApiId__": { + "Ref": "ServerlessRestApi" + }, + "__Stage__": "*" + } + ] + } + }, + "Type": "AWS::Lambda::Permission" + }, "FunctionDeploymentGroup": { "Properties": { "ApplicationName": { @@ -96,6 +117,64 @@ }, "Type": "AWS::CodeDeploy::Application" }, + "ServerlessRestApi": { + "Properties": { + "Body": { + "info": { + "title": { + "Ref": "AWS::StackName" + }, + "version": "1.0" + }, + "paths": { + "/test": { + "get": { + "responses": {}, + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws-us-gov:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${FunctionAliaslive}/invocations" + } + } + } + } + }, + "swagger": "2.0" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + }, + "Type": "AWS::ApiGateway::RestApi" + }, + "ServerlessRestApiDeployment0cc4766f88": { + "Properties": { + "Description": "RestApi deployment id: 0cc4766f880e230c48f8b0ff59d3a7eff33b11d9", + "RestApiId": { + "Ref": "ServerlessRestApi" + }, + "StageName": "Stage" + }, + "Type": "AWS::ApiGateway::Deployment" + }, + "ServerlessRestApiProdStage": { + "Properties": { + "DeploymentId": { + "Ref": "ServerlessRestApiDeployment0cc4766f88" + }, + "RestApiId": { + "Ref": "ServerlessRestApi" + }, + "StageName": "Prod" + }, + "Type": "AWS::ApiGateway::Stage" + }, "preTrafficHook": { "Properties": { "Code": { diff --git a/tests/translator/output/eventbridgerule_with_retry_policy.json b/tests/translator/output/eventbridgerule_with_retry_policy.json index 3125ae432f..4f1ed0c77a 100644 --- a/tests/translator/output/eventbridgerule_with_retry_policy.json +++ b/tests/translator/output/eventbridgerule_with_retry_policy.json @@ -65,7 +65,10 @@ "Arn" ] }, - "Id": "ScheduledFunctionScheduleLambdaTarget" + "Id": "ScheduledFunctionScheduleLambdaTarget", + "RetryPolicy": { + "MaximumRetryAttempts": 3 + } } ] }, diff --git a/tests/translator/output/function_with_disabled_traffic_hook.json b/tests/translator/output/function_with_disabled_traffic_hook.json index 58326e9d1a..1d9e8f9187 100644 --- a/tests/translator/output/function_with_disabled_traffic_hook.json +++ b/tests/translator/output/function_with_disabled_traffic_hook.json @@ -50,6 +50,27 @@ } } }, + "FunctionApiPermissionProd": { + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "FunctionAliaslive" + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/test", + { + "__ApiId__": { + "Ref": "ServerlessRestApi" + }, + "__Stage__": "*" + } + ] + } + }, + "Type": "AWS::Lambda::Permission" + }, "FunctionDeploymentGroup": { "Properties": { "ApplicationName": { @@ -96,6 +117,56 @@ }, "Type": "AWS::CodeDeploy::Application" }, + "ServerlessRestApi": { + "Properties": { + "Body": { + "info": { + "title": { + "Ref": "AWS::StackName" + }, + "version": "1.0" + }, + "paths": { + "/test": { + "get": { + "responses": {}, + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${FunctionAliaslive}/invocations" + } + } + } + } + }, + "swagger": "2.0" + } + }, + "Type": "AWS::ApiGateway::RestApi" + }, + "ServerlessRestApiDeployment0e07dd5b7f": { + "Properties": { + "Description": "RestApi deployment id: 0e07dd5b7f2251dbc336532c5e3bc7518feead5e", + "RestApiId": { + "Ref": "ServerlessRestApi" + }, + "StageName": "Stage" + }, + "Type": "AWS::ApiGateway::Deployment" + }, + "ServerlessRestApiProdStage": { + "Properties": { + "DeploymentId": { + "Ref": "ServerlessRestApiDeployment0e07dd5b7f" + }, + "RestApiId": { + "Ref": "ServerlessRestApi" + }, + "StageName": "Prod" + }, + "Type": "AWS::ApiGateway::Stage" + }, "preTrafficHook": { "Properties": { "Code": {