1
votes

The AWS Lambda function pipeline I did just set up following the official AWS documentation (Building a Continuous Delivery Pipeline for a Lambda Application with AWS CodePipeline) fails for me on deploy stage (both source and build stages do succeed) with this message:

Action execution failed
Role arn:aws:iam::************:role/service-role/AWSCodePipelineServiceRole-eu-west-1-lambda-pipeline
is invalid or cannot be assumed
(Service: AmazonCloudFormation; Status Code: 400; Error Code: ValidationError; Request ID: ********-****-****-************)

I did try to edit the deploy stage and change the specified service role (WSCodePipelineServiceRole-eu-west-1-lambda-pipeline), an run again the pipeline, with no success... More, editing again the deploy stage after re-running the pipeline, I see the previous role is there again... ( solved myself: I was not saving changes... :-( )

This is my template.yml:

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Outputs the time
Resources:
  TimeFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.handler
      Runtime: nodejs10.x
      CodeUri: ./
      Events:
        MyTimeApi:
          Type: Api
          Properties:
            Path: /TimeResource
            Method: GET

This is my buildspec.yml:

version: 0.2
phases:
  install:
    runtime-versions:
        nodejs: 10
  build:
    commands:
      - npm install
      - export BUCKET=lambda-pipeline-repo-bucket
      - aws cloudformation package --template-file template.yml --s3-bucket $BUCKET --output-template-file outputtemplate.yml
artifacts:
  type: zip
  files:
    - template.yml
    - outputtemplate.yml

This is the WSCodePipelineServiceRole-eu-west-1-lambda-pipeline role policy JSON:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "iam:PassRole",
            "Resource": "*",
            "Condition": {
                "StringEqualsIfExists": {
                    "iam:PassedToService": [
                        "cloudformation.amazonaws.com",
                        "elasticbeanstalk.amazonaws.com",
                        "ec2.amazonaws.com",
                        "ecs-tasks.amazonaws.com"
                    ]
                }
            }
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "opsworks:DescribeStacks",
                "rds:*",
                "devicefarm:GetRun",
                "cloudformation:CreateChangeSet",
                "autoscaling:*",
                "codebuild:BatchGetBuilds",
                "servicecatalog:ListProvisioningArtifacts",
                "devicefarm:ScheduleRun",
                "devicefarm:ListDevicePools",
                "cloudformation:UpdateStack",
                "servicecatalog:DescribeProvisioningArtifact",
                "cloudformation:DescribeChangeSet",
                "devicefarm:ListProjects",
                "cloudformation:ExecuteChangeSet",
                "sns:*",
                "codedeploy:RegisterApplicationRevision",
                "cloudformation:*",
                "opsworks:DescribeDeployments",
                "devicefarm:CreateUpload",
                "cloudformation:DescribeStacks",
                "codecommit:GetUploadArchiveStatus",
                "cloudwatch:*",
                "opsworks:DescribeInstances",
                "cloudformation:DeleteStack",
                "ecr:DescribeImages",
                "ecs:*",
                "ec2:*",
                "codebuild:StartBuild",
                "opsworks:DescribeApps",
                "opsworks:UpdateStack",
                "cloudformation:ValidateTemplate",
                "codedeploy:CreateDeployment",
                "codedeploy:GetApplicationRevision",
                "codedeploy:GetDeploymentConfig",
                "servicecatalog:CreateProvisioningArtifact",
                "sqs:*",
                "cloudformation:DeleteChangeSet",
                "codecommit:GetCommit",
                "servicecatalog:DeleteProvisioningArtifact",
                "codedeploy:GetApplication",
                "cloudformation:SetStackPolicy",
                "codecommit:UploadArchive",
                "s3:*",
                "elasticloadbalancing:*",
                "codecommit:CancelUploadArchive",
                "devicefarm:GetUpload",
                "elasticbeanstalk:*",
                "opsworks:UpdateApp",
                "opsworks:CreateDeployment",
                "cloudformation:CreateStack",
                "servicecatalog:UpdateProduct",
                "codecommit:GetBranch",
                "lambda:*",
                "codedeploy:GetDeployment",
                "opsworks:DescribeCommands"
            ],
            "Resource": "*"
        },
        {
            "Sid": "VisualEditor2",
            "Effect": "Allow",
            "Action": "codestar-connections:UseConnection",
            "Resource": "*"
        }
    ]
}

Please feel free to ask for any additional information...

Please give me some direction, I'm out of my depth here...

UPDATE 1
After @omuthu answer, I did check my pipeline policy (AWSCodePipelineServiceRole-eu-west-1-lambda-pipeline):

{
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "iam:PassRole",
            "Resource": "*",
            "Condition": {
                "StringEqualsIfExists": {
                    "iam:PassedToService": [
                        "cloudformation.amazonaws.com",
                        "elasticbeanstalk.amazonaws.com",
                        "ec2.amazonaws.com",
                        "ecs-tasks.amazonaws.com"
                    ]
                }
            }
        },
        ...
    ],
    "Version": "2012-10-17"
}

and I see I already have iam:PassRole... It is conditioned to services "cloudformation.amazonaws.com", "elasticbeanstalk.amazonaws.com", "ec2.amazonaws.com", "ecs-tasks.amazonaws.com"... Should I add some other services? Or better remove the condition?

UPDATE 2 I did try to remove the condition, with no different result.

UPDATE 3 @shariqmaws: I did export my pipeline (named "lambda-pipeline"); here it is:

{
    "pipeline": {
        "version": 1,
        "artifactStore": {
            "location": "codepipeline-eu-west-1-##########",
            "type": "S3"
        },
        "roleArn": "arn:aws:iam::##########:role/service-role/AWSCodePipelineServiceRole-eu-west-1-lambda-pipeline",
        "name": "lambda-pipeline",
        "stages": [
            {
                "name": "Source",
                "actions": [
                    {
                        "inputArtifacts": [],
                        "region": "eu-west-1",
                        "name": "Source",
                        "configuration": {
                            "PollForSourceChanges": "true",
                            "BranchName": "master",
                            "RepositoryName": "lambda-pipeline-repo"
                        },
                        "outputArtifacts": [
                            {
                                "name": "SourceArtifact"
                            }
                        ],
                        "runOrder": 1,
                        "actionTypeId": {
                            "provider": "CodeCommit",
                            "owner": "AWS",
                            "version": "1",
                            "category": "Source"
                        }
                    }
                ]
            },
            {
                "name": "Build",
                "actions": [
                    {
                        "inputArtifacts": [
                            {
                                "name": "SourceArtifact"
                            }
                        ],
                        "region": "eu-west-1",
                        "name": "Build",
                        "configuration": {
                            "ProjectName": "lambda-pipeline-build"
                        },
                        "outputArtifacts": [
                            {
                                "name": "BuildArtifact"
                            }
                        ],
                        "runOrder": 1,
                        "actionTypeId": {
                            "provider": "CodeBuild",
                            "owner": "AWS",
                            "version": "1",
                            "category": "Build"
                        }
                    }
                ]
            },
            {
                "name": "Deploy",
                "actions": [
                    {
                        "inputArtifacts": [
                            {
                                "name": "BuildArtifact"
                            }
                        ],
                        "region": "eu-west-1",
                        "name": "Deploy",
                        "configuration": {
                            "TemplatePath": "BuildArtifact::outputtemplate.yml",
                            "ActionMode": "CHANGE_SET_REPLACE",
                            "ChangeSetName": "lambda-pipeline-changeset",
                            "Capabilities": "CAPABILITY_IAM",
                            "RoleArn": "arn:aws:iam::##########:role/service-role/AWSCodePipelineServiceRole-eu-west-1-lambda-pipeline",
                            "StackName": "lambda-pipeline-stack"
                        },
                        "outputArtifacts": [],
                        "runOrder": 1,
                        "actionTypeId": {
                            "provider": "CloudFormation",
                            "owner": "AWS",
                            "version": "1",
                            "category": "Deploy"
                        }
                    }
                ]
            }
        ]
    },
    "metadata": {
        "updated": 1584382274.615,
        "created": 1584382274.615,
        "pipelineArn": "arn:aws:codepipeline:eu-west-1:##########:lambda-pipeline"
    }
}

Can you find any issue with this pipeline? (and thanks for your help!)

UPDATE 4
@Shawn: I did read the document you pointed me to, and checked my configuration... I am in region eu-west-1, and it is enabled, as I see in my account settings: enter image description here

Thanks for any comment...

2
Are the regions you are using activated for STS in IAM? See docs.amazonaws.cn/en_us/IAM/latest/UserGuide/… - Shawn
Why is CloudFormation action trying to assume CodePipeline role (as per error)? can you please export the pipeline and paste in your question., i believe there is an issue with pipeline definition. - shariqmaws
$ aws codepipeline get-pipeline --name <pipeline_name> - shariqmaws
Thanks, @shariqmaws... I did add my exported pipeline to the question, under UPDATE 3... - MarcoS
Thanks, @Shawn... I did follow your suggestion under UPDATE 4, but it looks like the region I am using ("ue-west-1") is activated for STS in IAM... - MarcoS

2 Answers

2
votes

Add iam:PassRole to your codepipeline policy as it tries to pass the role (attach the role) to lambda

Read more about it here

2
votes

The problem is with the CloudFormation 'Deploy' action configuration:

"configuration": {
    "TemplatePath": "BuildArtifact::outputtemplate.yml",
    "ActionMode": "CHANGE_SET_REPLACE",
    "ChangeSetName": "lambda-pipeline-changeset",
    "Capabilities": "CAPABILITY_IAM",
    "RoleArn": "arn:aws:iam::##########:role/service-role/AWSCodePipelineServiceRole-eu-west-1-lambda-pipeline",
    "StackName": "lambda-pipeline-stack"
},

The 'RoleArn' above is a role in target account that CloudFormation will assume to execute the stack. Think of this role as the identity that will actually be creating the resources you have defined in the CloudFormation template. Now since CloudFormation service need to assume this role, the trust policy of this role should be for Cloudformation and NOT CodePipeline as it currently is.

Correct Trust Policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudformation.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

Fix:

  1. Create a new role for the CloudFormation service

enter image description here

  1. Provide the permissions to this role that are required to create the resources defined in the template

  2. Update the pipeline Action 'Deploy' in Stage 'Deploy' and set the RoleARN in configuration properties of this Action to the new role's ARN instead of "arn:aws:iam::##########:role/service-role/AWSCodePipelineServiceRole-eu-west-1-lambda-pipeline".