Serverless / AWS Lambda - Create the triggers for the published lambda versions - amazon-web-services

I'm using the Serverless framework to deploy my functions on the AWS Lambda
I'm trying to create a trigger automatically for each version of my Lambda functions published.
When I deploy my serverless app, the Lambda function and the triggers are created (in this case my AWS IOT trigger), as we can see on the following image:
But for my published version of the lambda function the trigger doesn't exist, only the resources:
I don't want to create new triggers every time I publish a new lambda version.
So, there is any way to create the triggers for my versioned lambdas too? And if is possible, disable the old ones using the Serverless framework?
my serverless.yml file:
service: serverless-lambdas
provider:
name: aws
runtime: nodejs6.10
iamRoleStatements:
- Effect: "Allow"
Action:
- "ses:*"
- "iot:*"
Resource:
- "*"
functions:
function1:
name: "function1"
handler: function1/handler.function1
events:
- iot:
name: "iotEvent1"
sql: "SELECT EXAMPLE"
sqlVersion: "2016-03-23"
enabled: true

UPDATE
I got a similar problem when I was trying to create triggers programmatically using my own AWS Lambda.
I got stuck on this when I saw that the problem was with my trigger that which had no permission to invoke the published Lambda function. So I needed to add the permission for the trigger first with the method add-permission. (This is not clearly written on the AWS docs :/).
So, before I added the the trigger on the Lambda, I used the following method (in node.js):
const addPermission = (ruleName) => {
const thingArn = `arn:aws:iot:${IOT_REGION}:${SOURCE_ACCOUNT}:rule/${ruleName}`;
const params = {
Action: "lambda:InvokeFunction",
FunctionName: LAMBDA_NAME,
Principal: "iot.amazonaws.com",
SourceAccount: SOURCE_ACCOUNT,
SourceArn: thingArn,
StatementId: `iot-sd-${Math.random().toString(36).substring(2) + Date.now().toString(36)}`
};
return new Promise((resolve, reject) => {
lambda.addPermission(params).promise().then(result => {
resolve(result)
}).catch(err => reject(err))
});
};
I tested the same function for the Serverless framework, and Shazam! my triggers were published! We can do something like this for now while the Serverless code is not updated.
In this way, this problem will need to be solved on the Serverless source-code and I will try to do it ASAP.
From what I checked this is the default behavior for the AWS Lambda functions, so there is no issue with the Serverless framework.
Every time I publish a Lambda function, there is no way to create the trigger events automatically.
For further information, we can read the documentation of Versioning aliases.

Related

How to override default AWS EventBridge event name when deploying with Serverless Framework?

I'm deploying a Lambda function via Serverless Framework, and the function is going to have multiple EventBridge events (schedules) tied to it. For this reason, I would like to create a custom name for each schedule to easily differentiate them from each other. The problem is that adding in a "name" propery to the event objects doesn't seem to be doing anything because the events are still being deployed with default names.
I have setup my Serverless file exactly how they have it setup in the documentation:
functions:
myFunction:
handler: index.handler
events:
- eventBridge:
name: event-bridge-custom-name
schedule: rate(10 minutes)
input:
key1: value1
Link to documentation.
Instead of my EventBridge rule being deployed as "event-bridge-custom-name", it's deployed as "myapp-rule-1", "myapp-rule-2", etc.

How can I specify apigateway's role to give permission to invoke a lambda?

I am using AWS apigateway to trigger a lambda function. I deployed them from serverless framework, the configuration looks like:
handler:
handler: src/index.handler
name: handler
tracing: true
role: updateRole
events:
- http:
path: /contact/{id}
method: patch
integration: lambda
request:
parameters:
paths:
id: true
after deploy, it works perfect. But what I don't understand is how I can find out where the iam role/policy defined for this API integration?
When open AWS console, it shows me the right configuration in the "Integration Request" tab:
But I can't find anywhere it specifies the IAM role to this integration. How can I find it or update it?
Permissions to execute a function from API, are set using resource-based policies for lambda, not IAM role. In lambda console they are listed as:

how to develop a lambda on SAM but deploy without api gateway

I am using SAM to develop a lambda that is triggered by SNS.
When I am using SAM, it seems I get API GATEWAY associated to the Lambda when I deploy.
It is nice in dev, but not in prod.
How would I develop a Lambda without deploying it attached to an API GATEWAY?
"I was not aware of Lambda runtime API"
Using the Lambda runtime API and the AWS SDKs, as a developer, you can build more flexible Lambda functions with the exact functionality that you want.
For example, you can build Lambda functions that can invoke multiple AWS Services to perform a given use case. For example, from a Lambda function, I want to detect PPE information in images within an Amazon S3 bucket, store the results in an Amazon DynamoDB table, and use the SES service to email the results.
Here are a few end to end tutorials.
For example - here are two JavaScript examples:
Creating and using Lambda functions
Creating scheduled events to execute AWS Lambda functions
Here are some Java runtime examples:
Creating an AWS Lambda function that detects images with Personal Protective Equipment
Creating an Amazon Web Services Lambda function that tags digital assets located in Amazon S3 buckets
Creating an ETL workflow by using AWS Step Functions and the AWS SDK for Java
UPDATE
Once you test your code in an IDE, deploy it and test it from the Lambda console. Once it is successfully invoked, you will see a message like this:
Another option I found, this time within SAM is define the function with a different Event source.
The Lambda will be exposed if it's event source is defined as Api
You can define it as many other things (S3,Sns,Sqs etc)
Here is an example of a function triggered by and http event via api gateway, and the other one, by Sns. The config for SNS is not complete, Check this link for full details https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md
in template.yaml Notice the Events section of each Lambda definition.
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
CodeUri: hello-world/
Handler: app.lambdaHandler
Runtime: nodejs14.x
Events:
HelloWorld:
Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
Properties:
Path: /hello
Method: get
BooBooFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
CodeUri: booboo/
Handler: app.lambdaHandler
Runtime: nodejs14.x
Events:
BooBoo:
Type: Sns # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api

Lambda#Edge through Go SDK

I am trying to associate a Lambda#Edge Function using the AWS Go SDK.
Creating the Function by hand in the console and assigning it to the Cloudfront distro using the SDK => works.
Creating the Function (using the same IAM role from 1.) in the code w/o assigning to cloudfront => works.
Assigning the created function from 2. by hand in the console => fails.
Assigning the created function from 2. via the SDK => fails.
Deploying the created function from 2. by hand in the lambda console (Actions => deploy to lambda#edge) => works. => after this the function can be assigned by hand and by code w/o problems...
The error in 3. and 4. is the same:
InvalidLambdaFunctionAssociation: Lambda#Edge cannot retrieve the specified Lambda function. Update the IAM policy to add permission: lambda:GetFunction for resource: arn:aws:lambda:us-east-1:123456789:function:example:1 and try again.
What confuses me is that I am reusing the same role that was created during 1.
This is how I create the function by code:
lam := lambda.New(session)
lam.CreateFunction(&lambda.CreateFunctionInput{
FunctionName: aws.String("example"),
Handler: aws.String("index.handler"),
Runtime: aws.String("nodejs12.x"),
Role: aws.String("arn:aws:iam::123456:role/service-role/existing-role"),
Code: &lambda.FunctionCode{
S3Bucket: aws.String("bucket-xyz"),
S3Key: aws.String("source.zip"),
},
}) // works w/o issues
lam.AddPermission(&lambda.AddPermissionInput{
FunctionName: aws.String("example"),
StatementId: aws.String("AllowExecutionFromCloudFront"),
SourceArn: aws.String("arn:aws:cloudfront::12333456:distribution/CDNID1234"),
Principal: aws.String("edgelambda.amazonaws.com"),
Action: aws.String("lambda:GetFunction"),
}) // also works w/o error
// assigning the created lambda function would now fail
using
go 1.13
github.com/aws/aws-sdk-go v1.31.8
I found the issue.
The error has absolutely nothing to do with the actual problem. Very misleading error if you ask me.
All that's been missing is a published version of the lambda function at hand.
To achieve that using the Go SDK you have to do:
lam := lambda.New(session)
lam.PublishVersion(&lambda.PublishVersionInput{
FunctionName: aws.String("example"),
Description: aws.String("Dont forget to publish ;)"),
})
using the CLI you would want to do the following:
aws lambda publish-version --function-name example --description "Dont forget to publish"
It actually makes sense that you cannot use a function that hasn't been published. However the error from AWS didn't really help there.
Hopefully this can help anybody!
This error occurred for me because the IAM user didn't have adequate permissions to access versions of the Lambda function.
Before (only one resource specifying the Lambda function):
arn:aws:lambda:<region>:*:function:<function_name>
After (additional wildcard resource for versions of the Lambda function):
arn:aws:lambda:<region>:*:function:<function_name>
arn:aws:lambda:<region>:*:function:<function_name>:*

How to add triggers for a AWS Lambda function created using a CloudFormation template?

I am trying to create a lambda function from a CloudFormation template based on this example:
http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/quickref-lambda.html
As can be seen from this link:
http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html
there is no way to add a trigger for the lambda function (like a S3 upload trigger).
Is there a workaround to specify the trigger while writing the template?
You can use cloudwatch rule to trigger your lambda function :
AWSTemplateFormatVersion: '2010-09-09'
Resources:
MyCloudWatchRule:
Type: "AWS::Events::Rule"
Properties:
Description: "Rule to trigger lambda"
Name: "MyCloudWatchRule"
EventPattern: <Provide Valid JSON Event pattern>
State: "ENABLED"
Targets:
- Arn: "arn:aws:lambda:us-west-2:12345678:function:MyLambdaFunction"
Id: "1234567-acvd-awse-kllpk-123456789"
Ref :
https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/CloudWatchEventsandEventPatterns.html
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-events-rule.html#aws-resource-events-rule-syntax
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-rule-target.html
It's been a while so I imagine you've solved the problem, but I'll put in my 2 cents to help others.
It's best to use SAM (Serverless Application Model) for this kind of things. So use AWS::Serverless::Function instead of AWS::Lambda::Function
https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html
In there, you can specify an EventSource which accepts the following possible values:
S3
SNS
Kinesis
DynamoDB
SQS
Api
Schedule
CloudWatchEvent
CloudWatchLogs
IoTRule
AlexaSkill
Cognito
HttpApi
SAM does the rest of the work. Follow this guide for the rest of the details:
https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-deploying.html
Nowadays, this issue is fixed by Amazon:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-events-rule.html#aws-resource-events-rule--examples
Just create Lambda permissions like in the example.
Lambda function can be triggered by several AWS resources such as S3, SNS, SQS, API, etc. Checkout for the full list at AWS docs
I suggest you use Altostra Designer, which let you create and configure Lambda Function super quick and also choose what will trigger it.
You need to add a NotificationConfiguration to the S3 bucket definition. However, this will lead to a circular dependency where the S3 bucket refers to the Lambda function and the Lambda function refers to the S3 bucket.
To avoid this circular dependency, create all resources (including the S3 bucket and the Lambda function) without specifying the notification configuration. Then, after you have created your stack, update the template with a notification configuration and then update the stack.
Here is a SAM based YAML example for CloudWatch log group trigger
lambdaFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri:
Bucket: someBucket
Key: someKey
Description: someDescription
Handler: function.lambda_handler
MemorySize:
Ref: MemorySize
Runtime: python3.7
Role: !GetAtt 'iamRole.Arn'
Timeout:
Ref: Timeout
Events:
NRSubscription0:
Type: CloudWatchLogs
Properties:
LogGroupName: 'someLogGroupName'
FilterPattern: "" #Match everything
For S3 example event see https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-function-s3.html