Amazon GuardDuty Guide
Detect threats with GuardDuty: findings, multi-account setup, automated remediation, and Security Hub integration.
Prerequisites
- AWS account with administrative access
- Basic understanding of AWS security services
Introduction to GuardDuty
Amazon GuardDuty is a managed threat detection service that continuously monitors your AWS accounts and workloads for malicious activity and unauthorized behavior. It analyzes data from multiple AWS sources including CloudTrail management events, CloudTrail S3 data events, VPC Flow Logs, DNS logs, EKS audit logs, and Lambda network activity without requiring you to deploy or manage any infrastructure.
GuardDuty uses machine learning, anomaly detection, and integrated threat intelligence feeds (from AWS and third-party sources like CrowdStrike and Proofpoint) to identify threats. When it detects suspicious activity, it generates a finding with detailed context about what happened, which resource was affected, and the severity level. Findings can be sent to EventBridge for automated remediation, to Security Hub for centralized visibility, or to an S3 bucket for long-term storage.
This guide covers enabling GuardDuty, understanding finding types, configuring multi-account deployments, building automated remediation workflows, and integrating GuardDuty with your broader security posture.
30-Day Free Trial
GuardDuty offers a 30-day free trial with full functionality. After the trial, pricing is based on the volume of data analyzed: CloudTrail events, VPC Flow Logs, and DNS logs. The trial period shows your estimated monthly cost so you can evaluate before committing. Most accounts pay between $5-50/month depending on activity volume.
Enabling GuardDuty
Enabling GuardDuty is straightforward: a single API call activates it for the current region. However, GuardDuty is a regional service, so you must enable it in every region where you operate (and ideally in all regions to detect unauthorized activity in regions you do not normally use).
# Enable GuardDuty in the current region
aws guardduty create-detector \
--enable \
--finding-publishing-frequency FIFTEEN_MINUTES \
--data-sources '{
"S3Logs": {"Enable": true},
"Kubernetes": {"AuditLogs": {"Enable": true}},
"MalwareProtection": {"ScanEc2InstanceWithFindings": {"EbsVolumes": true}}
}'
# Enable GuardDuty in ALL regions
for region in $(aws ec2 describe-regions --query 'Regions[].RegionName' --output text); do
echo "Enabling GuardDuty in $region..."
aws guardduty create-detector --enable --region "$region" 2>/dev/null || true
done
# Verify GuardDuty is active
aws guardduty list-detectors --query 'DetectorIds[0]' --output text
# Get detector details
DETECTOR_ID=$(aws guardduty list-detectors --query 'DetectorIds[0]' --output text)
aws guardduty get-detector --detector-id "$DETECTOR_ID"Terraform Deployment
resource "aws_guardduty_detector" "main" {
enable = true
finding_publishing_frequency = "FIFTEEN_MINUTES"
datasources {
s3_logs {
enable = true
}
kubernetes {
audit_logs {
enable = true
}
}
malware_protection {
scan_ec2_instance_with_findings {
ebs_volumes {
enable = true
}
}
}
}
tags = {
Environment = "production"
Service = "security"
}
}
# Enable in multiple regions using provider aliases
provider "aws" {
alias = "us_west_2"
region = "us-west-2"
}
resource "aws_guardduty_detector" "us_west_2" {
provider = aws.us_west_2
enable = true
datasources {
s3_logs {
enable = true
}
}
}Understanding GuardDuty Findings
GuardDuty findings are organized by resource type and threat purpose. Each finding includes a type name following the pattern ThreatPurpose:ResourceType/ThreatName, a severity level (Low, Medium, or High), affected resource details, and actor information.
Finding Types by Category
| Category | Example Finding | What It Means |
|---|---|---|
| Reconnaissance | Recon:EC2/PortProbeUnprotectedPort | An EC2 instance port is being probed by a known attacker |
| Unauthorized Access | UnauthorizedAccess:IAMUser/ConsoleLoginSuccess.B | Successful console login from unusual location |
| Credential Exfiltration | UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration | EC2 instance credentials used from external IP |
| Cryptocurrency | CryptoCurrency:EC2/BitcoinTool.B!DNS | EC2 instance communicating with Bitcoin-related domains |
| Backdoor | Backdoor:EC2/C&CActivity.B!DNS | EC2 instance querying command-and-control server |
| Data Exfiltration | Exfiltration:S3/AnomalousBehavior | Unusual S3 API calls suggesting data theft |
| Kubernetes | PrivilegeEscalation:Kubernetes/PrivilegedContainer | Privileged container launched in EKS cluster |
# List recent findings
DETECTOR_ID=$(aws guardduty list-detectors --query 'DetectorIds[0]' --output text)
aws guardduty list-findings \
--detector-id "$DETECTOR_ID" \
--finding-criteria '{
"Criterion": {
"severity": {"Gte": 7},
"updatedAt": {"GreaterThan": 1709251200000}
}
}' \
--sort-criteria '{"AttributeName": "severity", "OrderBy": "DESC"}' \
--max-results 20
# Get detailed finding information
aws guardduty get-findings \
--detector-id "$DETECTOR_ID" \
--finding-ids "finding-id-1" "finding-id-2" \
--query 'Findings[].{Type:Type, Severity:Severity, Title:Title, Description:Description}'Sample Findings for Testing
You can generate sample findings to test your alerting and remediation pipelines without waiting for real threats. Use aws guardduty create-sample-findings to generate findings across all detection types. These are clearly marked as sample findings and will not trigger real security incidents in properly configured workflows.
Multi-Account GuardDuty with AWS Organizations
In an AWS Organizations environment, you should designate a delegated administrator account for GuardDuty. This account automatically manages GuardDuty for all member accounts, enabling centralized finding visibility without requiring manual invitation in each account.
# From the management account: delegate GuardDuty administration
aws guardduty enable-organization-admin-account \
--admin-account-id 111222333444
# From the delegated admin: auto-enable for new accounts
DETECTOR_ID=$(aws guardduty list-detectors --query 'DetectorIds[0]' --output text)
aws guardduty update-organization-configuration \
--detector-id "$DETECTOR_ID" \
--auto-enable \
--data-sources '{
"S3Logs": {"AutoEnable": true},
"Kubernetes": {"AuditLogs": {"AutoEnable": true}},
"MalwareProtection": {"ScanEc2InstanceWithFindings": {"EbsVolumes": {"AutoEnable": true}}}
}'
# List member accounts
aws guardduty list-members \
--detector-id "$DETECTOR_ID" \
--query 'Members[].{Account:AccountId, Status:RelationshipStatus}' \
--output tableTerraform Multi-Account Setup
# Delegated admin configuration
resource "aws_guardduty_organization_admin_account" "main" {
admin_account_id = var.security_account_id
}
resource "aws_guardduty_organization_configuration" "main" {
auto_enable_organization_members = "ALL"
detector_id = aws_guardduty_detector.main.id
datasources {
s3_logs {
auto_enable = true
}
kubernetes {
audit_logs {
enable = true
}
}
malware_protection {
scan_ec2_instance_with_findings {
ebs_volumes {
auto_enable = true
}
}
}
}
}Automated Remediation with EventBridge
The real power of GuardDuty comes from automated remediation. When GuardDuty generates a high-severity finding, you can trigger an EventBridge rule that invokes a Lambda function, Step Functions workflow, or SNS notification to respond automatically. Common remediation actions include isolating compromised EC2 instances, revoking IAM credentials, blocking suspicious IP addresses, and notifying the security team.
# Create an EventBridge rule for high-severity findings
aws events put-rule \
--name "guardduty-high-severity" \
--event-pattern '{
"source": ["aws.guardduty"],
"detail-type": ["GuardDuty Finding"],
"detail": {
"severity": [{"numeric": [">=", 7]}]
}
}' \
--description "Trigger on high-severity GuardDuty findings"
# Add a Lambda target for auto-remediation
aws events put-targets \
--rule "guardduty-high-severity" \
--targets '[
{
"Id": "remediation-lambda",
"Arn": "arn:aws:lambda:us-east-1:123456789012:function:guardduty-remediation"
},
{
"Id": "security-team-sns",
"Arn": "arn:aws:sns:us-east-1:123456789012:security-alerts"
}
]'Remediation Lambda Example
import boto3
import json
ec2 = boto3.client("ec2")
iam = boto3.client("iam")
def handler(event, context):
finding = event["detail"]
finding_type = finding["type"]
severity = finding["severity"]
print(f"Processing finding: {finding_type} (severity: {severity})")
# Isolate compromised EC2 instances
if "EC2" in finding_type and severity >= 8:
instance_id = finding["resource"]["instanceDetails"]["instanceId"]
isolate_instance(instance_id)
# Disable compromised IAM credentials
if "IAMUser" in finding_type and "CredentialExfiltration" in finding_type:
access_key_id = finding["resource"]["accessKeyDetails"]["accessKeyId"]
username = finding["resource"]["accessKeyDetails"]["userName"]
disable_access_key(username, access_key_id)
return {"statusCode": 200, "body": "Remediation completed"}
def isolate_instance(instance_id):
"""Replace security groups with an isolation SG that blocks all traffic."""
# Create or find isolation security group
vpc_id = ec2.describe_instances(
InstanceIds=[instance_id]
)["Reservations"][0]["Instances"][0]["VpcId"]
# Apply isolation security group (no inbound/outbound rules)
ec2.modify_instance_attribute(
InstanceId=instance_id,
Groups=["sg-isolation-group-id"]
)
print(f"Isolated instance {instance_id}")
def disable_access_key(username, access_key_id):
"""Disable a compromised IAM access key."""
iam.update_access_key(
UserName=username,
AccessKeyId=access_key_id,
Status="Inactive"
)
print(f"Disabled access key {access_key_id} for user {username}")Threat Intelligence and IP/Domain Lists
GuardDuty uses built-in threat intelligence feeds, but you can also provide your own trusted IP lists (to suppress findings from known safe IPs like your VPN endpoints) and threat IP lists (to generate findings when your resources communicate with known bad actors).
# Upload a trusted IP list (IPs that should not generate findings)
DETECTOR_ID=$(aws guardduty list-detectors --query 'DetectorIds[0]' --output text)
aws guardduty create-ip-set \
--detector-id "$DETECTOR_ID" \
--name "corporate-vpn-ips" \
--format TXT \
--location "s3://my-security-bucket/trusted-ips.txt" \
--activate
# Upload a threat intelligence list
aws guardduty create-threat-intel-set \
--detector-id "$DETECTOR_ID" \
--name "custom-threat-feed" \
--format TXT \
--location "s3://my-security-bucket/threat-ips.txt" \
--activate
# Create suppression rules for known false positives
aws guardduty create-filter \
--detector-id "$DETECTOR_ID" \
--name "suppress-internal-scanner" \
--action ARCHIVE \
--finding-criteria '{
"Criterion": {
"type": {"Eq": ["Recon:EC2/PortProbeUnprotectedPort"]},
"resource.instanceDetails.tags.value": {"Eq": ["security-scanner"]}
}
}'Security Hub Integration
GuardDuty findings are automatically sent to AWS Security Hub when both services are enabled. Security Hub provides a centralized dashboard that aggregates findings from GuardDuty, Inspector, Macie, Firewall Manager, and third-party tools. This gives your security team a single pane of glass for all security findings.
# Enable Security Hub (if not already enabled)
aws securityhub enable-security-hub \
--enable-default-standards
# View GuardDuty findings in Security Hub
aws securityhub get-findings \
--filters '{
"ProductName": [{"Value": "GuardDuty", "Comparison": "EQUALS"}],
"SeverityLabel": [{"Value": "HIGH", "Comparison": "EQUALS"}]
}' \
--sort-criteria '[{"Field": "LastObservedAt", "SortOrder": "desc"}]' \
--max-results 10Exporting and Analyzing Findings
For long-term analysis and compliance, configure GuardDuty to export findings to an S3 bucket. Exported findings can be queried with Athena, visualized in QuickSight, or ingested into a SIEM platform like Splunk, Datadog, or Elastic.
# Configure finding export to S3
DETECTOR_ID=$(aws guardduty list-detectors --query 'DetectorIds[0]' --output text)
aws guardduty create-publishing-destination \
--detector-id "$DETECTOR_ID" \
--destination-type S3 \
--destination-properties '{
"DestinationArn": "arn:aws:s3:::guardduty-findings-bucket",
"KmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/key-id"
}'
# GuardDuty statistics
aws guardduty get-findings-statistics \
--detector-id "$DETECTOR_ID" \
--finding-statistic-types COUNT_BY_SEVERITY \
--finding-criteria '{
"Criterion": {
"updatedAt": {"GreaterThan": 1709251200000}
}
}'Cost Optimization
GuardDuty costs are driven primarily by VPC Flow Log and CloudTrail event volume. To estimate costs before enabling, use the GuardDuty usage statistics API or check the estimated cost during the 30-day free trial. In most accounts, GuardDuty costs $5-50/month. The security value far exceeds this cost: detecting a cryptocurrency mining attack or credential exfiltration early can save thousands of dollars.
Key Takeaways
- 1GuardDuty analyzes CloudTrail, VPC Flow Logs, and DNS logs without deploying infrastructure.
- 2Findings follow the pattern ThreatPurpose:ResourceType/ThreatName with Low, Medium, or High severity.
- 3Multi-account deployment via Organizations provides centralized finding visibility.
- 4EventBridge rules enable automated remediation for high-severity findings.
Frequently Asked Questions
How much does GuardDuty cost?
Can GuardDuty detect insider threats?
Written by CloudToolStack Team
Cloud engineers and architects with hands-on experience across AWS, Azure, and GCP. We write guides based on real-world production patterns, not just documentation rewrites.
Disclaimer: This guide is for educational purposes. Cloud services change frequently; always refer to official documentation for the latest information. AWS, Azure, and GCP are trademarks of their respective owners.