A quick guide to how to fix this cloudformation error: is not authorized to perform: iam:PassRole on resource:

The Problem: is not authorized to perform: iam:PassRole on resource:

Yesterday I ran into this slightly miss leading error shown below:

User: arn:aws:iam::123456789123:user/myUser is not authorized to perform: iam:PassRole on resource: CFDeployRole-lkjh1234lhj1324(Service: AWSCodePipeline; Status Code: 400; Error Code: AccessDeniedException; Request ID: xxxxxxxxx-1111-xxxx-1111-xxxxxxxxx; Proxy: null)

I ran into this while deploying an IAM role in CloudFormation and then using it as the RoleARN for one action in a CodePipeline deployed by the same CloudFormation template. Specifically, it was used in a CloudFormation CREATE_UPDATE action. A cut-down example of what I mean is below:

...
  CFDeployRole:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Action:
            - 'sts:AssumeRole'
            Effect: Allow
            Principal:
              Service:
              - "cloudformation.amazonaws.com"
      Policies:
        - PolicyName: "CodePipeline-Permissions"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: "Allow"
                Action:
                  - "cloudformation:CreateChangeSet"
                  - ...
                Resource:
                  - ...
...
  CodePipeline:
    Type: AWS::CodePipeline::Pipeline
    Properties:
      ArtifactStore:
        Location: !Ref CodePipelineArtifactStore
        Type: "S3"
      Name: CodePipelineName
      RoleArn:
        Fn::ImportValue: !Sub "${IamStack}-CodePipelineRoleARN"
      Tags:
        - Key: "Example"
          Value: "Example"
      Stages:
        - Actions:
            - Name: "BuildSource"
              ActionTypeId:
                Category: "Source"
                Owner: "AWS"
                Provider: "S3"
                Version: "1"
              OutputArtifacts:
                - Name: BuildArtifact
              Configuration:
                S3Bucket: !Ref BucketID
                S3ObjectKey: !Ref BucketKey
              RunOrder: 1
          Name: "BuildSource"
          - Name: "CloudFormation-Deploy-Stage"
            ActionTypeId:
              Category: "Deploy"
              Owner: "AWS"
              Provider: "CloudFormation"
              Version: "1"
            Configuration:
              ActionMode: CREATE_UPDATE
              StackName: !Sub '${Environment}-Example-CF-Deploy'
              Capabilities: CAPABILITY_IAM,CAPABILITY_AUTO_EXPAND
              ParameterOverrides: !Sub '{"Environment": "${Environment}", "ScheduleRate": "${ScheduleRate}"}'
              RoleArn: !Ref CFDeployRole
              TemplatePath: 'BuildArtifact::package.yml'
            RunOrder: 2
            InputArtifacts:
              - Name: BuildArtifact
          Name: "Deploy"

If you look close at the RoleARN in the deploy CodePipeline action you’ll notice it is !Ref CFDeployRole. For some resources this will give you the ARN, some it gives you the name. In this case, !Ref CFDeployRole is only providing the name.

The Solution

The solution is to use !GetAtt CFDeployRole.Arn instead of !Ref CFDeployRole.

RoleArn: needs an ARN, !Ref CFDeployRole is only passing in the role name. Once the problem is know the solution is pretty clear, the error thrown does not make the issue obvious though, requiring a bit of troubleshooting.

Example cut-down CodePipeline resource with the correct RoleArn:

  CodePipeline:
    Type: AWS::CodePipeline::Pipeline
    Properties:
      ArtifactStore:
        Location: !Ref CodePipelineArtifactStore
        Type: "S3"
      Name: CodePipelineName
      RoleArn:
        Fn::ImportValue: !Sub "${IamStack}-CodePipelineRoleARN"
      Tags:
        - Key: "Example"
          Value: "Example"
      Stages:
        - Actions:
            - Name: "BuildSource"
              ActionTypeId:
                Category: "Source"
                Owner: "AWS"
                Provider: "S3"
                Version: "1"
              OutputArtifacts:
                - Name: BuildArtifact
              Configuration:
                S3Bucket: !Ref BucketID
                S3ObjectKey: !Ref BucketKey
              RunOrder: 1
          Name: "BuildSource"
          - Name: "CloudFormation-Deploy-Stage"
            ActionTypeId:
              Category: "Deploy"
              Owner: "AWS"
              Provider: "CloudFormation"
              Version: "1"
            Configuration:
              ActionMode: CREATE_UPDATE
              StackName: !Sub '${Environment}-Example-CF-Deploy'
              Capabilities: CAPABILITY_IAM,CAPABILITY_AUTO_EXPAND
              ParameterOverrides: !Sub '{"Environment": "${Environment}", "ScheduleRate": "${ScheduleRate}"}'
              RoleArn: !GetAtt CFDeployRole.Arn
              TemplatePath: 'BuildArtifact::package.yml'
            RunOrder: 2
            InputArtifacts:
              - Name: BuildArtifact
          Name: "Deploy"