Amazon GuardDuty multi account threat detection solution.

Amazon GuardDuty is a threat detection service that continuously monitors for malicious activity and unauthorized behavior to protect your AWS accounts and workloads, read more about the service on Amazon documentation . we are going to look into how to implement Amazon GuardDuty multi account solution using terraform scripts.

Let’s look into a read world scenario where a customer is setup with multiple accounts for different workloads and for different environments and we wanted to monitor all the accounts centrally for the threat detection from a Shared services ( master ) account and be able to send notifications for the high severity findings ( threats).

here is the architecture we are going to implement.

Amazon Guard Duty multi account setup

Implementation of Amazon GuardDuty multi account setup

Follow the steps outlined in AWS documentation to setup GuardDuty in your multiple accounts

Create a S3 bucket in the master account which will be used to store all the findings from all the member accounts.

Create a lambda function to process the GuardDuty Cloud Watch (finding) events . use this example provided in the Amazon documentation
download the code and save it as guardduty-s3-function.zip in your terraform project root folder.

Create Lambda and IAM role using terraform


data "aws_caller_identity" "current" {}

resource "aws_iam_role" "guard_duty-lambda_role" {
  name = "PREFIX-GUARD-DUTY-LAMBDA-ROLE"
  tags = {
    Name       = "PREFIX-GUARDDUTY-LAMBDA-ROLE"
  }
  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}

resource "aws_iam_policy" "policy" {
  name        = "PREFIX-GUARDDUTY-LAMBDA-POLICY"
  description = "This policy allows to process Guard Duty events from CW"

  policy = <<POLICY
{
  "Version": "2012-10-17",
  "Statement": [
        {
            "Action": [
                "s3:List*",
                "s3:Get*",
                "s3:Put*"
            ],
            "Effect": "Allow",
            "Resource": "arn:aws:s3:::bukcket_name}/*"
        },
        {
            "Effect": "Allow",
            "Action": "logs:CreateLogGroup",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:eu-central-1:${data.aws_caller_identity.current.account_id}:log-group:/aws/lambda/guardduty_lambda_name:*"
            ]
        }
                        
        ]
}
POLICY
}


resource "aws_iam_role_policy_attachment" "policy_attachement1" {
  policy_arn = aws_iam_policy.policy.arn
  role       = aws_iam_role.gd-lambda_role.name
}


## Lambda function
resource "aws_lambda_function" "guardduty_s3_lambda" {
  filename      = "${path.module}/guardduty-s3-function.zip"
  function_name = "guardduty_lambda_name"
  role          = aws_iam_role.gd-lambda_role.arn
  handler       = "guardduty_lambda.handler"
  timeout       = 60
  memory_size   = "128"
  runtime       = "nodejs12.x"
  description   = "Lambda function processing GuardDuty findings from CW events into S3 bucket"

  tags = {
    "Name"            = guardduty_lambda_name
  }

  environment {
    variables = {
      GUARDDUTY_LOGS_BUCKET = your_bucket_name
    }
  }
}

#add CW event permissions to lambda
resource "aws_lambda_permission" "cw-lambda-permission" {
  statement_id  = "AllowExecutionFromSNS2"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.guardduty_s3_lambda.arn
  principal     = "events.amazonaws.com"
  source_arn    = aws_cloudwatch_event_rule.guardduty_event.arn
}

Create Cloud Watch even rule for GuardDuty finding events and add Lambda as target.

Terraform code :

resource "aws_cloudwatch_event_rule" "guardduty_event" {
  name        = guardduty_cw_process_event
  description = "Capture GuardDuty findins event and triggers Lambda"

  event_pattern = <<PATTERN
{
  "source": [
    "aws.guardduty"
  ],
  "detail-type": [
    "GuardDuty Finding"
  ]
}
PATTERN
}

resource "aws_cloudwatch_event_target" "lambda" {
  rule      = aws_cloudwatch_event_rule.guardduty_event.name
  target_id = "SendToLambda"
  arn       = aws_lambda_function.guardduty_s3_lambda.arn
}

Go to the S3 bucket and verify the guardduty findings are saved .Lambda will be processing the CW events and saving the JSON files in your S3 bucket.

GuardDuty findings in S3 bucket.

Next step is to add another Cloud Watch Event to monitor High severity findings and send SNS notifications

Create a SNS Topic and subscribe to the topic using your email / email group.

Create a Cloud Watch event with below event pattern which is monitoring all severity levels but in realty you only want to monitor anything between 8.9 – 7.0 which is High severity.

{"source":["aws.guardduty"],"detail-type":["GuardDuty Finding"],"detail":{"severity":[1.0,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2.0,2.1,2.2,2.3,2.4,2.5,2.6,2.7,2.8,2.9,3.0,3.1,3.2,3.3,3.4,3.5,3.6,3.7,3.9,4,4.0,4.1,4.2,4.3,4.4,4.5,4.6,4.7,4.8,4.9,5,5.0,5.1,5.2,5.3,5.4,5.5,5.6,5.7,5.8,5.9,6,6.0,6.1,6.2,6.3,6.4,6.5,6.6,6.7,6.8,6.9,7,7.0,7.1,7.2,7.3,7.4,7.5,7.6,7.7,7.8,7.9,8,8.0,8.1,8.2,8.3,8.4,8.5,8.6,8.7,8.8,8.9]}}

Select SNS topic that was create in the above step as the Target . you should start receiving the finding to your email address which helps us to evaluate the threats and take appropriate action.

Connecting your log aggregator tools such as Sumologic and Splunk with the S3 bucket should be straight forward and it provides you a easy way to centrally view and manage all the threats ( findings ) from multiple accounts.

Refer to this article for the AWS Transit Gateway Hub & Spoke model

1+

Leave a Reply

Your email address will not be published. Required fields are marked *