diff --git a/docs/globals.rst b/docs/globals.rst index 30c78f3086..6f2dfcffd6 100644 --- a/docs/globals.rst +++ b/docs/globals.rst @@ -67,6 +67,7 @@ Currently, the following resources and properties are being supported: Layers: AutoPublishAlias: DeploymentPreference: + RolePath: PermissionsBoundary: ReservedConcurrentExecutions: EventInvokeConfig: diff --git a/integration/resources/expected/single/function_with_role_path.json b/integration/resources/expected/single/function_with_role_path.json new file mode 100644 index 0000000000..d4dfecb350 --- /dev/null +++ b/integration/resources/expected/single/function_with_role_path.json @@ -0,0 +1,10 @@ +[ + { + "LogicalResourceId": "MyLambdaFunction", + "ResourceType": "AWS::Lambda::Function" + }, + { + "LogicalResourceId": "MyLambdaFunctionRole", + "ResourceType": "AWS::IAM::Role" + } +] diff --git a/integration/resources/templates/single/function_with_role_path.yaml b/integration/resources/templates/single/function_with_role_path.yaml new file mode 100644 index 0000000000..fb55ea9581 --- /dev/null +++ b/integration/resources/templates/single/function_with_role_path.yaml @@ -0,0 +1,10 @@ +Resources: + MyLambdaFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: ${codeuri} + Handler: hello.handler + Runtime: python3.8 + RolePath: /foo/bar/ +Metadata: + SamTransformTest: true diff --git a/integration/single/test_basic_function.py b/integration/single/test_basic_function.py index 9a5afc15b5..d625a40004 100644 --- a/integration/single/test_basic_function.py +++ b/integration/single/test_basic_function.py @@ -43,6 +43,23 @@ def test_basic_function(self, file_name): self.assertEqual(self.get_resource_status_by_logical_id("MyLambdaFunction"), "UPDATE_COMPLETE") + def test_basic_function_with_role_path(self): + self.create_and_verify_stack("single/function_with_role_path") + + lambda_client = self.client_provider.lambda_client + function_name = self.get_physical_id_by_type("AWS::Lambda::Function") + role_name = self.get_physical_id_by_type("AWS::IAM::Role") + response = lambda_client.get_function(FunctionName=function_name) + + role_arn = response.get("Configuration", {}).get("Role") + self.assertIsNotNone(role_arn) + self.assertIn("/foo/bar/", role_arn) + + iam_client = self.client_provider.iam_client + response = iam_client.get_role(RoleName=role_name) + + self.assertEqual(response["Role"]["Path"], "/foo/bar/") + @parameterized.expand( [ "single/function_with_http_api_events", diff --git a/samtranslator/model/role_utils/role_constructor.py b/samtranslator/model/role_utils/role_constructor.py index 4ecb6347fb..ff92f44a59 100644 --- a/samtranslator/model/role_utils/role_constructor.py +++ b/samtranslator/model/role_utils/role_constructor.py @@ -12,6 +12,7 @@ def construct_role_for_resource( # type: ignore[no-untyped-def] resource_policies, managed_policy_arns=None, policy_documents=None, + role_path=None, permissions_boundary=None, tags=None, ) -> IAMRole: @@ -24,6 +25,7 @@ def construct_role_for_resource( # type: ignore[no-untyped-def] :param resource_policies: ResourcePolicies object encapuslating the policies property of SAM resource :param managed_policy_arns: List of managed policy ARNs to be associated with the role :param policy_documents: List of policy documents to be associated with the role + :param role_path: The path to the role :param permissions_boundary: The ARN of the policy used to set the permissions boundary for the role :param tags: Tags to be associated with the role @@ -103,6 +105,7 @@ def construct_role_for_resource( # type: ignore[no-untyped-def] execution_role.ManagedPolicyArns = list(managed_policy_arns) execution_role.Policies = policy_documents or None + execution_role.Path = role_path execution_role.PermissionsBoundary = permissions_boundary execution_role.Tags = tags diff --git a/samtranslator/model/sam_resources.py b/samtranslator/model/sam_resources.py index fdf20dfae1..d3bd063368 100644 --- a/samtranslator/model/sam_resources.py +++ b/samtranslator/model/sam_resources.py @@ -80,6 +80,7 @@ from samtranslator.model.role_utils import construct_role_for_resource from samtranslator.model.xray_utils import get_xray_managed_policy_name from samtranslator.utils.types import Intrinsicable +from samtranslator.schema.common import PassThrough from samtranslator.validator.value_validator import sam_expect @@ -103,6 +104,7 @@ class SamFunction(SamResourceMacro): "Role": PropertyType(False, is_str()), "AssumeRolePolicyDocument": PropertyType(False, is_type(dict)), "Policies": PropertyType(False, one_of(is_str(), is_type(dict), list_of(one_of(is_str(), is_type(dict))))), + "RolePath": PassThroughProperty(False), "PermissionsBoundary": PropertyType(False, is_str()), "Environment": PropertyType(False, dict_of(is_str(), is_type(dict))), "Events": PropertyType(False, dict_of(is_str(), is_type(dict))), @@ -141,6 +143,7 @@ class SamFunction(SamResourceMacro): Role: Optional[Intrinsicable[str]] AssumeRolePolicyDocument: Optional[Dict[str, Any]] Policies: Optional[List[Any]] + RolePath: Optional[PassThrough] PermissionsBoundary: Optional[Intrinsicable[str]] Environment: Optional[Dict[str, Any]] Events: Optional[Dict[str, Any]] @@ -588,6 +591,7 @@ def _construct_role(self, managed_policy_map, event_invoke_policies): # type: i resource_policies=function_policies, managed_policy_arns=managed_policy_arns, policy_documents=policy_documents, + role_path=self.RolePath, permissions_boundary=self.PermissionsBoundary, tags=self._construct_tag_list(self.Tags), ) diff --git a/samtranslator/plugins/globals/globals.py b/samtranslator/plugins/globals/globals.py index 4a79b8af0d..c447a8c396 100644 --- a/samtranslator/plugins/globals/globals.py +++ b/samtranslator/plugins/globals/globals.py @@ -37,6 +37,7 @@ class Globals(object): "AutoPublishAlias", "Layers", "DeploymentPreference", + "RolePath", "PermissionsBoundary", "ReservedConcurrentExecutions", "ProvisionedConcurrencyConfig", diff --git a/samtranslator/schema/aws_serverless_function.py b/samtranslator/schema/aws_serverless_function.py index 1ec84c7343..8cd3629c77 100644 --- a/samtranslator/schema/aws_serverless_function.py +++ b/samtranslator/schema/aws_serverless_function.py @@ -433,6 +433,7 @@ class ScheduleV2Event(BaseModel): KmsKeyArn = Optional[PassThrough] Layers = Optional[PassThrough] AutoPublishAlias = Optional[SamIntrinsicable[str]] +RolePath = Optional[PassThrough] # TODO: update docs when live PermissionsBoundary = Optional[PassThrough] ReservedConcurrentExecutions = Optional[PassThrough] ProvisionedConcurrencyConfig = Optional[PassThrough] @@ -490,6 +491,7 @@ class Properties(BaseModel): Layers: Optional[Layers] = prop("Layers") MemorySize: Optional[MemorySize] = prop("MemorySize") PackageType: Optional[PassThrough] = prop("PackageType") + RolePath: Optional[RolePath] PermissionsBoundary: Optional[PermissionsBoundary] = prop("PermissionsBoundary") Policies: Optional[SamIntrinsicable[Union[str, List[SamIntrinsicable[str]]]]] = prop("Policies") ProvisionedConcurrencyConfig: Optional[ProvisionedConcurrencyConfig] = prop("ProvisionedConcurrencyConfig") @@ -519,6 +521,7 @@ class Globals(BaseModel): Layers: Optional[Layers] = prop("Layers") AutoPublishAlias: Optional[AutoPublishAlias] = prop("AutoPublishAlias") DeploymentPreference: Optional[DeploymentPreference] = prop("DeploymentPreference") + RolePath: Optional[RolePath] PermissionsBoundary: Optional[PermissionsBoundary] = prop("PermissionsBoundary") ReservedConcurrentExecutions: Optional[ReservedConcurrentExecutions] = prop("ReservedConcurrentExecutions") ProvisionedConcurrencyConfig: Optional[ProvisionedConcurrencyConfig] = prop("ProvisionedConcurrencyConfig") diff --git a/samtranslator/schema/schema.json b/samtranslator/schema/schema.json index 55a29ff815..ccb55f3fdb 100644 --- a/samtranslator/schema/schema.json +++ b/samtranslator/schema/schema.json @@ -486,6 +486,9 @@ } ] }, + "RolePath": { + "title": "Rolepath" + }, "PermissionsBoundary": { "title": "PermissionsBoundary", "description": "The ARN of a permissions boundary to use for this function's execution role\\. This property works only if the role is generated for you\\. \n*Type*: String \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the [`PermissionsBoundary`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html#cfn-iam-role-permissionsboundary) property of an `AWS::IAM::Role` resource\\.", @@ -3907,6 +3910,9 @@ "description": "The deployment package type of the Lambda function\\. For more information, see [Lambda deployment packages](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-package.html) in the *AWS Lambda Developer Guide*\\. \n**Notes**: \n1\\. If this property is set to `Zip` \\(default\\), then either `CodeUri` or `InlineCode` applies, and `ImageUri` is ignored\\. \n2\\. If this property is set to `Image`, then only `ImageUri` applies, and both `CodeUri` and `InlineCode` are ignored\\. The Amazon ECR repository required to store the functionsl container image can be auto created by the AWS SAM CLI\\. For more information, see [sam deploy](sam-cli-command-reference-sam-deploy.md)\\. \n*Valid values*: `Zip` or `Image` \n*Type*: String \n*Required*: No \n*Default*: `Zip` \n*AWS CloudFormation compatibility*: This property is passed directly to the [`PackageType`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html#cfn-lambda-function-packagetype) property of an `AWS::Lambda::Function` resource\\.", "markdownDescription": "The deployment package type of the Lambda function\\. For more information, see [Lambda deployment packages](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-package.html) in the *AWS Lambda Developer Guide*\\. \n**Notes**: \n1\\. If this property is set to `Zip` \\(default\\), then either `CodeUri` or `InlineCode` applies, and `ImageUri` is ignored\\. \n2\\. If this property is set to `Image`, then only `ImageUri` applies, and both `CodeUri` and `InlineCode` are ignored\\. The Amazon ECR repository required to store the functionsl container image can be auto created by the AWS SAM CLI\\. For more information, see [sam deploy](sam-cli-command-reference-sam-deploy.md)\\. \n*Valid values*: `Zip` or `Image` \n*Type*: String \n*Required*: No \n*Default*: `Zip` \n*AWS CloudFormation compatibility*: This property is passed directly to the [`PackageType`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html#cfn-lambda-function-packagetype) property of an `AWS::Lambda::Function` resource\\." }, + "RolePath": { + "title": "Rolepath" + }, "PermissionsBoundary": { "title": "PermissionsBoundary", "description": "The ARN of a permissions boundary to use for this function's execution role\\. This property works only if the role is generated for you\\. \n*Type*: String \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the [`PermissionsBoundary`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html#cfn-iam-role-permissionsboundary) property of an `AWS::IAM::Role` resource\\.", diff --git a/tests/translator/input/function_with_globals_role_path.yaml b/tests/translator/input/function_with_globals_role_path.yaml new file mode 100644 index 0000000000..2f5cd975c4 --- /dev/null +++ b/tests/translator/input/function_with_globals_role_path.yaml @@ -0,0 +1,20 @@ +Globals: + Function: + RolePath: /foo/bar + +Resources: + Function1: + Type: AWS::Serverless::Function + Properties: + CodeUri: s3://sam-demo-bucket/hello.zip + Handler: hello.handler + Runtime: python2.7 + RolePath: /foo/bar + + Function2: + Type: AWS::Serverless::Function + Properties: + CodeUri: s3://sam-demo-bucket/hello.zip + Handler: hello.world + Runtime: python3.7 + RolePath: /foo/bar diff --git a/tests/translator/input/function_with_role_and_role_path.yaml b/tests/translator/input/function_with_role_and_role_path.yaml new file mode 100644 index 0000000000..55127a4b53 --- /dev/null +++ b/tests/translator/input/function_with_role_and_role_path.yaml @@ -0,0 +1,21 @@ +Resources: + MyFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: s3://sam-demo-bucket/hello.zip + Handler: hello.handler + Runtime: python2.7 + Role: !Ref MyRole + RolePath: /foo/bar + + MyRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Effect: Allow + Action: sts:AssumeRole + Principal: + Service: lambda.amazonaws.com + ManagedPolicyArns: + - arn:{AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole diff --git a/tests/translator/input/function_with_role_path.yaml b/tests/translator/input/function_with_role_path.yaml new file mode 100644 index 0000000000..d0a426b31a --- /dev/null +++ b/tests/translator/input/function_with_role_path.yaml @@ -0,0 +1,8 @@ +Resources: + MinimalFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: s3://sam-demo-bucket/hello.zip + Handler: hello.handler + Runtime: python2.7 + RolePath: /foo/bar diff --git a/tests/translator/output/aws-cn/function_with_globals_role_path.json b/tests/translator/output/aws-cn/function_with_globals_role_path.json new file mode 100644 index 0000000000..4ec77a4a4c --- /dev/null +++ b/tests/translator/output/aws-cn/function_with_globals_role_path.json @@ -0,0 +1,112 @@ +{ + "Resources": { + "Function1": { + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip" + }, + "Handler": "hello.handler", + "Role": { + "Fn::GetAtt": [ + "Function1Role", + "Arn" + ] + }, + "Runtime": "python2.7", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "Function1Role": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Path": "/foo/bar", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "Function2": { + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip" + }, + "Handler": "hello.world", + "Role": { + "Fn::GetAtt": [ + "Function2Role", + "Arn" + ] + }, + "Runtime": "python3.7", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "Function2Role": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Path": "/foo/bar", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/aws-cn/function_with_role_and_role_path.json b/tests/translator/output/aws-cn/function_with_role_and_role_path.json new file mode 100644 index 0000000000..131d254f03 --- /dev/null +++ b/tests/translator/output/aws-cn/function_with_role_and_role_path.json @@ -0,0 +1,43 @@ +{ + "Resources": { + "MyFunction": { + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip" + }, + "Handler": "hello.handler", + "Role": { + "Ref": "MyRole" + }, + "Runtime": "python2.7", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "MyRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:{AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/aws-cn/function_with_role_path.json b/tests/translator/output/aws-cn/function_with_role_path.json new file mode 100644 index 0000000000..5422b825f4 --- /dev/null +++ b/tests/translator/output/aws-cn/function_with_role_path.json @@ -0,0 +1,58 @@ +{ + "Resources": { + "MinimalFunction": { + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip" + }, + "Handler": "hello.handler", + "Role": { + "Fn::GetAtt": [ + "MinimalFunctionRole", + "Arn" + ] + }, + "Runtime": "python2.7", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "MinimalFunctionRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Path": "/foo/bar", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/aws-us-gov/function_with_globals_role_path.json b/tests/translator/output/aws-us-gov/function_with_globals_role_path.json new file mode 100644 index 0000000000..0b14bfaba2 --- /dev/null +++ b/tests/translator/output/aws-us-gov/function_with_globals_role_path.json @@ -0,0 +1,112 @@ +{ + "Resources": { + "Function1": { + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip" + }, + "Handler": "hello.handler", + "Role": { + "Fn::GetAtt": [ + "Function1Role", + "Arn" + ] + }, + "Runtime": "python2.7", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "Function1Role": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Path": "/foo/bar", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "Function2": { + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip" + }, + "Handler": "hello.world", + "Role": { + "Fn::GetAtt": [ + "Function2Role", + "Arn" + ] + }, + "Runtime": "python3.7", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "Function2Role": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Path": "/foo/bar", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/aws-us-gov/function_with_role_and_role_path.json b/tests/translator/output/aws-us-gov/function_with_role_and_role_path.json new file mode 100644 index 0000000000..131d254f03 --- /dev/null +++ b/tests/translator/output/aws-us-gov/function_with_role_and_role_path.json @@ -0,0 +1,43 @@ +{ + "Resources": { + "MyFunction": { + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip" + }, + "Handler": "hello.handler", + "Role": { + "Ref": "MyRole" + }, + "Runtime": "python2.7", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "MyRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:{AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/aws-us-gov/function_with_role_path.json b/tests/translator/output/aws-us-gov/function_with_role_path.json new file mode 100644 index 0000000000..a57151ee54 --- /dev/null +++ b/tests/translator/output/aws-us-gov/function_with_role_path.json @@ -0,0 +1,58 @@ +{ + "Resources": { + "MinimalFunction": { + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip" + }, + "Handler": "hello.handler", + "Role": { + "Fn::GetAtt": [ + "MinimalFunctionRole", + "Arn" + ] + }, + "Runtime": "python2.7", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "MinimalFunctionRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Path": "/foo/bar", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/error_globals_unsupported_property.json b/tests/translator/output/error_globals_unsupported_property.json index cf17dda1b5..60cdd3e0ef 100644 --- a/tests/translator/output/error_globals_unsupported_property.json +++ b/tests/translator/output/error_globals_unsupported_property.json @@ -1,8 +1,8 @@ { - "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. 'Globals' section is invalid. 'SomeKey' is not a supported property of 'Function'. Must be one of the following values - ['Handler', 'Runtime', 'CodeUri', 'DeadLetterQueue', 'Description', 'MemorySize', 'Timeout', 'VpcConfig', 'Environment', 'Tags', 'Tracing', 'KmsKeyArn', 'AutoPublishAlias', 'Layers', 'DeploymentPreference', 'PermissionsBoundary', 'ReservedConcurrentExecutions', 'ProvisionedConcurrencyConfig', 'AssumeRolePolicyDocument', 'EventInvokeConfig', 'FileSystemConfigs', 'CodeSigningConfigArn', 'Architectures', 'EphemeralStorage', 'FunctionUrlConfig']", + "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. 'Globals' section is invalid. 'SomeKey' is not a supported property of 'Function'. Must be one of the following values - ['Handler', 'Runtime', 'CodeUri', 'DeadLetterQueue', 'Description', 'MemorySize', 'Timeout', 'VpcConfig', 'Environment', 'Tags', 'Tracing', 'KmsKeyArn', 'AutoPublishAlias', 'Layers', 'DeploymentPreference', 'RolePath', 'PermissionsBoundary', 'ReservedConcurrentExecutions', 'ProvisionedConcurrencyConfig', 'AssumeRolePolicyDocument', 'EventInvokeConfig', 'FileSystemConfigs', 'CodeSigningConfigArn', 'Architectures', 'EphemeralStorage', 'FunctionUrlConfig']", "errors": [ { - "errorMessage": "'Globals' section is invalid. 'SomeKey' is not a supported property of 'Function'. Must be one of the following values - ['Handler', 'Runtime', 'CodeUri', 'DeadLetterQueue', 'Description', 'MemorySize', 'Timeout', 'VpcConfig', 'Environment', 'Tags', 'Tracing', 'KmsKeyArn', 'AutoPublishAlias', 'Layers', 'DeploymentPreference', 'PermissionsBoundary', 'ReservedConcurrentExecutions', 'ProvisionedConcurrencyConfig', 'EventInvokeConfig', 'FileSystemConfigs', 'CodeSigningConfigArn', 'Architectures', 'FunctionUrlConfig']" + "errorMessage": "'Globals' section is invalid. 'SomeKey' is not a supported property of 'Function'. Must be one of the following values - ['Handler', 'Runtime', 'CodeUri', 'DeadLetterQueue', 'Description', 'MemorySize', 'Timeout', 'VpcConfig', 'Environment', 'Tags', 'Tracing', 'KmsKeyArn', 'AutoPublishAlias', 'Layers', 'DeploymentPreference', 'RolePath', 'PermissionsBoundary', 'ReservedConcurrentExecutions', 'ProvisionedConcurrencyConfig', 'EventInvokeConfig', 'FileSystemConfigs', 'CodeSigningConfigArn', 'Architectures', 'FunctionUrlConfig']" } ] } diff --git a/tests/translator/output/function_with_globals_role_path.json b/tests/translator/output/function_with_globals_role_path.json new file mode 100644 index 0000000000..4d2137efdd --- /dev/null +++ b/tests/translator/output/function_with_globals_role_path.json @@ -0,0 +1,112 @@ +{ + "Resources": { + "Function1": { + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip" + }, + "Handler": "hello.handler", + "Role": { + "Fn::GetAtt": [ + "Function1Role", + "Arn" + ] + }, + "Runtime": "python2.7", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "Function1Role": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Path": "/foo/bar", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "Function2": { + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip" + }, + "Handler": "hello.world", + "Role": { + "Fn::GetAtt": [ + "Function2Role", + "Arn" + ] + }, + "Runtime": "python3.7", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "Function2Role": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Path": "/foo/bar", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/function_with_role_and_role_path.json b/tests/translator/output/function_with_role_and_role_path.json new file mode 100644 index 0000000000..131d254f03 --- /dev/null +++ b/tests/translator/output/function_with_role_and_role_path.json @@ -0,0 +1,43 @@ +{ + "Resources": { + "MyFunction": { + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip" + }, + "Handler": "hello.handler", + "Role": { + "Ref": "MyRole" + }, + "Runtime": "python2.7", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "MyRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:{AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/function_with_role_path.json b/tests/translator/output/function_with_role_path.json new file mode 100644 index 0000000000..e18996d7aa --- /dev/null +++ b/tests/translator/output/function_with_role_path.json @@ -0,0 +1,58 @@ +{ + "Resources": { + "MinimalFunction": { + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip" + }, + "Handler": "hello.handler", + "Role": { + "Fn::GetAtt": [ + "MinimalFunctionRole", + "Arn" + ] + }, + "Runtime": "python2.7", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "MinimalFunctionRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Path": "/foo/bar", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +}