I'm working on setting up my Java AWS lambda functions to be deployed via Codepipeline -> Cloudformation and am having some difficulty with Cloudformation. I've worked with Terraform before, so I understand the general concepts...
To clarify, my code is housed in a Codecommit repository and everything was setup by Codestar, so it created a Codepipeline with a single stage, two-step deployment (generate changeset, execute changeset).
For right now, I am just marking up the sample template.yml file that Codestar created in the repository, hence the HelloWorld references.
In addition to the template.yml file, I also have a buildspec.yml file for Codebuild, though the build process completes successfully.
Below is my template.yml cloudformation script. The ChangeSet step in the Codepipeline deployment stage completes successfully, however the ExecuteChangeset step fails, with "No reason provided" (super helpful). Clicking on the details link brings me to the Cloudformation page for the execute step which does not actually show any errors. It shows a few of the add/remove steps I would expect to see, though not all of the ones I would think would need to happen. If I click "Execute", it fails with the following error:
Error: Failed to execute change set: ChangeSet [arn:aws:cloudformation:us-east-1:XXXXXXXXXXXX:stack/awscodestar-test2-lambda/07e71ee0-6a73-11e7-bee5-50d5cd24fac6] cannot be executed in its current execution status of [EXECUTE_FAILED]
What am I doing wrong here? I don't have a good grasp of the Fn::GetAtt call, but I've tried that a few different ways with no joy.
**In addition to identifying what's going wrong, I have two questions:
Please explain what exactly I'm supposed to reference in the Fn::GetAtt function call? Is it the resource name I provide at the top of the resource I'm trying to call (e.g. GetHelloWorld)? Or an explicit name that's provided as a property of that resource (i.e. FunctionName)?
In the Lambda function declaration, I'm trying to setup the Event trigger in-line, which then needs to reference the Lambda function. Can I refer to the Lambda function resource from within the Event declaration that's nested within the Lambda function resource??
Below is my template.yml file.
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:
RoleForLambda:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service: "lambda.amazonaws.com"
Action: "sts:AssumeRole"
Policies:
- PolicyName: s3put
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action:
- 'logs:CreateLogGroup'
- 'logs:CreateLogStream'
- 'logs:PutLogEvents'
- 's3:PutObject'
Resource:
- 'arn:aws:logs:*:*:*'
- 'arn:aws:s3:*'
GetHelloWorld:
Type: AWS::Serverless::Function
Properties:
Handler: com.aws.codestar.projecttemplates.handler.HelloWorldHandler
Runtime: java8
Timeout: 60
MemorySize: 256
Role:
'Fn::GetAtt':
- RoleForLambda
- Arn
ScheduleRule:
Type: 'AWS::Events::Rule'
Properties:
Name: DownloadFiles
ScheduleExpression: 'cron(2,7,12,17,22,27,32,37,42,47,52,57 * * * ? *)'
State: ENABLED
Targets:
- Arn:
'Fn::GetAtt':
- GetHelloWorld
- Arn
Id: downloadFiles
LambdaInvokePermission:
Type: "AWS::Lambda::Permission"
Properties:
Action: lambda:InvokeFunction
FunctionName: GetHelloWorld
Principal: events.amazonaws.com
SourceAccount: AWS::XXXXXXXXXXXX
SourceArn:
- Arn:
'Fn::GetAtt':
- ScheduleRule
- Arn
In case anyone else gets to this with similar issues. Turns out, I had a few syntax errors and, I'm sure, other problems... Here is a working template.
AWSTemplateFormatVersion: 2010-09-09
Description: >-
This Lambda function does something
Parameters:
ProjectId:
Description: AWS CodeStar projectID used to associate new resources to team members
Type: String
Resources:
DownloadRole:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Sid: ''
Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: 'sts:AssumeRole'
Policies:
- PolicyName: PutS3Policy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- 'logs:CreateLogGroup'
- 'logs:CreateLogStream'
- 'logs:PutLogEvents'
- 's3:PutObject'
- 's3:PutObjectAcl'
- 's3:PutObjectTagging'
- 'sns:Publish'
Resource:
- 'arn:aws:logs:*:*:*'
- 'arn:aws:s3:::myBucket'
- 'arn:aws:s3:::myBucket/*'
- 'arn:aws:sns:us-east-1:xxxxxxxxxxxx:SNS_TOPIC'
Path: /
DownloadFunction:
Type: 'AWS::Lambda::Function'
Properties:
Handler: 'com.mycompany.download.LambdaFunction::lambdaHandler'
MemorySize: '256'
Description: A scheduled Lambda function
FunctionName: Download
Role: !GetAtt
- DownloadRole
- Arn
Runtime: java8
Timeout: '60'
DependsOn:
- DownloadRole
ScheduleRule:
Type: 'AWS::Events::Rule'
Properties:
Name: DownloadFiles
ScheduleExpression: 'cron(2,7,12,17,22,27,32,37,42,47,52,57 * * * ? *)'
State: ENABLED
Targets:
- Arn: !GetAtt
- DownloadFunction
- Arn
Id: DownloadFiles
DependsOn:
- DownloadFunction
LambdaInvokePermission:
Type: 'AWS::Lambda::Permission'
Properties:
FunctionName: !GetAtt
- DownloadFunction
- Arn
Action: 'lambda:InvokeFunction'
Principal: events.amazonaws.com
SourceArn: !GetAtt
- ScheduleRule
- Arn
DependsOn:
- DownloadFunction
- ScheduleRule
Maybe not exactly the same issue
This was our error message:
An error occurred (InvalidChangeSetStatus) when calling the ExecuteChangeSet operation: ChangeSet [arn:aws:cloudformation:....]
cannot be executed in its current execution status of [OBSOLETE]
And to resolve I simply reran the same Cloudformation script. Strange enough - this issue occurred in all environments (DEV, TETS, and PROD) and the same step for all 3 situations.
Related
I am trying to delete an aws lambda application, but the delete continuously fails with the following message:
"Role arn:aws:iam::070781698397:role/CloudFormationRole-demo-app-us-east-1 is invalid or cannot be assumed"
I previously deleted the above mentioned cloudformation role and the lambda function "helloFromLambda" (seen below). I have attempted to recreate the cloudformation role, hoping this would facilitate the deletion process (suggested in another post).
Here is my lambda function template:
AWSTemplateFormatVersion: 2010-09-09
Description: Start from scratch starter project
Parameters:
AppId:
Type: String
Resources:
helloFromLambdaFunction:
Type: 'AWS::Lambda::Function'
Properties:
Code:
S3Bucket: aws-us-east-1-070781698397-demo-app-pipe
S3Key: b42fa7cf7096fa092274e9524d6cadda
Description: A Lambda function that returns a static string.
Handler: src/handlers/hello-from-lambda.helloFromLambdaHandler
MemorySize: 128
Role: !GetAtt
- helloFromLambdaFunctionRole
- Arn
Runtime: nodejs16.x
Timeout: 60
Tags:
- Key: 'lambda:createdBy'
Value: SAM
helloFromLambdaFunctionRole:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Action:
- 'sts:AssumeRole'
Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
PermissionsBoundary: !Sub >-
arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/${AppId}-${AWS::Region}-PermissionsBoundary
Tags:
- Key: 'lambda:createdBy'
Value: SAM
I tried deleting through aws management console. I have tried deleting through the aws cli.
I'm trying to create a Batch setup in Cloudformation. I have in Resources an IAM Role:
SecretsAndS3AccessRole:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service: batch.amazonaws.com
Action: 'sts:AssumeRole'
- Effect: Allow
Principal:
Service: ec2.amazonaws.com
Action: 'sts:AssumeRole'
- Effect: Allow
Principal:
Service: ecs-tasks.amazonaws.com
Action: 'sts:AssumeRole'
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/SecretsManagerReadWrite'
- 'arn:aws:iam::aws:policy/AmazonS3FullAccess'
- 'arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy'
Then in my JobDefinition I have:
JobDefinition:
Type: 'AWS::Batch::JobDefinition'
Properties:
Type: container
ContainerProperties:
Image: public.ecr.aws/l0v4l2q2/rapidtide-cloud
Vcpus: 2
Memory: 2000
Command:
- /simple-test
Privileged: true
JobRoleArn: !Ref SecretsAndS3AccessRole
ExecutionRoleArn: !Ref SecretsAndS3AccessRole
Secrets:
- Name: MY_SECRET
ValueFrom: arn:aws:secretsmanager:us-east-1:123456789:secret:MYSECRET-zSQVSQ
RetryStrategy:
Attempts: 1
When I try to build the stack, I get:
An error occurred (ClientException) when calling the RegisterJobDefinition operation: Error executing request, Exception : executionRoleArn bothrefs-SecretsAndS3AccessRole-1INAOWFBH2SK2 is not an iam role arn
If I remove the ExecutionRoleArn line and the Secrets, the stack builds fine, which is to say that JobRoleArn is happy with a value of !Ref SecretsAndS3AccessRole. (But I need the secrets, and to use secrets you need an execution role.) And if I hardcode the ARN there, it works fine.
What is different about ExecutionRoleArn that it doesn't allow a !Ref? According to the documentation for JobDefinition/ContainerProperties, JobRoleArn and ExecutionRoleArn seem the same sort of object.
!Ref returns the logical ID of the resource, not the ARN.
You need to use !GetAtt.
This should work:
ExecutionRoleArn: !GetAtt SecretsAndS3AccessRole.Arn
This is my cft for lambda, I upload the jar file to s3 and then upload to lambda through s3, I completed the LambdaRole and LambdaFunction section, in the permission section, what should be the SourceArn? I went through the lambda official doc but didn't find any example.
Also, can anyone take a look to see if this cft is correct or not? Thanks!
ConfigurationLambdaRole:
Type: "AWS::IAM::Role"
Properties:
RoleName: 'configuration-sqs-lambda'
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
- events.amazonaws.com
- s3.amazonaws.com
Action:
- sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSQSFullAccess
- arn:aws:iam::aws:policy/CloudWatchLogsFullAccess
ConfigurationLambdaFunction:
Type: AWS::Lambda::Function
Properties:
Description: 'configuration service with lambda'
FunctionName: 'configuration-lambda'
Handler: com.lambda.handler.EventHandler::handleRequest
Runtime: Java 11
MemorySize: 128
Timeout: 120
Code:
S3Bucket: configurationlambda
S3Key: lambda-service-1.0.0-SNAPSHOT.jar
Role: !GetAtt ConfiguratioLambdaRole.Arn
ConfigurationLambdaInvokePermission:
Type: AWS::Lambda::Permission
Properties:
FunctionName:
Fn::GetAtt:
- ConfigurationLambdaFunction
- Arn
Action: 'lambda:InvokeFunction'
Principal: s3.amazonaws.com
SourceArn: ''
You are creating a Role to run your lambda, a lambda function, and permissions for something to invoke that lambda. The SourceArn is the thing that will invoke the lambda. So in your case it sounds like you want an S3 bucket to invoke the lambda, so the SourceArn would be the ARN of the S3 bucket.
This tutorial relates to what you are doing--specifically step 8 under the "Create the Lambda function" section.
Your CF template generally looks correct. The only thing I see that will be assuming this role is lambda.amazonaws.com, so the role may not need to list the following in the AssumeRolePolicyDocument section:
- events.amazonaws.com
- s3.amazonaws.com
Also see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-permission.html
I am trying to create a code pipeline using cloud formation. My cloudformation template gets created successfully. However, the pipeline created gets stuck at the source stage itself saying the provided role does not have permission to access codecommit/s3.
The problem is that I have already given codecommit:* and s3:* policies to the pipeline role. Also I am using user permissions while running the cloud formation template and the user has admin permissions.
When I rerun the pipeline from the dashboard the pipeline runs successfully. Why is it getting failed when run automatically on getting created?
Following is the code where I am facing the problem:
Resources:
CodePipelineRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
Effect: Allow
Principal:
Service:
- codepipeline.amazonaws.com
- events.amazonaws.com
Action: sts:AssumeRole
Path: /
CodePipelinePolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: CodePipelinePolicy
PolicyDocument:
Statement:
- Action:
- iam:PassRole
Resource: "*"
Effect: Allow
Condition:
StringEqualsIfExists:
iam:PassedToService:
- cloudformation.amazonaws.com
- elasticbeanstalk.amazonaws.com
- ec2.amazonaws.com
- ecs-tasks.amazonaws.com
- Action:
- s3:*
- cloudwatch:*
- codecommit:*
- opsworks:*
- states:*
- appconfig:*
Resource: "*"
Effect: Allow
Version: '2012-10-17'
Roles:
- Ref: CodePipelineRole
Pipeline:
Type: AWS::CodePipeline::Pipeline
Properties:
ArtifactStore:
Type: S3
Location: !Ref S3Bucket
Name: SamplePipeline
RoleArn: !GetAtt [CodePipelineRole,Arn]
Stages:
- Name: Source
Actions:
- InputArtifacts: []
Name: Template
Region: !Ref AWS::Region
ActionTypeId:
Category: Source
Owner: AWS
Version: '1'
Provider: S3
OutputArtifacts:
- Name: template
Configuration:
S3Bucket: !Ref S3Bucket
PollForSourceChanges: 'false'
S3ObjectKey: !Sub ${NameOfArtifact}.zip
RunOrder: 1
....
Currently my serverless.yml file looks like this:
service: bbb
provider:
name: aws
runtime: go1.x
stage: dev
package:
exclude:
- ./**
include:
- ./bin/**
functions:
ccc:
handler: bin/executable
name: my1minutelambda
role:
'Fn::GetAtt':
- mylambdaexecutionrole
- Arn
resources:
Resources:
mylambdaexecutionrole:
Type: AWS::IAM::Role
Properties:
RoleName: my-basiclambdaexec-role
Description: This is my basiclambdaexecution role
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"
myminschedulerevent:
Type: AWS::Events::Rule
Properties:
Description: This is my 1 minute rate scheduler.
Name: my-1-min-trigger-event-scheduler
ScheduleExpression: rate(1 hour)
Targets:
-
Arn: "arn:aws:lambda:us-east-1:111111111111:function:my1minutelambda" #update your a/c Id
Id: "TargetFunctionV1"
command used to deploy: sls deploy
After deployment finished, I can see on aws management console that all my resources got created.
BUT I am not able to see cloudwatch trigger extablishment for my lambda function.
See below screenshot:
CloudWatch Event Rule created successfully. (Target section pointing to my lambda function)
Trigger link not established for my lambda:
Please let me know what i am missing here. Thank you.
Update#1:
After adding following lines (as suggested by Marcin), I am able to see "CloudWatch event".
EventsPermission:
Type: AWS::Lambda::Permission
Properties:
FunctionName: my1minutelambda
Action: lambda:InvokeFunction
Principal: events.amazonaws.com
SourceAccount: !Ref 'AWS::AccountId'
SourceArn: !GetAtt myminschedulerevent.Arn
But, I can't see CloudWatch logs!! So, I can't findout if my lambda function is executing. Please see image below:
I tried to replicate the issue using serverless framework.
To do so I added the following AWS::Lambda::Permission to the end of your template:
EventsPermission:
Type: AWS::Lambda::Permission
Properties:
FunctionName: dsfgsdfg # <-- REPLACE this with your function name my1minutelambda
Action: lambda:InvokeFunction
Principal: events.amazonaws.com
SourceArn: !GetAtt myminschedulrevent.Arn
After adding the permissions, the console showed the trigger as expected:
If all you are trying to do is get a Lambda function to execute on a schedule, the Serverless Framework already includes an event type expressly for that purpose:
functions:
crawl:
handler: crawl
events:
- schedule: rate(2 hours)
- schedule: cron(0 12 * * ? *)
It will set everything up for you with no need to add additional CloudFormation. You can find the documentation here: https://www.serverless.com/framework/docs/providers/aws/events/schedule/#schedule/
ScheduledRule:
Type: AWS::Events::Rule
Properties:
Name: "SphEvent"
Description: "ScheduledRule"
ScheduleExpression: "rate(1 hour)"
State: "ENABLED"
Targets:
- Arn: !Sub "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:lambda-name"
Id: "TargetFunctionV1"
PermissionForEventsToInvokeLambda:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !Ref "LambdaFunction"
Action: "lambda:InvokeFunction"
Principal: "events.amazonaws.com"
SourceArn:
Fn::GetAtt:
- "ScheduledRule"
- "Arn"