介绍
在本教程中,您将学习如何使用 Terraform 配置 AWS 安全解决方案。您将使用 Amazon GuardDuty、Amazon SNS、AWS Lambda 和 Amazon EvenBridge 服务。.
对于许多组织而言,威胁检测与事件响应 (TDIR) 可能是一个耗时且繁琐的手动过程。这会导致响应流程不一致、安全结果不一致,并增加风险。在本教程中,您将学习如何自动化威胁检测结果并自动化事件响应流程,从而缩短威胁响应时间。由于许多组织倾向于使用标准的基础设施即代码 (IaC) 工具来实现跨供应商的一致配置,本教程将演示如何使用 Terraform 配置此解决方案。.
先决条件
- AWS账户
关于亚马逊 GuardDuty
在深入学习本教程之前,了解我们将要使用的一些工具的基本功能会很有帮助。Amazon GuardDuty 提供威胁检测功能,使您能够持续监控和保护 AWS 账户、工作负载以及存储在 Amazon Simple Storage Service (S3) 中的数据。GuardDuty 会分析从您的账户和网络活动生成的持续元数据流,这些元数据流存在于 AWS CloudTrail 事件、Amazon Virtual Private Cloud (VPC) 流日志和域名系统 (DNS) 日志中。GuardDuty 还利用集成的威胁情报(例如已知的恶意 IP 地址、异常检测和机器学习 (ML))来更准确地识别威胁。.
GuardDuty 完全独立于您的资源运行,因此不会对您的工作负载的性能或可用性造成任何影响。该服务由 Amazon GuardDuty 全面托管,集成了威胁情报、异常检测和机器学习功能。Amazon GuardDuty 提供准确、可操作的警报,并可轻松集成到现有的事件管理系统和工作流程中。无需预付费用,您只需为分析的事件付费,无需部署任何额外的软件或订阅威胁情报源。.
关于 Terraform 和 Cloud9
Terraform 是由 HashiCorp 开发的基础设施即代码 (IaC) 工具,它允许您使用配置文件而非用户界面来管理基础设施。借助 Terraform,您可以使用易于阅读的声明式配置文件来构建、修改和销毁基础设施。是的,您还可以使用 Terraform 构建、修改和销毁 AWS 基础设施——只需使用名为 Provider 的 Terraform 插件即可。AWS Provider 允许 Terraform 与 AWS 应用程序编程接口 (API) 进行交互。.
本教程使用 AWS Cloud9 进行 Terraform 配置。AWS Cloud9 是一个基于云的集成开发环境 (IDE),您只需使用浏览器即可编写、运行和调试代码。它包含代码编辑器、调试器和终端。Cloud9 预装了常用编程语言(包括 JavaScript、Python、PHP 和 Terraform)所需的基本工具,因此您无需安装任何文件或配置开发环境即可开始本教程。Cloud9 运行在您开始本教程时自动创建的 EC2 实例上。.
你将做什么
- “接触”主机与“风险”主机交互,导致 GuardDuty 报告发现问题。.
- 此发现与您将使用 Terraform 创建的 EventBridge 规则相匹配。该 EventBridge 规则执行两项操作:
- 创建一个 SNS 规则,该规则将使用 Terraform 创建。此 SNS 规则会向指定的管理员发送一封电子邮件,其中包含解释调查结果的易读文本。.
- 它会触发一个您使用 Terraform 创建的 Lambda 函数。该 Lambda 函数会将受感染的主机传递给取证安全小组,以便将其隔离进行进一步调查。.
步骤 1. 下载初始设置
本教程使用 AWS CloudFormation 模板来配置初始资源。这样做是为了让您能够专注于安全解决方案的基础配置。CloudFormation 模板会创建一个堆栈。该堆栈包含一个 AWS Cloud9 IDE 实例。我们使用此 Cloud9 实例是为了确保所有运行本教程的用户都能获得相同的编辑和部署体验。此外,当您在 US-WEST-2 区域部署堆栈时,请确保存在 t3.small 实例。如果模板部署在其他区域,且 t3.small 实例不可用,则可能需要修改模板以使用其他实例类型。.
1.1. 在 AWS 管理控制台中转到 AWS CloudFormation,然后单击“创建堆栈”按钮创建堆栈。.

1.2. 选择“上传模板文件”,然后从上面提供的示例代码库中上传 gd-iac-initial.yml 文件。然后单击“下一步”。.

1.3. 输入堆栈名称,然后单击“下一步”。.

1.4. 在“配置堆栈选项”页面上,单击“下一步”。.

1.5. 在审核页面上,向下滚动并单击复选框以确认 AWS CloudFormation 可以创建 IAM 资源,然后单击“下一步”。.

1.6. 确保栈处于完全创建状态。.
至此,您已部署了完成本教程所需的初始资源。下一步,您将访问创建该堆栈的 Cloud9 实例并初始化 Terraform。.
步骤 2. 访问 Cloud9 并启动 Terraform
2.1. 在 AWS 管理控制台中打开 AWS Cloud9,并在 Cloud9 IDE 中打开环境。.

2.2. 在 Cloud9 首选项中,禁用使用 AWS 管理的临时凭证。.

2.3. 从 Cloud9 实例上的终端模拟源代码存储库。.
git clone https://github.com/build-on-aws/automating-amazon-guardduty-with-iac.git
2.4. 切换到 automating-amazon-guardduty-with-iac 目录,并运行 terraform init、terraform plan 和 terraform apply。.
成功的请求将如下所示:

2.5. 验证是否存在两个新的 EC2 实例,一个命名为 IAC Tutorial: Compromised Instance,另一个命名为 IAC Tutorial: Malicious Instance。.
至此,您已部署了一个 VPC 和两个 EC2 实例。这两个 EC2 实例可以相互通信,稍后当您将其中一个 EC2 Elastic 实例的 IP 地址添加到威胁列表中时,GuardDuty 会触发生成一条安全发现。接下来,您将创建构成实际安全解决方案的各个资源。.
步骤 3:创建 S3 存储桶以存储威胁列表
GuardDuty 可以指代两种类型的列表:受信任 IP 列表和威胁 IP 列表。GuardDuty 不会对包含在受信任 IP 列表中的 IP 地址创建检测结果,但会对包含在威胁 IP 列表中的 IP 地址创建检测结果。由于本教程中我们需要强制创建检测结果,因此我们将使用威胁 IP 列表。.
3.1. 首先在 modules/s3/variables.tf 中为 vpc_id 创建一个变量。.
variable "vpc_id" {
}
3.2. 接下来,在 modules/s3/main.tf 文件中,获取当前的 AWS 账户号码并创建一个 S3 存储桶资源。.
# GET CURRENT AWS ACCOUNT NUMBER
data "aws_caller_identity" "current" {}
# CREATE TWO S3 BUCKETS
resource "aws_s3_bucket" "bucket" {
bucket = "guardduty-example-${data.aws_caller_identity.current.account_id}-us-east-1"
force_destroy = true
}
resource "aws_s3_bucket" "flow-log-bucket" {
bucket = "vpc-flow-logs-${data.aws_caller_identity.current.account_id}-us-east-1"
force_destroy = true
}
3.3. 然后启用 S3 存储桶中的 VPC 流日志。这不是必需的,但它允许我们查看 GuardDuty 看到的日志。.
# VPC FLOW LOGS
resource "aws_flow_log" "flow_log_example" {
log_destination = aws_s3_bucket.flow-log-bucket.arn
log_destination_type = "s3"
traffic_type = "ALL"
vpc_id = var.vpc_id
}
3.4. 最后,将 bucket_id 和 bucket_arn 值输出到 modules/s3/outputs.tf 文件中。.
# S3 Bucket id
output "bucket_id" {
value = aws_s3_bucket.bucket.id
description = "Output of s3 bucket id."
}
# S3 Bucket arn
output "bucket_arn" {
value = aws_s3_bucket.bucket.arn
description = "Output of s3 bucket arn."
}
3.5. 现在回到 root/main.tf 文件并添加 S3 存储桶。.
# CREATES S3 BUCKET
module "s3_bucket" {
source = "./modules/s3"
vpc_id = module.iac_vpc.vpc_attributes.id
}
至此,您已创建了两个 S3 存储桶。如果您想自行查看,其中一个存储桶用于存放 VPC 流日志。另一个存储桶包含您将在下一步创建的威胁列表。.
步骤 4:创建 GuardDuty Terraform 模块
4.1. GuardDuty 模块文件已为您创建,但与 S3 文件一样,它们都是空的。首先打开 modules/guardduty/variables.tf 文件。您需要在这里创建两个变量。第一个变量名为 bucket,我们将使用它来定义 S3 存储桶威胁列表的详细信息。第二个变量是我们已添加到存储桶中的恶意 IP 地址。.
variable "bucket" {
}
variable "malicious_ip" {
}
4.2. 然后转到文件 modules/guardduty/main.tf。.
在这个文件中,您需要添加三个数据源。第一个数据源是 GuardDuty 检测器。您会在提供程序文档中看到,所有选项都是可选的——除了声明数据源之外,无需其他任何设置。不过,在我们的示例中,我们将启用值设置为 true,并将 `finding_publishing_frequency` 更改为 15 分钟。默认值为一小时。.
# ENABLE THE DETECTOR
resource "aws_guardduty_detector" "gd-tutorial" {
enable = true
finding_publishing_frequency = "FIFTEEN_MINUTES"
}
4.3. 接下来,我们将一个文件上传到上一步创建的 S3 存储桶。虽然这不是必需的,但为了演示,我们希望使用其中一个 EC2 实例的 IP 地址,以确保本教程中的分析结果能够正确生成。在下面的代码中,我们将一个文本文件上传到名为 MyThreatIntelSet 的 S3 存储桶,文件内容为变量 var.malicious_ip 中包含的 IP 地址。.
# ADD THE EIP/MALICIOUS IP TO THE BUCKET AS A TEXT FILE.
resource "aws_s3_object" "MyThreatIntelSet" {
content = var.malicious_ip
bucket = var.bucket
key = "MyThreatIntelSet"
}
4.4. 最后,我们将创建一个名为 aws_guardduty_threatintelset 的资源,该资源告诉 GuardDuty 使用位于已定义位置的文件(这就是 activate = true 的作用)。.
# HAVE GUARDDUTY LOOK AT THE TEXT FILE IN S3
resource "aws_guardduty_threatintelset" "Example-Threat-List" {
activate = true
detector_id = aws_guardduty_detector.gd-tutorial.id
format = "TXT"
location = "https://s3.amazonaws.com/${aws_s3_object.MyThreatIntelSet.bucket}/${aws_s3_object.MyThreatIntelSet.key}"
name = "MyThreatIntelSet"
}
4.5. 然后打开根目录下的 main.tf 文件,调用 GuardDuty 模块。我们需要提供存储桶 ID 和恶意 IP 地址。可以看到,这些信息分别来自 S3 模块和计算模块。.
# Enable GuardDuty
module "guardduty" {
source = "./modules/guardduty"
bucket = module.s3_bucket.bucket_id
malicious_ip = module.compute.malicious_ip
}
在本节中,您启用了 GuardDuty,创建了威胁列表,并将恶意 EC2 实例的 Elastic IP 地址添加到了该列表中。接下来,我们将创建一条 SNS 规则。.
步骤 5:创建 SNS Terraform 模块
在本节中,我们将使用 Terraform 创建一条 SNS 规则。SNS 是一个简单的通知服务,允许您在满足特定条件时发送通知。SNS 本身并不对应发送消息的操作,我们将使用 EventBridge 来实现此功能。但是,由于 EventBridge 需要规则才能发送通知,因此我们需要先创建 SNS 规则。.
5.1. 首先,在 modules/sns/variables.tf 文件中,您需要创建两个变量:
- sns_name 用于命名我们将要创建的 SNS 主题。.
- 用于保存您订阅我们通知时所用电子邮件地址的邮箱地址。.
以下是我们 SNS 变量的示例。.
variable "sns_name" {
description = "Name of the SNS Topic to be created"
default = "GuardDuty-Example"
}
variable "email" {
description = "Email address for SNS"
}
5.2. 然后我们在 modules/sns/main.tf 文件中创建 SNS 主题和订阅。.
首先创建主题资源。.
# Create the SNS topic
resource "aws_sns_topic" "gd_sns_topic" {
name = var.sns_name
}
在上面的代码中,您使用 Terraform 创建了一个名为 gd_sns_topic 的资源。在 AWS 控制台中,它的名称是“GuardDuty-Example”。这是因为我们调用了变量 var.sns_name,而它的默认值为“GuardDuty-Example”。.
5.3. 接下来,创建 SNS 策略资源。ARN 和 Policy 值是必需的。此处创建的策略是一个 AWS IAM 策略文档。该策略文档允许服务主体 events.amazonaws.com 向指定主题发布消息。.
resource "aws_sns_topic_policy" "gd_sns_topic_policy" {
arn = aws_sns_topic.gd_sns_topic.arn
policy = jsonencode(
{
Id = "ID-GD-Topic-Policy"
Statement = [
{
Action = "sns:Publish"
Effect = "Allow"
Principal = {
Service = "events.amazonaws.com"
}
Resource = aws_sns_topic.gd_sns_topic.arn
Sid = "SID-GD-Example"
},
]
Version = "2012-10-17"
}
)
}
5.4. 接下来,您需要创建主题订阅。主题订阅会调用 ARN,设置要使用的协议(在本例中为电子邮件)以及接收通知的电子邮件地址。本例中电子邮件地址是硬编码的,但您可以将其配置为在 Terraform 应用时提示输入电子邮件地址。此外,将 endpoint_auto_confirm 设置为 false 意味着电子邮件地址的所有者将收到一封包含链接的电子邮件,他们需要点击该链接才能订阅通知。.
# Create the topic subscription
resource "aws_sns_topic_subscription" "user_updates_sqs_target" {
topic_arn = aws_sns_topic.gd_sns_topic.arn
protocol = "email"
endpoint = var.email
endpoint_auto_confirms = false
}
5.5. 接下来,在 modules/sns/outputs.tf 文件中,我们希望输出主题 ARN,以便我们可以在稍后进行的 EventBridge 配置中引用它。.
output "sns_topic_arn" {
value = aws_sns_topic.gd_sns_topic.arn
description = "Output of ARN to call in the eventbridge rule."
}
5.6. 最后,返回根目录下的 main.tf 文件,添加 SNS 主题。在这里,您需要指定订阅的电子邮件地址。.
# Creates an SNS Topic
module "guardduty_sns_topic" {
source = "./modules/sns"
email = "[email protected]"
}
在本节中,您创建了 SNS 主题,以便在生成特定发现时向您发送电子邮件。.
步骤 6:创建 EventBridge Terraform 模块
在本节中,您将使用 Terraform 创建 EventBridge 规则。EventBridge 规则将此解决方案的两个组成部分连接起来。.
EventBridge 的工作原理是什么?简而言之,EventBridge 接收一个事件(即环境变化的指示符),并应用一条规则将该事件路由到目标。规则根据事件的结构(称为事件模式)或基于预定的时间表将事件与目标进行匹配。在本例中,每当发现结果发生变化时,GuardDuty 都会向 Amazon EventBridge 生成一个事件。事件匹配后,Amazon EventBridge 会将规则路由到目标。在本例中,规则的目标是 SNS。SNS 规则会获取找到的数据,并向订阅者发送电子邮件通知。.
6.1. EventBridge 规则需要有关 GuardDuty 和 SNS 的信息。首先创建一个变量,用于存储 SNS 主体 ARN。请在 modules/eventbridge/variables.tf 文件中创建此变量。.
variable "sns_topic_arn" {
}
6.2. 接下来,在 modules/eventbridge/main.tf 文件中创建一个事件规则源。您需要定义所需的事件源和事件类型。.
# EVENT RULE RESOURCE
resource "aws_cloudwatch_event_rule" "GuardDuty-Event-EC2-MaliciousIPCaller" {
name = "GuardDuty-Event-EC2-MaliciousIPCaller"
description = "GuardDuty Event: UnauthorizedAccess:EC2/MaliciousIPCaller.Custom"
event_pattern = <<EOF
{
"source": ["aws.guardduty"],
"detail": {
"type": ["UnauthorizedAccess:EC2/MaliciousIPCaller.Custom"]
}
}
EOF
}
6.3. 接下来,定义事件目标源。创建此源时,您可以通过定义输入转换器来增强电子邮件通知的可读性。这将自定义 EventBridge 发送到事件目标的内容。下面我们获取 GuardDuty ID、区域和 EC2 实例 ID,并创建一个输入模板来简要说明消息内容。您可以看到,我们创建了一个输入模板,该模板使用了从 GuardDuty 发现的详细信息,并将其包含在已发送的电子邮件中。.
# EVENT TARGET RESOURCE FOR SNS NOTIFICATIONS
resource "aws_cloudwatch_event_target" "sns" {
rule = aws_cloudwatch_event_rule.GuardDuty-Event-EC2-MaliciousIPCaller.name
target_id = "GuardDuty-Example"
arn = var.sns_topic_arn
input_transformer {
input_paths = {
gdid = "$.detail.id",
region = "$.detail.region",
instanceid = "$.detail.resource.instanceDetails.instanceId"
}
input_template = "\"First GuardDuty Finding for the GuardDuty-IAC tutorial. | ID:<gdid> | The EC2 instance: <instanceid>, may be compromised and should be investigated. Go to https://console.aws.amazon.com/guardduty/home?region=<region>#/findings?macros=current&fId=<gdid>\""
}
}6.4. 在我们创建的第一个事件规则中,我们查找 GuardDuty-Event-EC2-MaliciousIPCaller 事件。创建第二个事件规则,查找 GuardDuty-Event-IAMUser-MaliciousIPCaller 事件,并针对该事件发送电子邮件通知。.
# EVENT RULE RESOURCE
resource "aws_cloudwatch_event_rule" "GuardDuty-Event-IAMUser-MaliciousIPCaller" {
name = "GuardDuty-Event-IAMUser-MaliciousIPCaller"
description = "GuardDuty Event: UnauthorizedAccess:IAMUser/MaliciousIPCaller.Custom"
event_pattern = <<EOF
{
"source": ["aws.guardduty"],
"detail": {
"type": ["UnauthorizedAccess:IAMUser/MaliciousIPCaller.Custom", "Discovery:S3/MaliciousIPCaller.Custom"]
}
}
EOF
}
#EVENT TARGET RESOURCE FOR SNS NOTIFICATIONS
resource "aws_cloudwatch_event_target" "iam-sns" {
rule = aws_cloudwatch_event_rule.GuardDuty-Event-IAMUser-MaliciousIPCaller.name
target_id = "GuardDuty-Example"
arn = var.sns_topic_arn
input_transformer {
input_paths = {
gdid = "$.detail.id",
region = "$.detail.region",
userName = "$.detail.resource.accessKeyDetails.userName"
}
input_template = "\"Second GuardDuty Finding for the GuardDuty-IAC tutorial. | ID:<gdid> | AWS Region:<region>. An AWS API operation was invoked (userName: <userName>) from an IP address that is included on your threat list and should be investigated.Go to https://console.aws.amazon.com/guardduty/home?region=<region>#/findings?macros=current&fId=<gdid>\""
}
}6.5. 在模块中创建资源后,返回 root/main.tf 文件并添加 EventBridge 规则。.
# Create the EventBridge rule
module "guardduty_eventbridge_rule" {
source = "./modules/eventbridge"
sns_topic_arn = module.guardduty_sns_topic.sns_topic_arn
}在本节中,您创建了一条 EventBridge 规则,该规则使用您创建的 SNS 主题,以便在 GuardDuty 检测结果匹配时发送电子邮件。在下一节中,您将使用 Lambda 扩展此功能。.
步骤 7:创建 Lambda Terraform 模块
在本节中,我们将使用 Terraform 创建一个 Lambda 函数,用于修复我们的环境。本教程的目标是将受损主机迁移到新的安全组。与 EventBridge 使用 SNS 生成电子邮件类似,EventBridge 将封装该 Lambda 函数。.
需要注意的是,这里有很多种可能的方法。更多信息,请参阅“使用 Amazon CloudWatch Events 创建针对 GuardDuty 发现结果的自定义响应”和“使用 AWS 网络防火墙和 Amazon GuardDuty 自动阻止可疑流量”文档。.
在开始之前,让我们先来看看要实现这一点需要做些什么。.
目前,我们的 GuardDuty 检测结果会与 EventBridge 规则进行匹配,目标为——目前是一个发送电子邮件的 SNS 规则。为了增强此功能,EventBridge 使用 AWS Lambda 作为目标。.
由于我们计划代表 AWS Lambda 访问其他资源,因此需要创建一个 IAM 角色来授予该服务相应的权限。该角色称为服务,当我们更改 EC2 实例的安全组时,AWS Lambda 将承担此角色。.
下图展示了前三个代码块如何组合在一起,使 AWS Lambda 服务能够承担更改分配给 EC2 实例的安全组的角色。.

7.1. 首先在 modules/lambda/main.tf 中创建 IAM 策略文档。这是该策略的信任关系。.
data "aws_iam_policy_document" "GD-EC2MaliciousIPCaller-policy-document" {
statement {
effect = "Allow"
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["lambda.amazonaws.com"]
}
}
}
7.2. 接下来,创建一个适用于 AWS Lambda 将承担的角色的内联策略。.
resource "aws_iam_role_policy" "GD-EC2MaliciousIPCaller-inline-role-policy" {
name = "GD-EC2MaliciousIPCaller-inline-role-policy"
role = aws_iam_role.GD-Lambda-EC2MaliciousIPCaller-role.id
policy = jsonencode({
"Version" : "2012-10-17",
"Statement" : [
{
"Action" : [
"ssm:PutParameter",
"ec2:AuthorizeSecurityGroupEgress",
"ec2:AuthorizeSecurityGroupIngress",
"ec2:CreateSecurityGroup",
"ec2:DescribeSecurityGroups",
"ec2:RevokeSecurityGroupEgress",
"ec2:RevokeSecurityGroupIngress",
"ec2:UpdateSecurityGroupRuleDescriptionsEgress",
"ec2:UpdateSecurityGroupRuleDescriptionsIngress",
"ec2:DescribeInstances",
"ec2:UpdateSecurityGroupRuleDescriptionsIngress",
"ec2:DescribeVpcs",
"ec2:ModifyInstanceAttribute",
"lambda:InvokeFunction",
"cloudwatch:PutMetricData",
"xray:PutTraceSegments",
"xray:PutTelemetryRecords"
],
"Resource" : "*",
"Effect" : "Allow"
},
{
"Action" : [
"logs:*"
],
"Resource" : "arn:aws:logs:*:*:*",
"Effect" : "Allow"
},
{
"Action" : [
"sns:Publish"
],
"Resource" : var.sns_topic_arn,
"Effect" : "Allow"
}
]
})
}
7.3. 现在创建 AWS Lambda 将承担的 IAM 角色。.
resource "aws_iam_role" "GD-Lambda-EC2MaliciousIPCaller-role" {
name = "GD-Lambda-EC2MaliciousIPCaller-role1"
assume_role_policy = data.aws_iam_policy_document.GD-EC2MaliciousIPCaller-policy-document.json
}
7.4. 创建一个指向代码的数据源。.
data "archive_file" "python_lambda_package" {
type = "zip"
source_file = "${path.module}/code/index.py"
output_path = "index.zip"
}
7.5. 接下来,我们需要授予 EventBridge 对 Lambda 的访问权限。.
resource "aws_lambda_permission" "GuardDuty-Hands-On-RemediationLambda" {
statement_id = "GuardDutyTerraformRemediationLambdaEC2InvokePermissions"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.GuardDuty-Example-Remediation-EC2MaliciousIPCaller.function_name
principal = "events.amazonaws.com"
}
上述代码块允许 EventBridge 调用 Lambda 函数。.
7.6 最后,我们创建 Lambda 函数的源文件。为此,我们需要创建一些变量来传递信息。编辑 modules/lambda/variables.tf 文件,添加以下变量:
variable "sns_topic_arn" {
}
variable "compromised_instance_id" {
}
variable "forensic_sg_id" {
}7.7. 然后返回 modules/lambda/main.tf 文件,创建 Lambda 函数源。请注意,以下代码块使用的是 Python 3.9。我们还引用了压缩在 index.zip 文件中的 Python 代码。最后,我们在源中设置了几个环境变量:INSTANCE_ID、FORENSICS_SG 和 TOPIC_ARN。这些变量将从我们创建的变量传递到 Lambda 函数环境中。.
# Create the Lambda function Resource
resource "aws_lambda_function" "GuardDuty-Example-Remediation-EC2MaliciousIPCaller" {
function_name = "GuardDuty-Example-Remediation-EC2MaliciousIPCaller"
filename = "index.zip"
source_code_hash = data.archive_file.python_lambda_package.output_base64sha256
role = aws_iam_role.GD-Lambda-EC2MaliciousIPCaller-role.arn
runtime = "python3.9"
handler = "index.handler"
timeout = 10
environment {
variables = {
INSTANCE_ID = var.compromised_instance_id
FORENSICS_SG = var.forensic_sg_id
TOPIC_ARN = var.sns_topic_arn
}
}
}7.8. 在 root/main.tf 文件中,调用 Lambda 模块,设置 SNS 主题 ARN、受损实例 ID 和取证安全组。请注意,这些值来自 GuardDuty 模块、Compute 模块和 VPC 模块。.
# CREATE THE LAMBDA FUNCTION
module "lambda" {
source = "./modules/lambda"
sns_topic_arn = module.guardduty_sns_topic.sns_topic_arn
compromised_instance_id = module.compute.compromised_instance_id
forensic_sg_id = module.forensic-security-group.security_group_id
}
7.9. 法律安全组尚未创建。请添加一个安全组以使用它。.
# CREATES THE FORENSICS_SG SECURITY GROUP
module "forensic-security-group" {
source = "terraform-aws-modules/security-group/aws"
version = "4.17.1"
name = "FORENSIC_SG"
description = "Forensic Security group "
vpc_id = module.iac_vpc.vpc_attributes.id
}7.10. 要访问 security-legal 组,我们需要将其输出。在 root/outputs.tf 文件中输出安全组 ID。.
output "forensic_sg_id" {
value = module.forensic-security-group.security_group_id
description = "Output of forensic sg id created - to place the EC2 instance(s)."
}7.11. 现在我们需要配置 EventBridge 规则,将找到的数据发送到 Lambda 函数。我们将在下一节中进行配置。返回 modules/eventbridge/main.tf 文件。为 Lambda 函数添加一个事件目标源,该函数会查找规则 aws_cloudwatch_event_rule.GuardDuty-Event-EC2-MaliciousIPCaller.name,并将目标 ID 设置为 GuardDuty-Example-Remediation。这里需要 Lambda 函数的 ARN。该 ARN 可以从 Lambda 模块输出。.
#EVENT TARGET RESOURCE FOR LAMBDA REMEDIATION FUNCTION
resource "aws_cloudwatch_event_target" "lambda_function" {
rule = aws_cloudwatch_event_rule.GuardDuty-Event-EC2-MaliciousIPCaller.name
target_id = "GuardDuty-Example-Remediation"
arn = var.lambda_remediation_function_arn
}7.12. 如果您还没有这样做,请将输出添加到 Lambda 模块(modules/lambda/outputs.tf)。.
output "lambda_remediation_function_arn" {
value = aws_lambda_function.GuardDuty-Example-Remediation-EC2MaliciousIPCaller.arn
}
7.13. 此变量也应应用于 EventBridge 模块(modules/eventbridge/variables.tf)。.
variable "lambda_remediation_function_arn" {
}7.14. 最后,将 lambda_remediation_function_arn 添加到 root/main.tf 文件中。这段代码需要添加到之前创建的 EventBridge 规则中。下面的输出是完整的代码块,其中部分代码已存在。请确保只将代码 lambda_remediation_function_arn = module.lambda.lambda_remediation_function_arn 添加到已有的代码块中。.
module "guardduty_eventbridge_rule" {
source = "./modules/eventbridge"
sns_topic_arn = module.guardduty_sns_topic.sns_topic_arn
lambda_remediation_function_arn = module.lambda.lambda_remediation_function_arn
}
在本节中,您创建了一个 Lambda 函数,用于将存在风险的主机隔离到不同的安全组中。当 GuardDuty 检测到的安全事件与 EventBridge 规则匹配时,EventBridge 会调用此 Lambda 函数。在下一节中,您将应用完整的配置。.
步骤 8:将设置应用到您的 AWS 账户
8.1. 运行 terraform init 命令。这将初始化你在本代码教程中添加的所有模块。输出结果应如下所示。.

8.2. 绘制平面图。.
8.3. 要将更改应用到 AWS,请运行 Terraform 应用程序。应用后,输出应如下所示:
在本节中,您已将 Terraform 配置应用到您的 AWS 账户。此时,您有两个 EC2 实例正在相互通信。其中一个实例是恶意实例,其 IP 地址已被添加到我们的威胁 IP 列表中。当 GuardDuty 检测到此 IP 地址正在与受感染的实例通信时,它会创建一个安全发现。我们有一个 EventBridge 规则与该安全发现匹配,并执行两项操作:首先,它会向我们发送电子邮件,告知我们发生了什么;其次,它会调用一个 Lambda 函数来更改受感染主机的安全组。在下一节中,我们将在 AWS 控制台中验证配置。.
步骤 9:在 AWS 管理控制台中验证解决方案
在本节中,我们将在 AWS 控制台中查看整个解决方案,并验证当 GuardDuty 中出现调查结果且 EventBridge 触发 Lambda 函数时,安全组是否已迁移。.
您应该还会收到一封确认订阅的电子邮件。请记住,您必须订阅才能接收您已配置的通知。.
订阅后,请转到 AWS 管理控制台,验证是否存在两个 EC2 实例,并且这两个实例都位于主安全组中。.
首先,检查是否存在被入侵的主机。.
然后检查是否存在恶意主机。.
然后确保 GuardDuty 报告调查结果。.

现在检查一下 EventBridge 规则发现了什么。.
然后检查 EventBridge 规则目标。您应该看到一个 SNS 目标和一个 Lambda 目标。.
查看 SNS 规则,了解其具体作用。它应该会向您指定的地址发送电子邮件。.
然后检查 Lambda 函数。您可以从 EventBridge 规则中找到它,也可以直接导航到那里。.
最后,验证 Lambda 函数是否已将受感染的主机移动到新的安全组。.
根据您等待的时间长短,如果您的配置与上面的屏幕截图相符,那么您已经使用 Terraform 成功创建了一个完整的 AWS 安全解决方案。.
































