I am trying to allow cloudwatch to execute a lambda function in a serverless.yml. I can do this via the CLI. How can I do this within a serverless.yml?
CLI command from here:
aws lambda add-permission --function-name XXX --statement-id MyId --action 'lambda:InvokeFunction' --principal events.amazonaws.com --source-arn arn:aws:events:us-east-1:1232132323:rule/XXXX
I tried from here which immediately gave deployment errors:
functions:
generateFile:
handler: api/handler.generateFile
tags:
LiveOrTest: test
# to allow cloudwatch to invoke lambdas
resources:
Resources:
cleanLambdaPermission:
Type: AWS::Lambda::Permission
Properties:
FunctionName:
"Fn::GetAtt": [cleanLambdaFunction, Arn]
Action: "lambda:InvokeFunction"
Principal: "events.amazonaws.com"
SourceArn: "*"
The only apparent issue in your AWS::Lambda::Permission is incorrect ARN:
SourceArn: "*"
You can't have * as ARN, instead it should be:
SourceArn: "arn:aws:events:us-east-1:1232132323:rule/XXXX"
Alternatively, you can just remove the entire SourceArn property.
Related
Within AWS I've created a CloudTrail which is then filtered by an Eventbridge Rule to only look for certain events within CloudTrail that correspond to resources being created on AWS. Reason being is that I've created some code for Lambda that will automatically tag resources dependent on events passed to it from Eventbridge. When I manually connect eventbridge rule & lambda together it all works fine. However, when I deploy my stack using Cloudformation my Lambda doesn't show Eventbridge as an eventsource/trigger for the function and I don't know why. Below is my Cloudformation template alongside what is shown on AWS Lambda vs what I expect to be seen.
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
# ---------------------------------------------------------------------------- #
# Input parameters #
# ---------------------------------------------------------------------------- #
Parameters:
ProjectName:
Type: String
Default: 'AutoTagger'
Description: ""
# ---------------------------------------------------------------------------- #
# Resources #
# ---------------------------------------------------------------------------- #
Resources:
AutoTaggerLambda:
Type: AWS::Serverless::Function
Name: auto-tagger-lambda
Properties:
CodeUri: release/archive.zip
Handler: auto-tagger/main.lambda_handler
Runtime: python3.9
Policies: [AWSLambda_FullAccess]
MemorySize: 128
Timeout: 30
Tags:
- Key: "project_name"
Value: !Ref ProjectName
TagEvents:
Type: "AWS::Events::Rule"
Properties:
Description: "Rule to trigger lambda"
Name: "TagEvents"
EventPattern: {
"detail-type": ["AWS API Call via CloudTrail"],
"detail": {
"eventSource": ["ec2.amazonaws.com", "rds.amazonaws.com", "lambda.amazonaws.com", "s3.amazonaws.com", "dynamodb.amazonaws.com", "elasticfilesystem.amazonaws.com"],
"eventName": ["CreateVolume", "RunInstances", "CreateImage", "CreateSnapshot", "CreateDBInstance", "CreateFunction20150331", "UpdateFunctionConfiguration20150331v2", "UpdateFunctionCode20150331v2", "CreateBucket", "CreateTable", "CreateMountTarget"]
}
}
State: "ENABLED"
Targets:
- Arn: !GetAtt AutoTaggerLambda.Arn
Id: "TagEventsTargetLambda"
Do I need to add an event to the lambda also? I'm a little confused.
You are missing permissions. An AWS::Lambda::Permission resource gives your EventBridge rule permission to invoke the Lambda. It is added to the Lambda's resource-based policy.
PermissionForEventsToInvokeLambda:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !GetAtt AutoTaggerLambda.Arn
Action: 'lambda:InvokeFunction'
Principal: 'events.amazonaws.com'
SourceArn: !GetAtt TagEvents.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 an AWS Eventbridge rule with a Lambda function as a target. I can add the rule and target fine but when I try to set the lambda permissions via RoleArn the Cloudformation stack deployment fails with:
RoleArn is not supported for target arn:aws:lambda:us-east-1:1234567890:function:contacts-lambda-consume-new-customer. (Service: AmazonCloudWatchEvents; Status Code: 400; Error Code: ValidationException; Request ID: xxxxx-ec5d-45e8-b45d-xxxxxx; Proxy: null)
Here is my Cloudformation stack code:
EventRuleNewCustomer:
Type: AWS::Events::Rule
Properties:
Name: new-customer
EventBusName: myEventBus
# RoleArn: !Join ["", ["arn:aws:iam::",!Ref "AWS::AccountId", ":role/my-role"] ] #no error but doesn't add the permissions
Description: "New customer event rule"
EventPattern:
detail-type:
- "NewCustomer"
State: "ENABLED"
Targets:
-
Arn: !Join ["", ["arn:aws:lambda:" ,!Ref "AWS::Region", ":", !Ref "AWS::AccountId", ":function:contacts-lambda-consume-new-customer"] ]
Id: "NewCustomer"
RoleArn: !Join ["", ["arn:aws:iam::",!Ref "AWS::AccountId", ":role/my-role"] ]
I have tried setting a RoleArn on the rule itself which doesn't give an error when the stack is created but also doesn't add the necessary permissions to execute the Lambda.
The work-around I am using is to edit the lambda target in the AWS Eventbridge console. This seems to do some behind the scenes magic to add the correct permissions for Eventbridge to be able to execute the lambda
Any ideas gratefully appreciated.
This seems to do some behind the scenes magic to add the correct permissions for Eventbridge to be able to execute the lambda
In case of lambda, the permissions are set using Lambda's resource-based policy.
Thus you should use AWS::Lambda::Permission in CloudFormation to allow EventBridge to invoke your function, rather than using RoleArn.
So your permissions would be something as the following (just an example):
EventBridgeLambdaPermission:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !GetAtt function.Arn
Action: lambda:InvokeFunction
Principal: events.amazonaws.com
SourceArn: !GetAtt EventRuleNewCustomer.Arn
I've got an app that runs on Lambda and is accessible through APIGateway.
In my SAM template, I've set it up so that APIGateway can invoke my function.
ConfigLambdaPermission:
Type: "AWS::Lambda::Permission"
DependsOn:
- MyFunction
Properties:
Action: lambda:InvokeFunction
FunctionName: !Ref MyFunction
Principal: apigateway.amazonaws.com
But now I need the app to call its own function recursively. I thought that I could just append a new ConfigLambdaPermission to my existing one like this.
ConfigLambdaPermission:
Type: "AWS::Lambda::Permission"
DependsOn:
- MyFunction
Properties:
Action: lambda:InvokeFunction
FunctionName: !Ref MyFunction
Principal: apigateway.amazonaws.com
ConfigLambdaPermission:
Type: "AWS::Lambda::Permission"
DependsOn:
- MyFunction
Properties:
Action: lambda:InvokeFunction
FunctionName: !Ref MyFunction
Principal: lambda.amazonaws.com
However, when the function tries to call itself, it throws the following error:
2019-01-27 14:27:56 - Aws::Lambda::Errors::AccessDeniedException -
User: arn:aws:sts::666666666666:assumed-role/my-app-MyFunction-166U166U166U1/my-app-MyFunction-1DJIJCDO1DJIJ
is not authorized to perform: lambda:InvokeFunction on resource:
arn:aws:lambda:us-west-2:666666666666:function:my-app-MyFunction-1DJIJCDO1DJIJ:
I'm not sure if I added the privileges incorrectly or whether there some other step I need to do to inform AWS that the privileges have changed.
Any idea how to correctly allow this lambda function to call itself?
The Principal in this case is going to be the IAM role that the Lambda itself runs under, which is as follows (replace aws-account-id and role-name as appropriate):
Principal: arn:aws:iam::aws-account-id:role/role-name
I am having some trouble writing the cloudformation script for cloudwatch event trigger to kick off my lambda script, I know I can do it through the console but my requirement is that I need to provision everything in cloudformation. I followed the documentation and it still haven't worked for me and I kept getting the error:
Template contains errors.: Invalid template property or properties
[rPermissionForEventsToInvokeLambda, rLambdaScheduledRule]
can someone point out what is the issue with this part of my cloudformation script? I followed the document almost to the letter and still having error, even the example in the documentation have the same error when I tried to validate it. my cloudformation code is below, any help is appreciated!
rLambdaScheduledRule:
Type: AWS::Events::Rule
Properties:
ScheduleExpression: rate(1 hour)
State: ENABLED
Targets:
Ref:
Fn::ImportValue:
Fn::Sub: rUploadLambda
Action: lambda:InvokeFunction
rPermissionForEventsToInvokeLambda:
Type: AWS::Lambda::Permission
Properties:
FunctionName:
Ref:
Fn::ImportValue:
Fn::Sub: rUploadLambda
Action: lambda:InvokeFunction
Principal: events.amazonaws.com
SourceArn:
Fn::GetAtt:
- rLambdaScheduledRule
- Arn
1) You must export the Lambda function ARN in the CloudFormation template in which you create the lambda function. You need to pass the Lambda function ARN as input to the cloudwatch event (The AWS::Events::Rule Targets attribute requires a resource ARN).
See a sample script below:
Resources:
# Create Controlled Lambda Function
myLambda:
Type: "AWS::Lambda::Function"
Properties:
Code:
S3Bucket: "lambda-bucket"
S3Key: "myhandler.zip"
Description: "Lambda handler"
FunctionName: "myhandler"
Handler: myhandler.myhandler
MemorySize: 128
Role: "arn:aws:iam::xxxxxxxxxxx:role/myLambdaExecutionRole-NC7FA7TUSZ5B"
Runtime: "python3.6"
Timeout: 10
# Output of the cf template
Outputs:
myLambdaArn:
Description: Arn of the my_lambda_function
Value: !GetAtt myLambda.Arn
Export:
Name: !Sub "${AWS::StackName}-LambdaArn"
2) When you create the CloudWatch Event, you need to pass the ARN of the lambda function created in Step1 as the Target.
See a sample script below:
Resources:
# Cloudwatch event to trigger lambda periodically
rLambdaScheduledRule:
Type: "AWS::Events::Rule"
Properties:
Description: "CloudWatch Event to trigger lambda fn"
ScheduleExpression: "rate(1 hour)"
State: "ENABLED"
Targets:
-
Arn:
Fn::ImportValue:
!Sub "${NetworkStackName}-LambdaArn"
Id: "targetevent_v1"
PermissionForEventsToInvokeLambda:
Type: "AWS::Lambda::Permission"
Properties:
FunctionName:
Fn::ImportValue:
!Sub "${NetworkStackName}-LambdaArn"
Action: "lambda:InvokeFunction"
Principal: "events.amazonaws.com"
SourceArn:
Fn::GetAtt:
- rLambdaScheduledRule
- Arn
The value of ${NetworkStackName} should be the StackName from Step1.
Some of the issues you need to correct in your template:
correct the Targets property of resource rLambdaScheduledRule.
remove Action property from resource rLambdaScheduledRule.
correct the FunctionName property of resource rPermissionForEventsToInvokeLambda.
Keeping above sample as reference, correct your template and try again.