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
2 changes: 2 additions & 0 deletions samtranslator/model/sam_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -1120,6 +1120,7 @@ class SamStateMachine(SamResourceMacro):
"Tags": PropertyType(False, is_type(dict)),
"Policies": PropertyType(False, one_of(is_str(), list_of(one_of(is_str(), is_type(dict), is_type(dict))))),
"Tracing": PropertyType(False, is_type(dict)),
"PermissionsBoundary": PropertyType(False, is_str()),
}
event_resolver = ResourceTypeResolver(
samtranslator.model.stepfunctions.events,
Expand All @@ -1140,6 +1141,7 @@ def to_cloudformation(self, **kwargs):
logging=self.Logging,
name=self.Name,
policies=self.Policies,
permissions_boundary=self.PermissionsBoundary,
definition_substitutions=self.DefinitionSubstitutions,
role=self.Role,
state_machine_type=self.Type,
Expand Down
23 changes: 16 additions & 7 deletions samtranslator/model/stepfunctions/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,12 @@ def _generate_logical_id(self, prefix, suffix, resource_type):
logical_id = generator.gen()
return logical_id

def _construct_role(self, resource, prefix=None, suffix=""):
def _construct_role(self, resource, permissions_boundary=None, prefix=None, suffix=""):
"""Constructs the IAM Role resource allowing the event service to invoke
the StartExecution API of the state machine resource it is associated with.

:param model.stepfunctions.StepFunctionsStateMachine resource: The state machine resource associated with the event
:param string permissions_boundary: The ARN of the policy used to set the permissions boundary for the role
:param string prefix: Prefix to use for the logical ID of the IAM role
:param string suffix: Suffix to add for the logical ID of the IAM role

Expand All @@ -63,6 +64,9 @@ def _construct_role(self, resource, prefix=None, suffix=""):
IAMRolePolicies.step_functions_start_execution_role_policy(state_machine_arn, role_logical_id)
]

if permissions_boundary:
event_role.PermissionsBoundary = permissions_boundary

return event_role


Expand All @@ -88,6 +92,8 @@ def to_cloudformation(self, resource, **kwargs):
"""
resources = []

permissions_boundary = kwargs.get("permissions_boundary")

events_rule = EventsRule(self.logical_id)
resources.append(events_rule)

Expand All @@ -99,7 +105,7 @@ def to_cloudformation(self, resource, **kwargs):
if CONDITION in resource.resource_attributes:
events_rule.set_resource_attribute(CONDITION, resource.resource_attributes[CONDITION])

role = self._construct_role(resource)
role = self._construct_role(resource, permissions_boundary)
resources.append(role)
events_rule.Targets = [self._construct_target(resource, role)]

Expand Down Expand Up @@ -144,6 +150,8 @@ def to_cloudformation(self, resource, **kwargs):
"""
resources = []

permissions_boundary = kwargs.get("permissions_boundary")

events_rule = EventsRule(self.logical_id)
events_rule.EventBusName = self.EventBusName
events_rule.EventPattern = self.Pattern
Expand All @@ -152,7 +160,7 @@ def to_cloudformation(self, resource, **kwargs):

resources.append(events_rule)

role = self._construct_role(resource)
role = self._construct_role(resource, permissions_boundary)
resources.append(role)
events_rule.Targets = [self._construct_target(resource, role)]

Expand Down Expand Up @@ -243,9 +251,9 @@ def resources_to_link(self, resources):
return {"explicit_api": explicit_api, "explicit_api_stage": {"suffix": stage_suffix}}

def to_cloudformation(self, resource, **kwargs):
"""If the Api event source has a RestApi property, then simply return the IAM role resource
allowing API Gateway to start the state machine execution. If no RestApi is provided, then
additionally inject the path, method, and the x-amazon-apigateway-integration into the
"""If the Api event source has a RestApi property, then simply return the IAM role resource
allowing API Gateway to start the state machine execution. If no RestApi is provided, then
additionally inject the path, method, and the x-amazon-apigateway-integration into the
Swagger body for a provided implicit API.

:param model.stepfunctions.resources.StepFunctionsStateMachine resource; the state machine \
Expand All @@ -259,12 +267,13 @@ def to_cloudformation(self, resource, **kwargs):
resources = []

intrinsics_resolver = kwargs.get("intrinsics_resolver")
permissions_boundary = kwargs.get("permissions_boundary")

if self.Method is not None:
# Convert to lower case so that user can specify either GET or get
self.Method = self.Method.lower()

role = self._construct_role(resource)
role = self._construct_role(resource, permissions_boundary)
resources.append(role)

explicit_api = kwargs["explicit_api"]
Expand Down
9 changes: 8 additions & 1 deletion samtranslator/model/stepfunctions/generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ def __init__(
logging,
name,
policies,
permissions_boundary,
definition_substitutions,
role,
state_machine_type,
Expand All @@ -60,6 +61,7 @@ def __init__(
:param logging: Logging configuration for the State Machine
:param name: Name of the State Machine resource
:param policies: Policies attached to the execution role
:param permissions_boundary: The ARN of the policy used to set the permissions boundary for the role
:param definition_substitutions: Variable-to-value mappings to be replaced in the State Machine definition
:param role: Role ARN to use for the execution role
:param state_machine_type: Type of the State Machine
Expand All @@ -82,6 +84,7 @@ def __init__(
self.name = name
self.logging = logging
self.policies = policies
self.permissions_boundary = permissions_boundary
self.definition_substitutions = definition_substitutions
self.role = role
self.type = state_machine_type
Expand Down Expand Up @@ -220,6 +223,7 @@ def _construct_role(self):
assume_role_policy_document=IAMRolePolicies.stepfunctions_assume_role_policy(),
resource_policies=state_machine_policies,
tags=self._construct_tag_list(),
permissions_boundary=self.permissions_boundary,
)
return execution_role

Expand All @@ -242,7 +246,10 @@ def _generate_event_resources(self):
resources = []
if self.events:
for logical_id, event_dict in self.events.items():
kwargs = {"intrinsics_resolver": self.intrinsics_resolver}
kwargs = {
"intrinsics_resolver": self.intrinsics_resolver,
"permissions_boundary": self.permissions_boundary,
}
try:
eventsource = self.event_resolver.resolve_resource_type(event_dict).from_dict(
self.state_machine.logical_id + logical_id, event_dict, logical_id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def setUp(self):
"logging": None,
"name": None,
"policies": None,
"permissions_boundary": None,
"definition_substitutions": None,
"role": None,
"state_machine_type": None,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
Resources:
MyFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: s3://sam-demo-bucket/hello.zip
Handler: hello.handler
Runtime: python2.7
ReservedConcurrentExecutions: 100

StateMachine:
Type: AWS::Serverless::StateMachine
Properties:
Name: MyStateMachine
Events:
ScheduleEvent:
Type: Schedule
Properties:
Schedule: "rate(1 minute)"
Name: TestSchedule
CWEvent:
Type: CloudWatchEvent
Properties:
Pattern:
detail:
state:
- terminated
MyApiEvent:
Type: Api
Properties:
Path: /startMyExecution
Method: post
DefinitionUri:
Bucket: sam-demo-bucket
Key: my-state-machine.asl.json
Version: 3
PermissionsBoundary: arn:aws:1234:iam:boundary/CustomerCreatedPermissionsBoundary
Policies:
- LambdaInvokePolicy:
FunctionName: !Ref MyFunction
Loading