Step Function 中的嵌套 Step Function:未知错误:“...未授权创建托管规则”

Posted

技术标签:

【中文标题】Step Function 中的嵌套 Step Function:未知错误:“...未授权创建托管规则”【英文标题】:Nested Step Function in a Step Function: Unknown Error: "...not authorized to create managed-rule" 【发布时间】:2020-06-22 01:39:18 【问题描述】:

我在 SAM/CloudFormation 模板中创建了一个 Step Function(父级),除其他外,它调用另一个 Step Function(子级)。我正在按照使用service integration pattern 从父级调用子级的说明进行操作。但是我遇到了一个与 IAM 相关的(我认为)错误,我在通过 CLI 部署时无法解决。 (错误显示在 CLI 输出中,因此它从未真正进入 AWS。之前已经进行了大量部署,因此 changeset 只是尝试使用此部署修改 Step Function。)

'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)

为了获得我想要的同步行为(父调用子,等待子的执行完成,然后进入下一个状态)我使用建议(来自上面的服务集成模式链接)创建一个任务(在我的SAM 模板),如下所示:

...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...

我已经为 Parent 定义了 IAM-role 如下,确保它仅对 Parent 中的 Lambda 函数具有 Lambda 执行权限,并且更适用于该问题,具有 Child 的 StartExecution 的权限。我按照下面链接中的说明进行操作,说明 StartExecution 是使用服务集成模式时所需的唯一权限。

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

我尝试将上述状态替换为简单的Pass 状态,以确保 Step Function 中没有其他错误阻止部署,并且部署正常。所以我知道这与那个州有关。 (另外值得注意的是,当使用Pass 状态进行部署以进行测试时,我离开了上面定义的角色,所以,我再次知道,这不是导致这种情况的策略的语法错误。显然,这不一样可能有错误缺少政策。)

【问题讨论】:

在权限修复后我仍然遇到这个问题,它也是间歇性的。尝试添加一堆DependsOn,但没有帮助! 【参考方案1】:

[根据 @Matt 的帖子和 @Joe.CK 的评论于 2020 年 5 月 22 日更新,以将范围缩小到所需的特定资源。]

这个 Stack Overflow 问题为我指明了正确的方向。 botocore.exceptions.ClientError: An error occurred (AccessDeniedException) when calling the CreateStateMachine operation

问题似乎源于 CloudWatch,我通过将以下语句添加到我的 IAM 政策中得以解决。

- Effect: Allow
  Action:
  - events:PutTargets
  - events:PutRule
  - events:DescribeRule
  Resource: 
  - !Sub arn:$AWS::Partition:events:$AWS::Region:$AWS::AccountId:rule/StepFunctionsGetEventsForStepFunctionsExecutionRule

AWS Step Functions 示例项目“在工作流中启动工作流”包含类似的内容,但仅限于它调用的单个 Lambda 函数。

【讨论】:

啊哈。这对我帮助很大!谢谢。它帮助我更仔细地阅读了上面的链接(这里:docs.aws.amazon.com/step-functions/latest/dg/…),我最初说只需要states:StartExecution。但是,向下滚动您会发现它根据 同步 调用的需要概述了您在此处显示的内容(加上更多内容)。我猜当它是异步的时,它只是使用startExecution“触发并忘记”,但要跟踪完成,您需要让 CloudWatch 将消息发送回 Step Functions。今晚我会尝试,一旦测试,我会将其标记为已解决。 请参阅下文,了解如何将此答案完全纳入正确的角色定义中。 您实际上并不需要所有资源 *。 (允许任何角色访问 * 资源通常是个坏主意)您要查找的是StepFunctionsGetEventsForStepFunctionsExecutionRule。它用于 Step Function 中的嵌套工作流(即作为任务启动另一个状态机执行) 我遇到了类似的问题,但是在调用 ECS 时,为了弄清楚我最初在资源上允许“*”,然后在控制台中注意到它指的是 StepFunctionsGetEventsForECSTaskRule。事实上,我遇到了这两个问题,因为它是一个 Step Function 调用一个运行 ECS 任务的 Step Function【参考方案2】:

添加完整的角色定义,结合 Andrew 提供的内容和文档中的内容来解决问题。它分为四个部分:

    允许子 Step Function 通过 states:StartExecution 运行 允许父级描述和停止任何 Step Functions。 (我认为这可能会根据资源进行更紧密的定制;但是,这是 AWS 文档的复制和粘贴。) 允许父级创建/修改(放置)规则到 Cloud Watch(特定系统生成/管理的资源)中,以便它可以保持到执行完成(因为同步执行)。 允许父级在 Step Function 中运行所有适用的 Lambda 函数。 (这并不是我遇到的问题的一部分,而是与整个 Step Function 相关。这也可能包括其他集成——例如 SNS——如果你有的话。)
  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

【讨论】:

我添加了托管策略 CloudWatchEventsFullAccess,一切正常。谢谢。【参考方案3】:

我添加了“CloudWatcheventsFullAccess”托管策略,该错误消失了。谢谢楼上的回答。我想在这里添加我的代码示例,因为它不适合评论。

  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"

【讨论】:

请注意,这不是好的做法。消除错误是一回事,正确地做到这一点是另一回事。为什么不给它,或者在这种情况下的所有资源,完全的管理员访问权限,再也不用担心权限了? ;-) 对所有资源的完全管理员访问权限?我不确定你指的是什么? 我指出您的解决方案使用“CloudWatchEventsFullAccess”托管策略提供了太多权限。我们不希望每次遇到权限问题时都使用“AdministratorAccess”策略,对吧?给它“CloudWatchEventsFullAccess”就是沿着这条路走的;过度分配权限以缓解问题。【参考方案4】:

只需一秒钟。这稍有不同,它是一个内联策略,授权对 StepFunctionsGetEventsForStepFunctionsExecutionRule 托管规则资源的 events:PutRule 操作。

  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

为了确保线路没有交叉,以下内容有点像 CloudFormation 在没有内联策略声明的情况下报告的错误,尽管不完全一样。

'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 由 SAM CloudFormation 转换为 AWS::Serverless::StateMachine 资源生成。这是公然的自动化。

【讨论】:

【参考方案5】:

StepFunctionsGetEventsForStepFunctionsExecutionRule 绝对是解决方案的关键。就我的情况而言,这还不够。使用 Terraform 时,我还必须将 AWS 提供程序提高到 >= 2.69,因为这是提供程序获取 AccessDeniedExceptions 的重试逻辑的地方。此外,我遇到了 Terraform 为应用更改而构建的资源依赖图的问题。该图有 terraform 在创建策略之前尝试创建状态机,并且策略依赖于状态机。解决方案是将 uber 策略分解为状态机使用的角色的三个策略附件。一个政策有StepFunctionsGetEventsForStepFunctionsExecutionRule,第二个政策围绕states 行动,第三个是原始的超级政策。有了这个,依赖图就创建了两个新策略,然后是状态机,然后是原始 uber 策略,一切都很好。

【讨论】:

以上是关于Step Function 中的嵌套 Step Function:未知错误:“...未授权创建托管规则”的主要内容,如果未能解决你的问题,请参考以下文章

Step Function 中的 AWS Batch 作业执行结果

如何在 PLIST 中访问嵌套的 NSDictionary?

从 SNS 触发 Step Function

RDLC 怎么嵌套多级子报表

错误:(-215:断言失败)_step >= minstep in function 'cv::Mat::Mat'

如何使用 Step Function 在 Amazon EMR 中添加步骤