AWS CodePipeline错误:不允许跨帐户传递角色

时间:2018-01-21 00:42:21

标签: amazon-web-services amazon-cloudformation amazon-iam aws-codepipeline

我正在尝试创建一个AWS CodePipeline,将生产代码部署到一个单独的帐户。代码由lambda函数组成,该函数使用sam模板和cloudformation进行设置。我目前正在部署到同一帐户而没有错误。我添加了另一个具有手动批准操作的阶段,在批准后,它应该部署到另一个帐户。它失败并出现以下错误:

  

不允许跨帐户传递角色(服务:AmazonCloudFormation;状态代码:403;错误代码:AccessDenied;请求ID:d880bdd7-fe3f-11e7-8a8c-7dcffeae19ae)

我在生产帐户中有一个角色,它与拥有管道的开发帐户之间存在信任关系。我给出了管道角色和生产角色管理员策略,以确保它不是一个策略问题。我使用此walkthrough中的技术编辑了管道。我正在松散地进行演练,因为他们设置的场景与我正在做的略有不同。

我的管道中的部署部分如下所示:

{
   "name": "my-stack",
   "actionTypeId": {
       "category": "Deploy",
       "owner": "AWS",
       "provider": "CloudFormation",
       "version": "1"
   },
   "runOrder": 2,
   "configuration": {
       "ActionMode": "CHANGE_SET_REPLACE",
           "Capabilities": "CAPABILITY_IAM",
       "ChangeSetName": "ProductionChangeSet",
       "RoleArn": "arn:aws:iam::000000000000:role/role-to-assume",
       "StackName": "MyProductionStack",
       "TemplatePath": "BuildArtifact::NewSamTemplate.yaml"
   },
   "outputArtifacts": [],
   "inputArtifacts": [
       {
           "name": "BuildArtifact"
      }
   ]
}

我可以使用控制台假设进入生产帐户中的角色。我不确定passrole是如何不同的,但是从我读过的所有东西都需要相同的假设角色信任关系。

如何为跨账户管道配置IAM?

2 个答案:

答案 0 :(得分:5)

通常,如果您想在多个帐户中执行任何操作,则必须在双方都允许这样做。这是通过角色假设完成的。

管道分布式部件通过管道工件进行通信,这些工件保存在S3存储桶中,并使用KMS加密密钥进行解/加密。必须可以从分发管道的所有帐户访问此密钥。

CI帐户中的

KMSKey:
  Type: AWS::KMS::Key
  Properties:
    EnableKeyRotation: true
    KeyPolicy:
      Version: "2012-10-17"
      Id: pipeline-kms-key
      Statement:
        - Sid: Allows admin of the key
          Effect: Allow
          Principal:
            AWS: !Sub "arn:aws:iam::${AWS::AccountId}:root"
          Action: ["kms:*"]
          Resource: "*"
        - Sid: Allow use of the key from the other accounts
          Effect: Allow
          Principal:
            AWS:
              - !Sub "arn:aws:iam::${DevAccountId}:root"
              - !GetAtt CodePipelineRole.Arn
          Action:
            - kms:Encrypt
            - kms:Decrypt
            - kms:ReEncrypt*
            - kms:GenerateDataKey*
            - kms:DescribeKey
          Resource: "*"
KMSAlias:
  Type: AWS::KMS::Alias
  Properties:
    AliasName: !Sub alias/codepipeline-crossaccounts
    TargetKeyId: !Ref KMSKey

S3存储桶必须允许通过策略从不同帐户进行访问:

CI帐户中的管道堆栈

S3ArtifactBucketPolicy:
  Type: AWS::S3::BucketPolicy
  Properties:
    Bucket: !Ref S3ArtifactBucket
    PolicyDocument:
      Statement:
      - Action: ["s3:*"]
        Effect: Allow
        Resource:
        - !Sub "arn:aws:s3:::${S3ArtifactBucket}"
        - !Sub "arn:aws:s3:::${S3ArtifactBucket}/*"
        Principal:
          AWS:
          - !GetAtt CodePipelineRole.Arn
          - !Sub "arn:aws:iam::${DevAccountId}:role/cross-account-role"
          - !Sub "arn:aws:iam::${DevAccountId}:role/cloudformation-role"

CodePipeline:
  Type: AWS::CodePipeline::Pipeline
  Properties:
    ArtifactStore:
      Type: S3
      Location: !Ref S3ArtifactBucket
      EncryptionKey:
        Id: !Ref KMSKey
        Type: KMS
    ...

管道(CI帐户)必须拥有在其他(DEV)帐户中担任角色的权限:

CI帐户中的管道堆栈

CodePipelinePolicy:
  Type: AWS::IAM::Policy
  Properties:
     PolicyDocument:
        Statement:
          - Action: ["sts:AssumeRole"]
            Resource: !Sub "arn:aws:iam::${DevAccountId}:role/cross-account-role
            Effect: Allow
          ...

该角色必须允许被假定为管道:

DEV帐户中的管道堆栈

CrossAccountRole:
  Type: AWS::IAM::Role
  Properties:
    RoleName: cross-account-role
    Path: /
    AssumeRolePolicyDocument:
      Version: 2012-10-17
      Statement:
        - Effect: Allow
          Principal:
            AWS: !Sub "arn:aws:iam::${CIAccountId}:root"
          Action: sts:AssumeRole

CrossAccountPolicy:
  Type: AWS::IAM::Policy
  Properties:
    PolicyName: CrossAccountPolicy
    PolicyDocument:
      Version: 2012-10-17
      Statement:
        - Effect: Allow
          Action:
            - cloudformation:*
            - codebuild:*
            - s3:*
            - iam:PassRole
          Resource: "*"
        - Effect: Allow
          Action: ["kms:Decrypt", "kms:Encrypt"]
          Resource: !Ref KMSKey
    Roles: [!Ref CrossAccountRole]

管道(从CI帐户管理和执行)必须承担另一个帐户的角色,才能从帐户中执行操作:

CI帐户中的管道堆栈

CodePipeline:
  Type: AWS::CodePipeline::Pipeline
  Properties:
    Name: pipeline
    RoleArn: !GetAtt CodePipelineRole.Arn
    Stages:
      ...
      - Name: StagingDev
      Actions:
      - Name: create-changeset
        InputArtifacts:
        - Name: BuildArtifact
        OutputArtifacts: []
        ActionTypeId:
          Category: Deploy
          Owner: AWS
          Version: "1"
          Provider: CloudFormation
        Configuration:
          StackName: app-stack-dev
          ActionMode: CHANGE_SET_REPLACE
          ChangeSetName: app-changeset-dev
          Capabilities: CAPABILITY_NAMED_IAM
          TemplatePath: "BuildArtifact::template.yml"
          RoleArn: !Sub "arn:aws:iam::${DevAccountId}:role/cloudformation-role"  # the action will be executed with this role
        RoleArn: !Sub "arn:aws:iam::${DevAccountId}:role/cross-account-role" # the pipeline assume this role to execute this action
  ...

上面的代码显示了如何在不同的帐户中执行CloudFormation操作,对于CodeBuild或CodeDeploy等不同的操作,方法是相同的。

AWS团队提供了一个很好的示例https://github.com/awslabs/aws-refarch-cross-account-pipeline

另一个例子是https://github.com/adcreare/cloudformation/tree/master/code-pipeline-cross-account

或者你可以在这里查看我的整个工作代码https://github.com/ttulka/aws-samples/tree/master/cross-account-pipeline

答案 1 :(得分:0)

我认为问题在于您的CloudFormation角色位于其他帐户中,但您的操作角色却不是。只允许管道角色在其他帐户中承担操作角色。

动作角色是直接位于ActionDeclaration下的角色。

基本上您的角色应配置如下:

  • 管道角色:帐户A
  • 行动角色:帐户B
  • CloudFormation角色:帐户B

有关于在此设置跨帐户操作的一些信息:https://docs.aws.amazon.com/codepipeline/latest/userguide/pipelines-create-cross-account.html

此处定义了操作角色:https://docs.aws.amazon.com/codepipeline/latest/APIReference/API_ActionDeclaration.html