How can I change the IAM Role for a Lambda function in an CloudFormation template of an AWS CodeStar project?
I have created a AWS CodeStar project (web service, Lambda based, Node.js). By default, AWS CodeStar generates the following CloudFormation:
AWSTemplateFormatVersion: 2010-09-09
Transform:
- AWS::Serverless-2016-10-31
- AWS::CodeStar
Parameters:
ProjectId:
Type: String
Description: AWS CodeStar projectID used to associate new resources to team members
Resources:
HelloWorld:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs4.3
Role:
Fn::ImportValue:
!Join ['-', [!Ref 'ProjectId', !Ref 'AWS::Region', 'LambdaTrustRole']]
Events:
GetEvent:
Type: Api
Properties:
Path: /
Method: get
PostEvent:
Type: Api
Properties:
Path: /
Method: post
Now, I would like to replace this role with a role of my own, because I need to add policies for the Lambda function to access other AWS resources. At the same time I have also removed the API Gateway, because I will add a scheduler to trigger the Lambda invocations later:
AWSTemplateFormatVersion: 2010-09-09
Transform:
- AWS::Serverless-2016-10-31
- AWS::CodeStar
Parameters:
ProjectId:
Type: String
Description: AWS CodeStar projectID used to associate new resources to team members
Resources:
HelloWorld:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs4.3
Role: !Ref HelloWorldLambdaRole
HelloWorldLambdaRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
However, when I commit and push these changes, AWS CodePipeline fails to update the CloudFormation template:
CREATE_FAILED AWS::IAM::Role EchoLambdaRole API: iam:CreateRole User: arn:aws:sts::[accountId]:assumed-role/CodeStarWorker-[projectId]-CloudFormation/AWSCloudFormation is not authorized to perform: iam:CreateRole on resource: arn:aws:iam::[accountId]:role/awscodestar-[projectId]-lambda-HelloWorldLambdaRole-ABCDEF123456
Based on this feedback, I conclude that CodeStarWorker-[projectId]-CloudFormation/AWSCloudFormation
role is not authorized to create IAM roles. However, this role is hidden from my CloudFormation template and to my understanding it is something that is setup by CodeStar automatically. As an AWS account admin, I could simply just edit the associated policy, but IMHO this is not the way to solve this problem.
Edit:
I have checked IAM configuration in my account. An aws-codestar-service-role has been created and it is associated with the AWSCodeStarServiceRole
policy that has the following statement (among other statements, see link for details):
{
"Sid": "ProjectWorkerRoles",
"Effect": "Allow",
"Action": [
"iam:AttachRolePolicy",
"iam:CreateRole",
"iam:DeleteRole",
"iam:DeleteRolePolicy",
"iam:DetachRolePolicy",
"iam:GetRole",
"iam:PassRole",
"iam:PutRolePolicy",
"iam:SetDefaultPolicyVersion",
"iam:CreatePolicy",
"iam:DeletePolicy",
"iam:AddRoleToInstanceProfile",
"iam:CreateInstanceProfile",
"iam:DeleteInstanceProfile",
"iam:RemoveRoleFromInstanceProfile"
],
"Resource": [
"arn:aws:iam::*:role/CodeStarWorker*",
"arn:aws:iam::*:policy/CodeStarWorker*",
"arn:aws:iam::*:instance-profile/awscodestar-*"
]
},
There is also the CodeStarWorker-[projectId]-CloudFormation
role, that has an inline policy named CodeStarWorkerCloudFormationRolePolicy
with the following configuration:
{
"Statement": [
{
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": [
"arn:aws:s3:::aws-chargeodestar-eu-west-1-[accountId]-[projectId]-pipeline",
"arn:aws:s3:::aws-codestar-eu-west-1-[accountId]-[projectId]-pipeline/*"
],
"Effect": "Allow"
},
{
"Action": [
"codestar:SyncResources",
"lambda:CreateFunction",
"lambda:DeleteFunction",
"lambda:AddPermission",
"lambda:UpdateFunction",
"lambda:UpdateFunctionCode",
"lambda:GetFunctionConfiguration",
"lambda:UpdateFunctionConfiguration",
"lambda:RemovePermission",
"apigateway:*",
"dynamodb:CreateTable",
"dynamodb:DeleteTable",
"dynamodb:DescribeTable",
"kinesis:CreateStream",
"kinesis:DeleteStream",
"kinesis:DescribeStream",
"sns:CreateTopic",
"sns:DeleteTopic",
"sns:ListTopics",
"sns:GetTopicAttributes",
"sns:SetTopicAttributes",
"s3:CreateBucket",
"s3:DeleteBucket"
],
"Resource": "*",
"Effect": "Allow"
},
{
"Action": [
"iam:PassRole"
],
"Resource": [
"arn:aws:iam::[accountId]:role/CodeStarWorker-[projectId]-Lambda"
],
"Effect": "Allow"
},
{
"Action": [
"cloudformation:CreateChangeSet"
],
"Resource": [
"arn:aws:cloudformation:eu-west-1:aws:transform/Serverless-2016-10-31",
"arn:aws:cloudformation:eu-west-1:aws:transform/CodeStar"
],
"Effect": "Allow"
}
]
}
Since I have created the project, the CodeStar_[projectId]_Owner
policy has been directly attached to my user.
Edit 2:
Despite my own recommendation, I attempted to update the inlined CodeStarWorkerCloudFormationRolePolicy
of the CodeStarWorker-[projectId]-CloudFormation
role by adding the following policy statement:
{
"Action": [
"iam:AttachRolePolicy",
"iam:CreateRole",
"iam:DeleteRole",
"iam:DetachRolePolicy",
"iam:GetRole",
"iam:PassRole"
],
"Resource": [
"arn:aws:iam::699602212296:role/awscodestar-[projectId]-*"
],
"Effect": "Allow"
}
However, this caused the following error in CloudFormation:
CREATE_FAILED AWS::CodeStar::SyncResources SyncResources123456789012 com.amazon.coral.service.InternalFailure
The CodeStar Service uses a service role called aws-codestar-service-role, with the following statement. You may want to amend this service role if it allows the dynamic worker roles for the project to inherit the IAM role creation action. Otherwise CodeStar could overwrite your changes.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ProjectStack",
"Effect": "Allow",
"Action": [
"cloudformation:*Stack*",
"cloudformation:GetTemplate"
],
"Resource": [
"arn:aws:cloudformation:*:*:stack/awscodestar-*",
"arn:aws:cloudformation:*:*:stack/awseb-*"
]
},
{
"Sid": "ProjectStackTemplate",
"Effect": "Allow",
"Action": [
"cloudformation:GetTemplateSummary",
"cloudformation:DescribeChangeSet"
],
"Resource": "*"
},
{
"Sid": "ProjectQuickstarts",
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::awscodestar-*/*"
]
},
{
"Sid": "ProjectS3Buckets",
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::aws-codestar-*",
"arn:aws:s3:::aws-codestar-*/*",
"arn:aws:s3:::elasticbeanstalk-*",
"arn:aws:s3:::elasticbeanstalk-*/*"
]
},
{
"Sid": "ProjectServices",
"Effect": "Allow",
"Action": [
"codestar:*Project",
"codestar:*Resource*",
"codestar:List*",
"codestar:Describe*",
"codestar:Get*",
"codestar:AssociateTeamMember",
"codecommit:*",
"codepipeline:*",
"codedeploy:*",
"codebuild:*",
"ec2:RunInstances",
"autoscaling:*",
"cloudwatch:Put*",
"ec2:*",
"elasticbeanstalk:*",
"elasticloadbalancing:*",
"iam:ListRoles",
"logs:*",
"sns:*"
],
"Resource": "*"
},
{
"Sid": "ProjectWorkerRoles",
"Effect": "Allow",
"Action": [
"iam:AttachRolePolicy",
"iam:CreateRole",
"iam:DeleteRole",
"iam:DeleteRolePolicy",
"iam:DetachRolePolicy",
"iam:GetRole",
"iam:PassRole",
"iam:PutRolePolicy",
"iam:SetDefaultPolicyVersion",
"iam:CreatePolicy",
"iam:DeletePolicy",
"iam:AddRoleToInstanceProfile",
"iam:CreateInstanceProfile",
"iam:DeleteInstanceProfile",
"iam:RemoveRoleFromInstanceProfile"
],
"Resource": [
"arn:aws:iam::*:role/CodeStarWorker*",
"arn:aws:iam::*:policy/CodeStarWorker*",
"arn:aws:iam::*:instance-profile/awscodestar-*"
]
},
{
"Sid": "ProjectTeamMembers",
"Effect": "Allow",
"Action": [
"iam:AttachUserPolicy",
"iam:DetachUserPolicy"
],
"Resource": "*",
"Condition": {
"ArnEquals": {
"iam:PolicyArn": [
"arn:aws:iam::*:policy/CodeStar_*"
]
}
}
},
{
"Sid": "ProjectRoles",
"Effect": "Allow",
"Action": [
"iam:CreatePolicy",
"iam:DeletePolicy",
"iam:CreatePolicyVersion",
"iam:DeletePolicyVersion",
"iam:ListEntitiesForPolicy",
"iam:ListPolicyVersions"
],
"Resource": [
"arn:aws:iam::*:policy/CodeStar_*"
]
},
{
"Sid": "InspectServiceRole",
"Effect": "Allow",
"Action": [
"iam:ListAttachedRolePolicies"
],
"Resource": [
"arn:aws:iam::*:role/aws-codestar-service-role"
]
}
]
}
Also see http://docs.aws.amazon.com/codestar/latest/userguide/access-permissions.html but as you may have guessed, it's relatively new and the docs don't cover your use case.
I believe the answer is that CodeStar appears to be inconsistent with the naming convention it uses to create roles in different situations. If when creating the role you provide a name with a prefix of CodeStar-[projectId]*
this will satisfy the IAM policy of the CodeStarWorker-[projectId]-CloudFormation role. i.e. include `RoleName: !Sub 'CodeStar-${ProjectId}-....'.
Further information When I encountered the same error I was also going to update the IAM policy and then noticed the permission boundary in the IAM policy of the CodeStarWorker-[projectId]-CloudFormation role. Compare the role in the error to the existing role:
Role in error: awscodestar-[projectId]-lambda-HelloWorldLambdaRole-ABCDEF123456
.
Role created by CodeStar example code: CodeStar-[projectId]-Execution
As an additional side note, this is confusing if you've come to CodeStar from using the SAM CLI, as with the CLI you can specify a lambda function without a role and SAM will create it for you, for example:
$ sam init --name test_sam
$ cat test_sam/template.yml
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello-world/
Handler: app.lambdaHandler
Runtime: nodejs8.10
Environment:
Variables:
PARAM1: VALUE
Events:
HelloWorld:
Type: Api
Properties:
Path: /hello
Method: get
However, in CodeStar this wouldn't work and it appears that you need to follow CodeStar's example and specify the function resource, as well as the role with the right name prefix! e.g.
Resources:
HelloWorld:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: python3.7
Role:
Fn::GetAtt:
- LambdaExecutionRole
- Arn
Events:
GetEvent:
Type: Api
Properties:
Path: /
Method: get
LambdaExecutionRole:
Description: Creating service role in IAM for AWS Lambda
Type: AWS::IAM::Role
Properties:
RoleName: !Sub 'CodeStar-${ProjectId}-Execution${Stage}'
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: [lambda.amazonaws.com]
Action: sts:AssumeRole
Path: /
ManagedPolicyArns:
- ....
来源:https://stackoverflow.com/questions/43591128/change-iam-role-for-a-lambda-in-a-cloudformation-template-in-a-codestar-project