Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/globals.rst
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ Currently, the following resources and properties are being supported:
Layers:
AutoPublishAlias:
DeploymentPreference:
RolePath:
PermissionsBoundary:
ReservedConcurrentExecutions:
EventInvokeConfig:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[
{
"LogicalResourceId": "MyLambdaFunction",
"ResourceType": "AWS::Lambda::Function"
},
{
"LogicalResourceId": "MyLambdaFunctionRole",
"ResourceType": "AWS::IAM::Role"
}
]
Original file line number Diff line number Diff line change
@@ -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
17 changes: 17 additions & 0 deletions integration/single/test_basic_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
3 changes: 3 additions & 0 deletions samtranslator/model/role_utils/role_constructor.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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

Expand Down Expand Up @@ -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

Expand Down
4 changes: 4 additions & 0 deletions samtranslator/model/sam_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand All @@ -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))),
Expand Down Expand Up @@ -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]]
Expand Down Expand Up @@ -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),
)
Expand Down
1 change: 1 addition & 0 deletions samtranslator/plugins/globals/globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class Globals(object):
"AutoPublishAlias",
"Layers",
"DeploymentPreference",
"RolePath",
"PermissionsBoundary",
"ReservedConcurrentExecutions",
"ProvisionedConcurrencyConfig",
Expand Down
3 changes: 3 additions & 0 deletions samtranslator/schema/aws_serverless_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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")
Expand Down
6 changes: 6 additions & 0 deletions samtranslator/schema/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -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\\.",
Expand Down Expand Up @@ -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\\.",
Expand Down
20 changes: 20 additions & 0 deletions tests/translator/input/function_with_globals_role_path.yaml
Original file line number Diff line number Diff line change
@@ -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
21 changes: 21 additions & 0 deletions tests/translator/input/function_with_role_and_role_path.yaml
Original file line number Diff line number Diff line change
@@ -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
8 changes: 8 additions & 0 deletions tests/translator/input/function_with_role_path.yaml
Original file line number Diff line number Diff line change
@@ -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
112 changes: 112 additions & 0 deletions tests/translator/output/aws-cn/function_with_globals_role_path.json
Original file line number Diff line number Diff line change
@@ -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"
}
}
}
Original file line number Diff line number Diff line change
@@ -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"
}
}
}
Loading