Enable Lambda function to an S3 bucket using cloudformation

匿名 (未验证) 提交于 2019-12-03 02:47:02

问题:

We are creating an S3 bucket using a CloudFormation template. I would like to associate (Add an event to S3 bucket) a Lambda function whenever a file is added to the S3 bucket.

How is it possible through CloudFormation templates. What are the properties which needs to be used in CloudFormation.

回答1:

Here's a complete, self-contained CloudFormation template that demonstrates how to trigger a Lambda function whenever a file is added to an S3 bucket:

Description: Upload an object to an S3 bucket, triggering a Lambda event, returning the object key as a Stack Output. Parameters:   Key:     Description: S3 Object key     Type: String     Default: test   Body:     Description: S3 Object body content     Type: String     Default: TEST CONTENT   BucketName:     Description: S3 Bucket name     Type: String Resources:   Bucket:     Type: AWS::S3::Bucket     DependsOn: BucketPermission     Properties:       BucketName: !Ref BucketName       NotificationConfiguration:         LambdaConfigurations:         - Event: 's3:ObjectCreated:*'           Function: !GetAtt BucketWatcher.Arn   BucketPermission:     Type: AWS::Lambda::Permission     Properties:       Action: 'lambda:InvokeFunction'       FunctionName: !Ref BucketWatcher       Principal: s3.amazonaws.com       SourceAccount: !Ref "AWS::AccountId"       SourceArn: !Sub "arn:aws:s3:::${BucketName}"   BucketWatcher:     Type: AWS::Lambda::Function     Properties:       Description: Sends a Wait Condition signal to Handle when invoked       Handler: index.handler       Role: !GetAtt LambdaExecutionRole.Arn       Code:         ZipFile: !Sub |           exports.handler = function(event, context) {             console.log("Request received:\n", JSON.stringify(event));             var responseBody = JSON.stringify({               "Status" : "SUCCESS",               "UniqueId" : "Key",               "Data" : event.Records[0].s3.object.key,               "Reason" : ""             });             var https = require("https");             var url = require("url");             var parsedUrl = url.parse('${Handle}');             var options = {                 hostname: parsedUrl.hostname,                 port: 443,                 path: parsedUrl.path,                 method: "PUT",                 headers: {                     "content-type": "",                     "content-length": responseBody.length                 }             };             var request = https.request(options, function(response) {                 console.log("Status code: " + response.statusCode);                 console.log("Status message: " + response.statusMessage);                 context.done();             });             request.on("error", function(error) {                 console.log("send(..) failed executing https.request(..): " + error);                 context.done();             });             request.write(responseBody);             request.end();           };       Timeout: 30       Runtime: nodejs4.3   Handle:     Type: AWS::CloudFormation::WaitConditionHandle   Wait:     Type: AWS::CloudFormation::WaitCondition     Properties:       Handle: !Ref Handle       Timeout: 300   S3Object:     Type: Custom::S3Object     Properties:       ServiceToken: !GetAtt S3ObjectFunction.Arn       Bucket: !Ref Bucket       Key: !Ref Key       Body: !Ref Body   S3ObjectFunction:     Type: AWS::Lambda::Function     Properties:       Description: S3 Object Custom Resource       Handler: index.handler       Role: !GetAtt LambdaExecutionRole.Arn       Code:         ZipFile: !Sub |           var response = require('cfn-response');           var AWS = require('aws-sdk');           var s3 = new AWS.S3();           exports.handler = function(event, context) {             console.log("Request received:\n", JSON.stringify(event));             var responseData = {};             if (event.RequestType == 'Create') {               var params = {                 Bucket: event.ResourceProperties.Bucket,                 Key: event.ResourceProperties.Key,                 Body: event.ResourceProperties.Body               };               s3.putObject(params).promise().then(function(data) {                 response.send(event, context, response.SUCCESS, responseData);               }).catch(function(err) {                 console.log(JSON.stringify(err));                 response.send(event, context, response.FAILED, responseData);               });             } else if (event.RequestType == 'Delete') {               var deleteParams = {                 Bucket: event.ResourceProperties.Bucket,                 Key: event.ResourceProperties.Key               };               s3.deleteObject(deleteParams).promise().then(function(data) {                 response.send(event, context, response.SUCCESS, responseData);               }).catch(function(err) {                 console.log(JSON.stringify(err));                 response.send(event, context, response.FAILED, responseData);               });             } else {               response.send(event, context, response.SUCCESS, responseData);             }           };       Timeout: 30       Runtime: nodejs4.3   LambdaExecutionRole:     Type: AWS::IAM::Role     Properties:       AssumeRolePolicyDocument:         Version: '2012-10-17'         Statement:         - Effect: Allow           Principal: {Service: [lambda.amazonaws.com]}           Action: ['sts:AssumeRole']       Path: /       ManagedPolicyArns:       - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"       Policies:       - PolicyName: S3Policy         PolicyDocument:           Version: '2012-10-17'           Statement:             - Effect: Allow               Action:                 - 's3:PutObject'                 - 'S3:DeleteObject'               Resource: !Sub "arn:aws:s3:::${BucketName}/${Key}" Outputs:   Result:     Value: !GetAtt Wait.Data


回答2:

You need a NotificationConfiguration property in your CloudFormation template. Unfortunately, it seems to require the bucket to already exist. To get around this, you can create an initial stack, then update it with the NotificationConfiguration. For example:

// template1.json {   "AWSTemplateFormatVersion": "2010-09-09",   "Parameters": {     "mylambda": {       "Type": "String"     }   },   "Resources": {     "bucketperm": {       "Type": "AWS::Lambda::Permission",       "Properties" : {         "Action": "lambda:InvokeFunction",         "FunctionName": {"Ref": "mylambda"},         "Principal": "s3.amazonaws.com",         "SourceAccount": {"Ref": "AWS::AccountId"},         "SourceArn": { "Fn::Join": [":", [             "arn", "aws", "s3", "" , "", {"Ref" : "mybucket"}]]         }       }     },     "mybucket": {       "Type": "AWS::S3::Bucket"     }   } }  // template2.json -- adds the ConfigurationNotification {   "AWSTemplateFormatVersion": "2010-09-09",   "Parameters": {     "mylambda": {       "Type": "String"     }   },   "Resources": {     "bucketperm": {       "Type": "AWS::Lambda::Permission",       "Properties" : {         "Action": "lambda:InvokeFunction",         "FunctionName": {"Ref": "mylambda"},         "Principal": "s3.amazonaws.com",         "SourceAccount": {"Ref": "AWS::AccountId"},         "SourceArn": { "Fn::Join": [":", [             "arn", "aws", "s3", "" , "", {"Ref" : "mybucket"}]]         }       }     },     "mybucket": {       "Type": "AWS::S3::Bucket",       "Properties": {         "NotificationConfiguration": {           "LambdaConfigurations": [             {               "Event" : "s3:ObjectCreated:*",               "Function" : {"Ref": "mylambda"}             }           ]         }       }     }   } }

You can use the aws CLI tool to create the stack like this:

$ aws cloudformation create-stack --stack-name mystack --template-body file://template1.json --parameters ParameterKey=mylambda,ParameterValue=<lambda arn> # wait until stack is created $ aws cloudformation update-stack --stack-name mystack --template-body file://template2.json --parameters ParameterKey=mylambda,ParameterValue=<lambda arn>


回答3:

i have added below bucket perm along with notificationconfiguration in cloudformation which is used to create S3 bucket..it worked !!

"bucketperm": {             "Type": "AWS::Lambda::Permission",             "Properties": {                 "Action": "lambda:invokeFunction",                 "FunctionName": "<arnvalue>",                 "Principal": "s3.amazonaws.com"             } }


回答4:

Yes, it's possible through Cloudformation, and what you need to configure are:

1) AWS::S3::Bucket resource and,

2) NotificationConfiguration configuration (use LambdaConfigurations in this case) for the s3 resource above.

Related documentation that you need:

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html#cfn-s3-bucket-notification

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-notificationconfig.html



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!