![](/img/trans.png)
[英]How to enable request metrics for S3 bucket using Cloudformation or CDK
[英]Enable Lambda function to an S3 bucket using cloudformation
我們正在使用 CloudFormation 模板創建一個 S3 存儲桶。 每當將文件添加到 S3 存儲桶時,我都想關聯(將事件添加到 S3 存儲桶)一個 Lambda 函數。
怎么可能通過 CloudFormation 模板。 CloudFormation 中需要使用哪些屬性。
這是一個完整的、自包含的 CloudFormation 模板,演示了在將文件添加到 S3 存儲桶時如何觸發 Lambda 函數:
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
您的 CloudFormation 模板中需要一個NotificationConfiguration
屬性。 不幸的是,它似乎要求存儲桶已經存在。 為了解決這個問題,您可以創建一個初始堆棧,然后使用NotificationConfiguration
更新它。 例如:
// 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 NotificationConfiguration
{
"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"}
}
]
}
}
}
}
}
您可以使用 AWS CLI 工具創建堆棧,如下所示:
$ 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>
我在用於創建 S3 存儲桶的 cloudformation 中添加了存儲桶 perm 和通知配置。它起作用了!
"bucketperm": {
"Type": "AWS::Lambda::Permission",
"Properties": {
"Action": "lambda:invokeFunction",
"FunctionName": "<arnvalue>",
"Principal": "s3.amazonaws.com"
}
}
是的,可以通過 Cloudformation 實現,您需要配置的是:
1) AWS::S3::Bucket
資源和,
2) 上面 s3 資源的NotificationConfiguration
配置(在這種情況下使用LambdaConfigurations
)。
您需要的相關文檔:
AWS 文檔中明確指出AWS::S3::Bucket用於創建資源,如果我們有一個已經存在的存儲桶,我們無法修改它以添加 NotificationConfiguration。 因此,必須不存在 S3 存儲桶才能使上述模板正常工作。 讓 CloudFormation 創建包括 S3 存儲桶在內的所有資源。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.