Skip to main content

guardduty

This component is responsible for configuring GuardDuty within an AWS Organization.

AWS GuardDuty is a managed threat detection service. It is designed to help protect AWS accounts and workloads by continuously monitoring for malicious activities and unauthorized behaviors. To detect potential security threats, GuardDuty analyzes various data sources within your AWS environment, such as AWS CloudTrail logs, VPC Flow Logs, and DNS logs.

Key features and components of AWS GuardDuty include:

  • Threat detection: GuardDuty employs machine learning algorithms, anomaly detection, and integrated threat intelligence to identify suspicious activities, unauthorized access attempts, and potential security threats. It analyzes event logs and network traffic data to detect patterns, anomalies, and known attack techniques.

  • Threat intelligence: GuardDuty leverages threat intelligence feeds from AWS, trusted partners, and the global community to enhance its detection capabilities. It uses this intelligence to identify known malicious IP addresses, domains, and other indicators of compromise.

  • Real-time alerts: When GuardDuty identifies a potential security issue, it generates real-time alerts that can be delivered through AWS CloudWatch Events. These alerts can be integrated with other AWS services like Amazon SNS or AWS Lambda for immediate action or custom response workflows.

  • Multi-account support: GuardDuty can be enabled across multiple AWS accounts, allowing centralized management and monitoring of security across an entire organization's AWS infrastructure. This helps to maintain consistent security policies and practices.

  • Automated remediation: GuardDuty integrates with other AWS services, such as AWS Macie, AWS Security Hub, and AWS Systems Manager, to facilitate automated threat response and remediation actions. This helps to minimize the impact of security incidents and reduces the need for manual intervention.

  • Security findings and reports: GuardDuty provides detailed security findings and reports that include information about detected threats, affected AWS resources, and recommended remediation actions. These findings can be accessed through the AWS Management Console or retrieved via APIs for further analysis and reporting.

GuardDuty offers a scalable and flexible approach to threat detection within AWS environments, providing organizations with an additional layer of security to proactively identify and respond to potential security risks.

Supported GuardDuty Protection Features

This component supports the following GuardDuty protection features:

  • S3 Protection: Monitors S3 data events to detect suspicious activities in your S3 buckets
  • EKS Audit Log Monitoring: Analyzes Kubernetes audit logs from Amazon EKS clusters
  • Malware Protection: Scans EBS volumes attached to EC2 instances for malware
  • Lambda Protection: Monitors Lambda function network activity logs
  • Runtime Monitoring: Provides runtime threat detection for EC2, ECS, and EKS workloads with automatic security agent management

SNS Notifications

This component creates its own SNS topic, SQS queue, and KMS key for GuardDuty findings notifications instead of using the ones from the upstream cloudposse/guardduty/aws module. This is a workaround for cloudposse/terraform-aws-guardduty#10 where the module's SNS topic encryption doesn't grant EventBridge permission to decrypt messages.

The component creates:

  • A custom KMS key with proper permissions for EventBridge, SNS, and SQS services
  • An SNS topic encrypted with the custom KMS key
  • An SQS queue subscribed to the SNS topic for message processing
  • CloudWatch Event Rules to route GuardDuty findings to the SNS topic

To enable notifications, set create_sns_topic: true and cloudwatch_enabled: true.

Usage

Stack Level: Regional

Prerequisites

Before deploying this component, ensure that GuardDuty trusted access is enabled in AWS Organizations. This can be done by adding guardduty.amazonaws.com to the aws_service_access_principals list in your account component, or by running the following command from the management account:

aws organizations enable-aws-service-access --service-principal guardduty.amazonaws.com

Deployment Overview

This component is complex in that it must be deployed multiple times with different variables set to configure the AWS Organization successfully.

It is further complicated by the fact that you must deploy each of the the component instances described below to every region that existed before March 2019 and to any regions that have been opted-in as described in the AWS Documentation.

In the examples below, we assume that the AWS Organization Management account is root and the AWS Organization Delegated Administrator account is security, both in the core tenant.

Step 1: Deploy to Delegated Administrator Account

First, the component is deployed to the Delegated Administrator account in each region in order to configure the central GuardDuty detector that each account will send its findings to.

# core-ue1-security
components:
terraform:
guardduty/delegated-administrator/ue1:
metadata:
component: guardduty
vars:
enabled: true
delegated_administrator_account_name: core-security
environment: ue1
region: us-east-1
atmos terraform apply guardduty/delegated-administrator/ue1 -s core-ue1-security
atmos terraform apply guardduty/delegated-administrator/ue2 -s core-ue2-security
atmos terraform apply guardduty/delegated-administrator/uw1 -s core-uw1-security
# ... other regions

Step 2: Deploy to Organization Management (root) Account

Next, the component is deployed to the AWS Organization Management, a/k/a root, Account in order to set the AWS Organization Designated Administrator account.

Note that you must use the SuperAdmin permissions as we are deploying to the AWS Organization Management account. Since we are using the SuperAdmin user, it will already have access to the state bucket, so we set the role_arn of the backend config to null and set var.privileged to true.

# core-ue1-root
components:
terraform:
guardduty/root/ue1:
metadata:
component: guardduty
backend:
s3:
role_arn: null
vars:
enabled: true
delegated_administrator_account_name: core-security
environment: ue1
region: us-east-1
privileged: true
atmos terraform apply guardduty/root/ue1 -s core-ue1-root
atmos terraform apply guardduty/root/ue2 -s core-ue2-root
atmos terraform apply guardduty/root/uw1 -s core-uw1-root
# ... other regions

Step 3: Deploy Organization Settings in Delegated Administrator Account

Finally, the component is deployed to the Delegated Administrator Account again in order to create the organization-wide configuration for the AWS Organization, but with var.admin_delegated set to true to indicate that the delegation has already been performed from the Organization Management account.

# core-ue1-security
components:
terraform:
guardduty/org-settings/ue1:
metadata:
component: guardduty
vars:
enabled: true
delegated_administrator_account_name: core-security
environment: use1
region: us-east-1
admin_delegated: true
atmos terraform apply guardduty/org-settings/ue1 -s core-ue1-security
atmos terraform apply guardduty/org-settings/ue2 -s core-ue2-security
atmos terraform apply guardduty/org-settings/uw1 -s core-uw1-security
# ... other regions

Enabling GuardDuty Protection Features

You can enable various GuardDuty protection features by setting the corresponding variables. Here's an example with all protection features enabled:

# core-ue1-security
components:
terraform:
guardduty/org-settings/ue1:
metadata:
component: guardduty
vars:
enabled: true
delegated_administrator_account_name: core-security
environment: use1
region: us-east-1
admin_delegated: true
# Protection features
s3_protection_enabled: true
kubernetes_audit_logs_enabled: true
malware_protection_scan_ec2_ebs_volumes_enabled: true
lambda_network_logs_enabled: true
# Runtime Monitoring with automatic agent management
runtime_monitoring_enabled: true
runtime_monitoring_additional_config:
eks_addon_management_enabled: true
ecs_fargate_agent_management_enabled: true
ec2_agent_management_enabled: true

Note: You cannot enable both eks_runtime_monitoring_enabled and runtime_monitoring_enabled at the same time. Use runtime_monitoring_enabled if you want runtime monitoring across EC2, ECS, and EKS resources.

Enabling SNS Notifications

To enable SNS notifications for GuardDuty findings, set create_sns_topic and cloudwatch_enabled to true:

# core-ue1-security
components:
terraform:
guardduty/delegated-administrator/ue1:
metadata:
component: guardduty
vars:
enabled: true
delegated_administrator_account_name: core-security
environment: ue1
region: us-east-1
# Enable SNS notifications
create_sns_topic: true
cloudwatch_enabled: true

This will create:

  • A KMS key with permissions for EventBridge, SNS, and SQS
  • An encrypted SNS topic for GuardDuty findings
  • An SQS queue subscribed to the SNS topic
  • CloudWatch Event Rules to route findings to SNS

Variables

Required Variables

region (string) required

AWS Region

Optional Variables

account_map_component_name (string) optional

The name of the account-map component


Default value: "account-map"

account_map_tenant (string) optional

The tenant where the account_map component required by remote-state is deployed


Default value: "core"

admin_delegated (bool) optional

A flag to indicate if the AWS Organization-wide settings should be created. This can only be done after the GuardDuty
Administrator account has already been delegated from the AWS Org Management account (usually 'root'). See the
Deployment section of the README for more information.



Default value: false

auto_enable_organization_members (string) optional

Indicates the auto-enablement configuration of GuardDuty for the member accounts in the organization. Valid values are ALL, NEW, NONE.


For more information, see:
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/guardduty_organization_configuration#auto_enable_organization_members



Default value: "NEW"

cloudwatch_enabled (bool) optional

Flag to indicate whether CloudWatch logging should be enabled for GuardDuty



Default value: false

cloudwatch_event_rule_pattern_detail_type (string) optional

The detail-type pattern used to match events that will be sent to SNS.


For more information, see:
https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/CloudWatchEventsandEventPatterns.html
https://docs.aws.amazon.com/eventbridge/latest/userguide/event-types.html
https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_findings_cloudwatch.html



Default value: "GuardDuty Finding"

create_sns_topic (bool) optional

Flag to indicate whether an SNS topic should be created for notifications. If you want to send findings to a new SNS
topic, set this to true and provide a valid configuration for subscribers.



Default value: false

delegated_administrator_account_name (string) optional

The name of the account that is the AWS Organization Delegated Administrator account


Default value: "core-security"

delegated_administrator_component_name (string) optional

The name of the component that created the GuardDuty detector.


Default value: "guardduty/delegated-administrator"

detector_features optional

A map of detector features for streaming foundational data sources to detect communication with known malicious domains and IP addresses and identify anomalous behavior.


For more information, see:
https://docs.aws.amazon.com/guardduty/latest/ug/guardduty-features-activation-model.html#guardduty-features


feature_name:
The name of the detector feature. Possible values include: S3_DATA_EVENTS, EKS_AUDIT_LOGS, EBS_MALWARE_PROTECTION, RDS_LOGIN_EVENTS, EKS_RUNTIME_MONITORING, LAMBDA_NETWORK_LOGS, RUNTIME_MONITORING. Specifying both EKS Runtime Monitoring (EKS_RUNTIME_MONITORING) and Runtime Monitoring (RUNTIME_MONITORING) will cause an error. You can add only one of these two features because Runtime Monitoring already includes the threat detection for Amazon EKS resources. For more information, see: https://docs.aws.amazon.com/guardduty/latest/APIReference/API_DetectorFeatureConfiguration.html.
status:
The status of the detector feature. Valid values include: ENABLED or DISABLED.
additional_configuration:
Optional list of additional configurations for a feature in your GuardDuty account. For more information, see: https://docs.aws.amazon.com/guardduty/latest/APIReference/API_DetectorAdditionalConfiguration.html.
addon_name:
The name of the add-on for which the configuration applies. Possible values include: EKS_ADDON_MANAGEMENT, ECS_FARGATE_AGENT_MANAGEMENT, and EC2_AGENT_MANAGEMENT. For more information, see: https://docs.aws.amazon.com/guardduty/latest/APIReference/API_DetectorAdditionalConfiguration.html.
status:
The status of the add-on. Valid values include: ENABLED or DISABLED.



Type:

map(object({
feature_name = string
status = string
additional_configuration = optional(list(object({
addon_name = string
status = string
})), [])
}))

Default value: { }

eks_runtime_monitoring_enabled (bool) optional

If true, enables EKS Runtime Monitoring.
Note: Do not enable both EKS_RUNTIME_MONITORING and RUNTIME_MONITORING as Runtime Monitoring already includes
threat detection for Amazon EKS resources.


For more information, see:
https://docs.aws.amazon.com/guardduty/latest/ug/eks-runtime-monitoring.html



Default value: false

finding_publishing_frequency (string) optional

The frequency of notifications sent for finding occurrences. If the detector is a GuardDuty member account, the value
is determined by the GuardDuty master account and cannot be modified, otherwise it defaults to SIX_HOURS.


For standalone and GuardDuty master accounts, it must be configured in Terraform to enable drift detection.
Valid values for standalone and master accounts: FIFTEEN_MINUTES, ONE_HOUR, SIX_HOURS."


For more information, see:
https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_findings_cloudwatch.html#guardduty_findings_cloudwatch_notification_frequency



Default value: null

findings_notification_arn (string) optional

The ARN for an SNS topic to send findings notifications to. This is only used if create_sns_topic is false.
If you want to send findings to an existing SNS topic, set this to the ARN of the existing topic and set
create_sns_topic to false.



Default value: null

global_environment (string) optional

Global environment name


Default value: "gbl"

kubernetes_audit_logs_enabled (bool) optional

If true, enables Kubernetes audit logs as a data source for Kubernetes protection.


For more information, see:
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/guardduty_detector#audit_logs



Default value: false

lambda_network_logs_enabled (bool) optional

If true, enables Lambda network logs as a data source for Lambda protection.


For more information, see:
https://docs.aws.amazon.com/guardduty/latest/ug/lambda-protection.html



Default value: false

malware_protection_scan_ec2_ebs_volumes_enabled (bool) optional

Configure whether Malware Protection is enabled as data source for EC2 instances EBS Volumes in GuardDuty.


For more information, see:
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/guardduty_detector#malware-protection



Default value: false

organization_management_account_name (string) optional

The name of the AWS Organization management account


Default value: null

privileged (bool) optional

true if the default provider already has access to the backend


Default value: false

root_account_stage (string) optional

The stage name for the Organization root (management) account. This is used to lookup account IDs from account names
using the account-map component.



Default value: "root"

runtime_monitoring_additional_config optional

Additional configuration for Runtime Monitoring features.


eks_addon_management_enabled: Enable EKS add-on management
ecs_fargate_agent_management_enabled: Enable ECS Fargate agent management
ec2_agent_management_enabled: Enable EC2 agent management


For more information, see:
https://docs.aws.amazon.com/guardduty/latest/ug/runtime-monitoring.html



Type:

object({
eks_addon_management_enabled = optional(bool, false)
ecs_fargate_agent_management_enabled = optional(bool, false)
ec2_agent_management_enabled = optional(bool, false)
})

Default value: { }

runtime_monitoring_enabled (bool) optional

If true, enables Runtime Monitoring for EC2, ECS, and EKS resources.
Note: Runtime Monitoring already includes threat detection for Amazon EKS resources, so you should not enable both
RUNTIME_MONITORING and EKS_RUNTIME_MONITORING features.


For more information, see:
https://docs.aws.amazon.com/guardduty/latest/ug/runtime-monitoring.html



Default value: false

s3_protection_enabled (bool) optional

If true, enables S3 protection.


For more information, see:
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/guardduty_detector#s3-logs



Default value: true

subscribers optional

A map of subscription configurations for SNS topics


For more information, see:
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_subscription#argument-reference


protocol:
The protocol to use. The possible values for this are: sqs, sms, lambda, application. (http or https are partially
supported, see link) (email is an option but is unsupported in terraform, see link).
endpoint:
The endpoint to send data to, the contents will vary with the protocol. (see link for more information)
endpoint_auto_confirms:
Boolean indicating whether the end point is capable of auto confirming subscription e.g., PagerDuty. Default is
false.
raw_message_delivery:
Boolean indicating whether or not to enable raw message delivery (the original message is directly passed, not
wrapped in JSON with the original message in the message property). Default is false.



Type:

map(object({
protocol = string
endpoint = string
endpoint_auto_confirms = bool
raw_message_delivery = bool
}))

Default value: { }

Context Variables

The following variables are defined in the context.tf file of this module and part of the terraform-null-label pattern.

additional_tag_map (map(string)) optional

Additional key-value pairs to add to each map in tags_as_list_of_maps. Not added to tags or id.
This is for some rare cases where resources want additional configuration of tags
and therefore take a list of maps with tag key, value, and additional configuration.


Required: No

Default value: { }

attributes (list(string)) optional

ID element. Additional attributes (e.g. workers or cluster) to add to id,
in the order they appear in the list. New attributes are appended to the
end of the list. The elements of the list are joined by the delimiter
and treated as a single ID element.


Required: No

Default value: [ ]

context (any) optional

Single object for setting entire context at once.
See description of individual variables for details.
Leave string and numeric variables as null to use default value.
Individual variable settings (non-null) override settings in context object,
except for attributes, tags, and additional_tag_map, which are merged.


Required: No

Default value:

{
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"descriptor_formats": {},
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"labels_as_tags": [
"unset"
],
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {},
"tenant": null
}
delimiter (string) optional

Delimiter to be used between ID elements.
Defaults to - (hyphen). Set to "" to use no delimiter at all.


Required: No

Default value: null

descriptor_formats (any) optional

Describe additional descriptors to be output in the descriptors output map.
Map of maps. Keys are names of descriptors. Values are maps of the form
\{<br/> format = string<br/> labels = list(string)<br/> \}
(Type is any so the map values can later be enhanced to provide additional options.)
format is a Terraform format string to be passed to the format() function.
labels is a list of labels, in order, to pass to format() function.
Label values will be normalized before being passed to format() so they will be
identical to how they appear in id.
Default is {} (descriptors output will be empty).


Required: No

Default value: { }

enabled (bool) optional

Set to false to prevent the module from creating any resources
Required: No

Default value: null

environment (string) optional

ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'
Required: No

Default value: null

id_length_limit (number) optional

Limit id to this many characters (minimum 6).
Set to 0 for unlimited length.
Set to null for keep the existing setting, which defaults to 0.
Does not affect id_full.


Required: No

Default value: null

label_key_case (string) optional

Controls the letter case of the tags keys (label names) for tags generated by this module.
Does not affect keys of tags passed in via the tags input.
Possible values: lower, title, upper.
Default value: title.


Required: No

Default value: null

label_order (list(string)) optional

The order in which the labels (ID elements) appear in the id.
Defaults to ["namespace", "environment", "stage", "name", "attributes"].
You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present.


Required: No

Default value: null

label_value_case (string) optional

Controls the letter case of ID elements (labels) as included in id,
set as tag values, and output by this module individually.
Does not affect values of tags passed in via the tags input.
Possible values: lower, title, upper and none (no transformation).
Set this to title and set delimiter to &#34;&#34; to yield Pascal Case IDs.
Default value: lower.


Required: No

Default value: null

labels_as_tags (set(string)) optional

Set of labels (ID elements) to include as tags in the tags output.
Default is to include all labels.
Tags with empty values will not be included in the tags output.
Set to [] to suppress all generated tags.
Notes:
The value of the name tag, if included, will be the id, not the name.
Unlike other null-label inputs, the initial setting of labels_as_tags cannot be
changed in later chained modules. Attempts to change it will be silently ignored.


Required: No

Default value:

[
"default"
]
name (string) optional

ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'.
This is the only ID element not also included as a tag.
The "name" tag is set to the full id string. There is no tag with the value of the name input.


Required: No

Default value: null

namespace (string) optional

ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique
Required: No

Default value: null

regex_replace_chars (string) optional

Terraform regular expression (regex) string.
Characters matching the regex will be removed from the ID elements.
If not set, &#34;/[^a-zA-Z0-9-]/&#34; is used to remove all characters other than hyphens, letters and digits.


Required: No

Default value: null

stage (string) optional

ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release'
Required: No

Default value: null

tags (map(string)) optional

Additional tags (e.g. {&#39;BusinessUnit&#39;: &#39;XYZ&#39;}).
Neither the tag keys nor the tag values will be modified by this module.


Required: No

Default value: { }

tenant (string) optional

ID element (Rarely used, not included by default). A customer identifier, indicating who this instance of a resource is for
Required: No

Default value: null

Outputs

cloudwatch_event_rule_arn

The ARN of the CloudWatch Event Rule for GuardDuty findings

cloudwatch_event_rule_id

The ID of the CloudWatch Event Rule for GuardDuty findings

delegated_administrator_account_id

The AWS Account ID of the AWS Organization delegated administrator account

guardduty_delegated_detector_arn

The ARN of the GuardDuty detector from the delegated administrator account (via remote state)

guardduty_delegated_detector_id

The ID of the GuardDuty detector from the delegated administrator account (via remote state)

guardduty_detector_arn

The ARN of the GuardDuty detector created by the component in this account

guardduty_detector_id

The ID of the GuardDuty detector created by the component in this account

root_kms_key_alias

The alias of the KMS key used for encrypting the GuardDuty SNS topic

root_kms_key_arn

The ARN of the KMS key used for encrypting the GuardDuty SNS topic

root_kms_key_id

The ID of the KMS key used for encrypting the GuardDuty SNS topic

root_sns_topic_arn

The ARN of the root-level SNS topic created for GuardDuty findings

root_sns_topic_id

The ID of the root-level SNS topic created for GuardDuty findings

root_sns_topic_name

The name of the root-level SNS topic created for GuardDuty findings

root_sqs_queue_arn

The ARN of the SQS queue subscribed to the GuardDuty SNS topic

root_sqs_queue_name

The name of the SQS queue subscribed to the GuardDuty SNS topic

root_sqs_queue_url

The URL of the SQS queue subscribed to the GuardDuty SNS topic

sns_topic_name

The name of the SNS topic created for GuardDuty findings

sns_topic_subscriptions

The SNS topic subscriptions for GuardDuty findings

Dependencies

Requirements

  • terraform, version: >= 1.3.0
  • aws, version: >= 5.0, < 6.0.0
  • awsutils, version: >= 0.16.0, < 6.0.0

Providers

  • aws, version: >= 5.0, < 6.0.0
  • awsutils, version: >= 0.16.0, < 6.0.0

Modules

NameVersionSourceDescription
account_map1.8.0cloudposse/stack-config/yaml//modules/remote-staten/a
findings_label0.25.0cloudposse/label/nulln/a
guardduty1.0.0cloudposse/guardduty/awsIf we are are in the AWS Org designated administrator account, enable the GuardDuty detector and optionally create an SNS topic for notifications and CloudWatch event rules for findings. NOTE: We set create_sns_topic=false in the module and create our own SNS topic instead. This is because of https://github.com/cloudposse/terraform-aws-guardduty/issues/10 The module's SNS topic encryption doesn't grant EventBridge permission to decrypt messages.
guardduty_delegated_detector1.8.0cloudposse/stack-config/yaml//modules/remote-staten/a
iam_roleslatest../account-map/modules/iam-rolesn/a
kms_key0.12.2cloudposse/kms-key/awsKMS key for encrypting the GuardDuty SNS topic This is required because of https://github.com/cloudposse/terraform-aws-guardduty/issues/10 The default AWS-managed key doesn't grant EventBridge permission to decrypt messages.
queue_policy2.0.2cloudposse/iam-policy/awsn/a
sns_topic1.2.0cloudposse/sns-topic/awsn/a
sqs4.3.1terraform-aws-modules/sqs/awsSQS queue for GuardDuty findings This queue is subscribed to the SNS topic to receive GuardDuty findings
this0.25.0cloudposse/label/nulln/a

Resources

The following resources are used by this module:

Data Sources

The following data sources are used by this module: