AWS Region issue while deploying cloudformation template - amazon-web-services

I have created a CloudFormation template where I am deploying a Lambda function which will take code from S3 bucket from a zipped file. The bucket is in us-west-2 region.
My issue here is that the template deployment is failing to create Lambda function if the user deploys it in another region apart from us-west-2 in another account since it's not able to find the bucket in the above mentioned region.
Also, i cannot directly add the code in the template since the code has some dependency files.
Sharing the snippet of the code. Any suggestion is highly appreciated.
Thanks
Resources:
DMARCFunction:
Type: AWS::Lambda::Function
Properties:
Code:
S3Bucket: lambda-code-bucket
S3Key: Lambda.zip
Runtime: python3.8
Role: !GetAtt LambdaRole.Arn
Handler: lambda_function.lambda_handler
Timeout: 15
TracingConfig:
Mode: Active

Its not CloudFormation issue. That's how lambda works. the ZIP and the function must be in same region. You have to replicate your ZIP to all regions and accounts were you want to create your function.

Related

How do refer an existing s3 bucket in my CFN template so that my lambda can use the bucket?

I have a CFN template where in I am creating 2 s3 buckets for the image resizing using CloudFront.
the issue is that I want to use an already existing bucket from s3 for these functions.
but I get an error that s3 already exists when I provide the resource ARN and other data.
how can I resolve this?
I tried giving the details ARN name etc and tried deploying but it doesn't work
Something like this would help you:
AWSTemplateFormatVersion: '2010-09-09'
Description: 'CFN template example for referencing existing S3 bucket to lambda'
Parameters:
myS3Bucket:
Type: String
Description: Provide the S3 bucket you want to referece into your lambda.
Resources:
MyLambdaFunction:
Type: AWS::Lambda::Function
Properties:
Description: A lambda function
Handler: index.handler
Runtime: python3.7
Environment:
Variables:
S3_BUCKET: !Ref myS3Bucket

Why S3 bucket is not getting created though it is mentioned in SAM template?

I am trying to create a lambda function with function code in the S3 bucket. Below is my template.
This template creates the lambda but, not the S3 bucket mentioned. I am looking for assistance to create S3 bucket through this template.
Resources:
ProducerLambda:
Type: 'AWS::Serverless::Function'
Properties:
FunctionName: !Sub '${ApplicationId}-${env}-Producer-Lambda-${AWS::AccountId}-${AWS::Region}'
Handler: index.handler
Runtime: nodejs14.x
CodeUri:
Bucket: s3bucket
Key: s3bucketref.zip
Role: 'arn:aws:iam::${AWS::AccountId}:role/Producer-lambda-trigger-role'
VpcConfig:
SecurityGroupIds: !Ref SecurityGroup
SubnetIds: !Ref VPCSubnetId
Environment:
Variables:
Region: !Sub '${AWS::Region}'
CodeUri is used to specify the path to the function's code - this can be an Amazon S3 URI, the path to a local folder, or a FunctionCode object.
They are not used to create S3 buckets.
If the packaged function does not exist at s3bucket/s3bucketref.zip then you will have to create the bucket yourself and upload the package.
Or alternatively, using sam build will build the Lambda for you & sam deploy will then automatically create an S3 bucket for you:
Deploying AWS Lambda functions through AWS CloudFormation requires an Amazon Simple Storage Service (Amazon S3) bucket for the Lambda deployment package. The AWS SAM CLI creates and manages this Amazon S3 bucket for you.
The latter is much simpler to manage.

How to add a resource based policy to a lambda using AWS SAM

I want to create a deployment script for some lambda functions using AWS SAM. Two of those functions will be deployed into one account(account A) but will be triggered by an s3 bucket object creation event in a second account(account B). From what I know the only way to do this is by using adding a resource based policy to my lambda. But I don't know how to do that in AWS SAM. My current yaml file looks like this.
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
deploy-test-s3-triggered-lambda
Parameters:
AppBucketName:
Type: String
Description: "REQUIRED: Unique S3 bucket name to use for the app."
Resources:
S3TriggeredLambda:
Type: AWS::Serverless::Function
Properties:
Role: arn:aws:iam::************:role/lambda-s3-role
Handler: src/handlers/s3-triggered-lambda.invokeAPI
CodeUri: src/handlers/s3-triggered-lambda.js.zip
Runtime: nodejs10.x
MemorySize: 128
Timeout: 60
Policies:
S3ReadPolicy:
BucketName: !Ref AppBucketName
Events:
S3NewObjectEvent:
Type: S3
Properties:
Bucket: !Ref AppBucket
Events: s3:ObjectCreated:*
AppBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref AppBucketName
What do I need to add to this yaml file in order to tie a resource based policy that allows for cross account access to my lambda function?
This can be done achieved with the help of AWS::Lambda::Permission using aws_cdk.aws_lambda.CfnPermission.
For example, to allow your lambda to be called from a role in another account, add the following to your CDK:
from aws_cdk import aws_lambda
aws_lambda.CfnPermission(
scope,
"CrossAccountInvocationPermission",
action="lambda:InvokeFunction",
function_name="FunctionName",
principal="arn:aws:iam::111111111111:role/rolename",
)
If your bucket and your Lambda function exist in separate accounts I don't know if it's possible to modify both of them from SAM / a single CloudFormation template.
Don't think cross account s3 event is possible with SAM, may need to go back to CFN.

AWS SAM Template: Issue mapping S3 events to Lambda

I've followed the AWS SAM documentation for hands-on learning experience and have reached this particular section: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-function-s3.html
Above page in the documentation explains how to map the S3 events to any resource and I've done something similar on my local machine. My local template below.
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
CreateThumbnail:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello_world/
Handler: app.lambda_handler
Runtime: python3.6
Timeout: 60
Policies: AWSLambdaExecute
Events:
CreateThumbnailEvent:
Type: S3
Properties:
Bucket: !Ref testBucket
Events: s3:ObjectCreated:*
testBucket:
Type: AWS::S3::Bucket
Now, when I build and deploy above SAM template, while a new S3 bucket is getting created, the 'object creation' event is not mapped to the Lambda function created. PSB screenshot.
I haven't found any articles or blogs on this error (probably, I'm doing a silly mistake here)
Please help.
Thanks.
I realized that for some reason, the AWS Lambda console is not showing the trigger event but the mapping is successful. I've also validated by uploading sample image to the bucket which triggered the lambda.
The event mapping can be seen in the properties section of the S3 bucket created.
S3 test bucket created -> Properties -> Events
You can add a AWS::Lambda::Permission to your Resources as described in this AWS SAM Github issue
LambdaInvokePermission:
Type: 'AWS::Lambda::Permission'
Properties:
FunctionName: !GetAtt MyFunction.Arn
Action: 'lambda:InvokeFunction'
Principal: 's3.amazonaws.com'
SourceAccount: !Sub ${AWS::AccountId}
SourceArn: !GetAtt MyBucket.Arn
First create bucket where you plan to save packaged code
aws s3 mb s3://youtbucketname
After sam build
go for
sam package --template-file template.yaml --s3-bucket <yourbucketname>

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