I have a Step Function (Parent) created in a SAM/CloudFormation template that, among other things, calls another Step Function (Child). I'm following the instructions on calling Child, from Parent, using the service integration pattern. But I'm getting an IAM-related (I think) error I can't resolve when deploying via the CLI. (The error manifests in the CLI output, so it never actually makes it into AWS. There have been plenty of prior deployments, so the changeset is just trying to modify the Step Function with this deployment.)
'arn:aws:iam::{Account-Number}:role/{Parent-Step-Function-Role-Name}' is not authorized to create managed-rule. (Service: AWSStepFunctions; Status Code: 400; Error Code: AccessDeniedException; Request ID: {Long-Id-Number})
To get the synchronous behavior I want (Parent calls Child, waits for execution of Child to complete, then moves onto the next State) I use the suggestion (from the service integration pattern link above) to create a task (in my SAM template) that looks like the following:
...More States...
"Call Child State": {
"Type": "Task",
"Next": "The Next State",
"Resource": "arn:aws:states:::states:startExecution.sync",
"Parameters": {
"Input": {
"comment": "Hello World!"
},
"StateMachineArn": "${ChildStepFunction}",
"Name": "ChildExecutionFromParent"
}
},
...More States...
I've defined the IAM-role for Parent as follows, making sure that it only has Lambda execution privileges for the Lambda functions in Parent, and, more applicably to the problem, has permission to StartExecution of Child. I followed the instructions in the link just below, that stated StartExecution was the only permission needed when using the service integration pattern.
https://docs.aws.amazon.com/step-functions/latest/dg/stepfunctions-iam.html
ParentStepFunctionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
-
Effect: Allow
Principal:
Service:
- !Sub states.${AWS::Region}.amazonaws.com
Action: sts:AssumeRole
Policies:
-
PolicyName: ChildStepFunctionExecution
PolicyDocument:
Version: 2012-10-17
Statement:
-
Effect: Allow
Action: states:StartExecution
Resource: !Ref ChildStepFunction
-
Effect: Allow
Action: lambda:InvokeFunction
Resource:
- !GetAtt Function1.Arn
...
- !GetAtt FunctionX.Arn
I've tried replacing the above State with a simple Pass State to make sure there were no other errors in the Step Function blocking the deployment, and it deployed fine. So I know it has to do with that State. (Also of note, when deploying with the Pass State for testing, I left the role as defined above, so, again, I know it's not a syntax error with the Policies that would be causing this. Obviously, that's not the same as perhaps having the wrong or missing policies.)
[Updated 5/22/2020 based on the post from @Matt and the comment from @Joe.CK to reduce the scope to the specific Resource required.]
This Stack Overflow question pointed me in the right direction. botocore.exceptions.ClientError: An error occurred (AccessDeniedException) when calling the CreateStateMachine operation
The issue appears to be stemming from CloudWatch and I was able to get past it by adding the following statement to my IAM policy.
- Effect: Allow
Action:
- events:PutTargets
- events:PutRule
- events:DescribeRule
Resource:
- !Sub arn:${AWS::Partition}:events:${AWS::Region}:${AWS::AccountId}:rule/StepFunctionsGetEventsForStepFunctionsExecutionRule
The AWS Step Functions sample project "Start a workflow within a workflow" includes something similar but restricted to a single Lambda function it invokes.
Adding the full Role definition that solved the problem combining what Andrew provided and what was in the documentation. It's in four parts:
ParentStepFunctionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
-
Effect: Allow
Principal:
Service:
- !Sub states.${AWS::Region}.amazonaws.com
Action: sts:AssumeRole
Policies:
-
PolicyName: ParentStepFunctionExecutionPolicy
PolicyDocument:
Version: 2012-10-17
Statement:
-
Effect: Allow
Action: states:StartExecution
Resource: !Ref ChildStepFunction
-
Effect: Allow
Action:
- states:DescribeExecution
- states:StopExecution
Resource: "*"
-
Effect: Allow
Action:
- events:PutTargets
- events:PutRule
- events:DescribeRule
Resource: !Sub arn:aws:events:${AWS::Region}:${AWS::AccountId}:rule/StepFunctionsGetEventsForStepFunctionsExecutionRule
-
Effect: Allow
Action: lambda:InvokeFunction
Resource:
- !GetAtt Function1.Arn
...
- !GetAtt FunctionX.Arn
Just a second. This is slightly different, an inline policy, authorizing the events:PutRule action on the StepFunctionsGetEventsForStepFunctionsExecutionRule managed rule resource.
StateMachine:
Type: AWS::Serverless::StateMachine
Properties:
DefinitionUri: statemachine/parentstatemachine.asl.json
DefinitionSubstitutions:
ChildWorkflowArn: !Ref ChildStateMachine
Policies:
- Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- events:PutTargets
- events:PutRule
- events:DescribeRule
Resource: !Sub arn:${AWS::Partition}:events:${AWS::Region}:${AWS::AccountId}:rule/StepFunctionsGetEventsForStepFunctionsExecutionRule
- StepFunctionsExecutionPolicy:
StateMachineName: !Ref ChildStateMachine
Just to make sure wires aren't crossed, the following is somewhat like the error that CloudFormation reports without the inline policy statement, though not exactly.
'arn:aws:iam::xxxxxxxx:role/xxxxxxxx' is not authorized to create managed-rule.
(
Service: AWSStepFunctions;
Status Code: 400;
Error Code: AccessDeniedException;
Request ID: xxxxxxx;
Proxy: null
)
role/xxxxxxxx is generated by the SAM CloudFormation transformation for the AWS::Serverless::StateMachine resource. It's blatant automation.
I added the "CloudWatcheventsFullAccess" managed policy, and that error went away. Thank you to the above answers. I wanted to add my code example here, because it would not fit inside of a comment.
NetworkFactory:
Type: AWS::Serverless::StateMachine
Properties:
DefinitionUri: statemachine/network-factory.asl.json
DefinitionSubstitutions:
CreateHubStateMachineArn: !Ref CreateHubStateMachine
CreateVpcStateMachineArn: !Ref CreateVpcStateMachine
Policies:
- StepFunctionsExecutionPolicy:
StateMachineName: !GetAtt CreateHubStateMachine.Name
- StepFunctionsExecutionPolicy:
StateMachineName: !GetAtt CreateVpcStateMachine.Name
- "CloudWatchEventsFullAccess"
The StepFunctionsGetEventsForStepFunctionsExecutionRule is definitely key to the solution. For my situation, that wasn't enough. When using Terraform, I also had to bump the AWS provider to >= 2.69 since that is where the provider picks up the retry logic for AccessDeniedExceptions. Additionally, I was running into issues with the resource dependency graph that Terraform built to apply the changes. The graph had terraform trying to create the state machine before the policy was created and the policy had dependencies on the state machine. The solution was to break up the uber policy into three policy attachments to the role used by the state machine. One policy had the StepFunctionsGetEventsForStepFunctionsExecutionRule, a second had policies around the states action and the third was the original uber policy. With that in place, the dependency graph was such that the two new policies were created, then the state machine then the original uber policy and all was well.