CloudTrail & GuardDuty
๐ฅ Vibe Prompt
"Set up CloudTrail for all accounts, create an organization trail. Enable GuardDuty with automated response."
CloudTrail Setup
resource "aws_cloudtrail" "org_trail" {
name = "org-trail"
s3_bucket_name = aws_s3_bucket.cloudtrail.id
include_global_service_events = true
is_multi_region_trail = true
enable_log_file_validation = true
is_organization_trail = true
event_selector {
read_write_type = "All"
include_management_events = true
}
}
resource "aws_s3_bucket" "cloudtrail" {
bucket = "myorg-cloudtrail-logs"
}
resource "aws_s3_bucket_policy" "cloudtrail" {
bucket = aws_s3_bucket.cloudtrail.id
policy = jsonencode({
Statement = [{
Effect = "Allow"
Principal = { Service = "cloudtrail.amazonaws.com" }
Action = "s3:PutObject"
Resource = "${aws_s3_bucket.cloudtrail.arn}/AWSLogs/*"
Condition = {
StringEquals = { "s3:x-amz-acl" = "bucket-owner-full-control" }
}
}]
})
}
Key CloudTrail Events
# Console login (without MFA)
{ "eventName": "ConsoleLogin", "userIdentity": { ... }, "responseElements": { "ConsoleLogin": "Failure" } }
# Root activity
{ "userIdentity": { "type": "Root" }, "eventName": "..." }
# IAM policy change
{ "eventSource": "iam.amazonaws.com", "eventName": "PutRolePolicy" }
# S3 public access change
{ "eventSource": "s3.amazonaws.com", "eventName": "PutBucketAcl" }
GuardDuty
resource "aws_guardduty_detector" "main" {
enable = true
datasources {
s3_logs {
enable = true
}
kubernetes {
audit_logs {
enable = true
}
}
}
}
GuardDuty Finding Types
| Finding | Severity | What It Means | |---------|----------|---------------| | CryptoCurrency:EC2/BitcoinTool.B!DNS | High | EC2 mining crypto | | Backdoor:EC2/C&CActivity.B!DNS | High | Malware C&C | | UnauthorizedAccess:IAM/User.IAMUser | Medium | Suspicious IAM | | Policy:IAM/User/RootCredentialUsage | High | Root user activity | | Recon:EC2/PortProbeUnprotected | Low | Port scanning |
Automated Response
import boto3
def lambda_handler(event, context):
finding = event['detail']['finding']
finding_type = finding['type']
resource_arn = finding['resource']['arn']
severity = finding['severity']
if severity >= 7: # HIGH or CRITICAL
if 'EC2' in finding_type:
# Isolate the instance
ec2 = boto3.client('ec2')
instance_id = resource_arn.split('/')[-1]
ec2.modify_instance_attribute(
InstanceId=instance_id,
Groups=['sg-quarantine']
)
print(f"Isolated {instance_id} in quarantine SG")
elif 'IAM' in finding_type:
# Disable the key
iam = boto3.client('iam')
iam.update_access_key(
UserName=finding['resource']['accessKeyDetails']['userName'],
AccessKeyId=finding['resource']['accessKeyDetails']['accessKeyId'],
Status='Inactive'
)
print("Disabled compromised access key")
GuardDuty + Security Hub
GuardDuty โ Security Hub โ EventBridge โ Lambda (auto-remediate)
โ
Slack notification
โ
PagerDuty (SEV-1/2)
Best Practices
- Enable CloudTrail in all regions
- Create organization trail (single log bucket)
- Enable log file validation (integrity)
- Enable GuardDuty in all accounts
- Set up automated response for critical findings
- Integrate with Security Hub for dashboard