AWS Lambda
开发人员指南
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

教程:将 AWS Lambda 与 AWS CloudTrail 结合使用

在这种情况下,AWS CloudTrail 将保留对您的账户进行的 AWS API 调用的记录(日志),并在每次发生用于创建 SNS 主题的 API 调用时通知您。由于 API 是在您的账户中调用的,CloudTrail 会将日志写入到您配置的 Amazon S3 存储桶中。在这种情况下,您希望 Amazon S3 在 CloudTrail 创建日志对象时将对象创建事件发布到 AWS Lambda 并调用 Lambda 函数。

当 Amazon S3 调用 Lambda 函数时,它会传递标识存储桶名称和 CloudTrail 创建的对象的键名称等的 S3 事件。Lambda 函数可读取该日志对象,并了解日志中报告的 API 调用。

CloudTrail 在 S3 存储桶中创建的每个对象都是包含一个或多个事件记录的 JSON 对象。此外,每条记录提供的内容都包括 eventSourceeventName

{ "Records":[ { "eventVersion":"1.02", "userIdentity":{ ... }, "eventTime":"2014-12-16T19:17:43Z", "eventSource":"sns.amazonaws.com", "eventName":"CreateTopic", "awsRegion":"us-west-2", "sourceIPAddress":"72.21.198.64", ... }, { ... }, ... }

为了展示这个过程,如果日志中报告了用于创建 Amazon SNS 主题的 API 调用,Lambda 函数会通过电子邮件向您发送通知。也就是说,Lambda 函数在分析日志时会查找包含以下内容的记录:

  • eventSource = "sns.amazonaws.com"

  • eventName = "CreateTopic"

如果找到,该函数会将该事件发布到 Amazon SNS 主题(您配置此主题以通过电子邮件向您发送通知)。

Lambda 函数将使用一个 S3 事件,该事件提供了存储桶名称和 CloudTrail 创建的对象的键名称。Lambda 函数随后读取该对象以处理 CloudTrail 记录。

先决条件

This tutorial assumes that you have some knowledge of basic Lambda operations and the Lambda console. If you haven't already, follow the instructions in 开始使用 AWS Lambda to create your first Lambda function.

To follow the procedures in this guide, you will need a command line terminal or shell to run commands. Commands are shown in listings preceded by a prompt symbol ($) and the name of the current directory, when appropriate:

~/lambda-project$ this is a command this is output

For long commands, an escape character (\) is used to split a command over multiple lines.

On Linux and macOS, use your preferred shell and package manager. On Windows 10, you can install the Windows Subsystem for Linux to get a Windows-integrated version of Ubuntu and Bash.

启用 CloudTrail

在 AWS CloudTrail 控制台中,为 CloudTrail 指定 us-west-2 区域中的 examplebucket 来保存日志,从而在您的账户中启用跟踪。配置跟踪时,不要启用 SNS 通知。

有关说明,请参阅 AWS CloudTrail User Guide 中的创建和更新您的跟踪

创建执行角色

创建执行角色,向您的函数授予访问 AWS 资源的权限。

创建执行角色

  1. 打开 IAM 控制台中的“角色”页面

  2. 选择 Create role (创建角色)

  3. 创建具有以下属性的角色。

    • 可信任的实体AWS Lambda

    • 角色名称 (角色名称)lambda-cloudtrail-role

    • 权限 – 自定义策略。

      { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "logs:*" ], "Resource": "arn:aws:logs:*:*:*" }, { "Effect": "Allow", "Action": [ "s3:GetObject" ], "Resource": "arn:aws:s3:::examplebucket/*" }, { "Effect": "Allow", "Action": [ "sns:Publish" ], "Resource": "your sns topic ARN" } ] }

此策略具有该函数从 Amazon S3 中读取项目并将日志写入 CloudWatch Logs 所需的权限。

创建函数

以下示例处理 CloudTrail 日志,并在创建 Amazon SNS 主题时发送通知。

例 index.js

var aws = require('aws-sdk'); var zlib = require('zlib'); var async = require('async'); var EVENT_SOURCE_TO_TRACK = /sns.amazonaws.com/; var EVENT_NAME_TO_TRACK = /CreateTopic/; var DEFAULT_SNS_REGION = 'us-west-2'; var SNS_TOPIC_ARN = 'The ARN of your SNS topic'; var s3 = new aws.S3(); var sns = new aws.SNS({ apiVersion: '2010-03-31', region: DEFAULT_SNS_REGION }); exports.handler = function(event, context, callback) { var srcBucket = event.Records[0].s3.bucket.name; var srcKey = event.Records[0].s3.object.key; async.waterfall([ function fetchLogFromS3(next){ console.log('Fetching compressed log from S3...'); s3.getObject({ Bucket: srcBucket, Key: srcKey }, next); }, function uncompressLog(response, next){ console.log("Uncompressing log..."); zlib.gunzip(response.Body, next); }, function publishNotifications(jsonBuffer, next) { console.log('Filtering log...'); var json = jsonBuffer.toString(); console.log('CloudTrail JSON from S3:', json); var records; try { records = JSON.parse(json); } catch (err) { next('Unable to parse CloudTrail JSON: ' + err); return; } var matchingRecords = records .Records .filter(function(record) { return record.eventSource.match(EVENT_SOURCE_TO_TRACK) && record.eventName.match(EVENT_NAME_TO_TRACK); }); console.log('Publishing ' + matchingRecords.length + ' notification(s) in parallel...'); async.each( matchingRecords, function(record, publishComplete) { console.log('Publishing notification: ', record); sns.publish({ Message: 'Alert... SNS topic created: \n TopicARN=' + record.responseElements.topicArn + '\n\n' + JSON.stringify(record), TopicArn: SNS_TOPIC_ARN }, publishComplete); }, next ); } ], function (err) { if (err) { console.error('Failed to publish notifications: ', err); } else { console.log('Successfully published all notifications.'); } callback(null,"message"); }); };

创建函数

  1. 将示例代码复制到名为 lambda-cloudtrail 的文件夹中名为 index.js 的文件。

  2. 使用 npm 安装 async

    ~/lambda-cloudtrail$ npm install async
  3. 创建部署程序包。

    ~/lambda-cloudtrail$ zip -r function.zip .
  4. 使用 create-function 命令创建 Lambda 函数。

    $ aws lambda create-function --function-name CloudTrailEventProcessing \ --zip-file fileb://function.zip --handler index.handler --runtime nodejs8.10 --timeout 10 --memory-size 1024 \ --role arn:aws:iam::123456789012:role/lambda-cloudtrail-role

向函数策略添加权限

向 Lambda 函数的资源策略添加权限以允许 Amazon S3 调用该函数。

  1. 运行下面的 add-permission 命令以向 Amazon S3 服务委托人 (s3.amazonaws.com) 授予执行 lambda:InvokeFunction 操作的权限。请注意,向 Amazon S3 授予权限,使其只能在满足以下条件时调用该函数:

    • 在特定的存储桶上检测到对象创建事件。

    • 存储桶归特定的 AWS 账户所有。如果存储桶拥有者删除了某个存储桶,则其他 AWS 账户可以创建使用该名称的存储桶。该条件确保只有特定的 AWS 账户能调用您的 Lambda 函数。

    $ aws lambda add-permission --function-name CloudTrailEventProcessing \ --statement-id Id-1 --action "lambda:InvokeFunction" --principal s3.amazonaws.com \ --source-arn arn:aws:s3:::examplebucket \ --source-account examplebucket-owner-account-id
  2. 使用 get-policy 命令验证函数的访问策略。

    $ aws lambda get-policy --function-name function-name

在存储桶上配置通知

examplebucket 上添加通知配置,以请求 Amazon S3 向 Lambda 发布对象创建事件。在配置中,指定以下内容:

  • 事件类型 – 任何创建对象的事件类型。

  • Lambda 函数 ARN – 这是您希望 Amazon S3 调用的 Lambda 函数。

    arn:aws:lambda:us-west-2:123456789012:function:CloudTrailEventProcessing

有关向存储桶添加通知配置的说明,请参阅 Amazon Simple Storage Service 控制台用户指南 中的启用事件通知

测试设置

现在,可以按以下方式测试设置:

  1. 创建一个 Amazon SNS 主题。

  2. AWS CloudTrail 在存储桶中创建日志对象。

  3. Amazon S3 会通过将该日志对象的位置作为事件数据传递来调用 Lambda 函数。

  4. Lambda 执行您的函数。函数将检索日志,查找 CreateTopic 事件,并发送通知。