The Challenge

Startups focus on shipping product. AWS account hygiene falls behind. The root account has no MFA. There are IAM users with admin access that haven't logged in for a year, with active access keys. CloudTrail is enabled in us-east-1 but not in the regions where you're actually deploying workloads. GuardDuty was enabled once during an investor security review but nobody configured alert routing, so findings sit in a dashboard nobody checks.

This isn't negligence — it's prioritization. Security configuration isn't a revenue-generating activity, and in the early stages every engineer hour is precious. The problem is that the cost of a security incident at this stage can be existential. A compromised AWS credential running crypto mining can generate a $30,000 bill before anyone notices. A data breach at Series A stage can kill a fundraise. The security fundamentals we implement here take a few days and provide coverage that would take months to investigate and remediate if ignored.

The goal is implementing controls that give you detection, logging, and hardening without slowing down your engineering team's day-to-day work. All changes are implemented via Terraform — no undocumented console changes, no configuration that disappears when an engineer leaves.

Signs You Need This

  • Your root AWS account has no MFA enabled — this is a single-point-of-failure for your entire cloud environment
  • GuardDuty is either not enabled or enabled but with no alert routing configured
  • CloudTrail is enabled in only one region, or the log bucket has no integrity validation
  • You have IAM users with access keys that haven't been rotated in over 90 days
  • You have no real-time visibility into who is making API calls in your AWS account
  • Security findings would go unnoticed for days or weeks before anyone investigated them

How We Approach It

01

Account-Level Hardening

We start with the fundamentals that take the least time and have the most impact: root account MFA enforced, root account access keys deleted, account contact information (security, billing, operations) set to reach the right people. IAM password policy configured with minimum length of 14 characters, MFA requirement for console access, and 90-day rotation policy. We audit and remove or deactivate IAM users that haven't been used in 90+ days — unused credentials with admin access are a common attack vector.

02

CIS AWS Foundations Benchmark

We implement the CIS AWS Foundations Benchmark Level 1 controls — the industry-standard security baseline covering IAM configuration, multi-region CloudTrail, logging on S3 bucket access, KMS key rotation, VPC flow logging, and alerting on specific high-risk API calls (root login, security group changes, CloudTrail configuration changes). All 51+ Level 1 controls are implemented in Terraform modules so they can be applied consistently across environments and reviewed in code review.

03

GuardDuty, CloudTrail & AWS Config in All Regions

GuardDuty detects threats using ML and threat intelligence feeds — cryptocurrency mining on compromised EC2 instances, compromised credentials making unusual API calls, reconnaissance activity like unusual S3 bucket enumeration, and DNS-based C2 communication. CloudTrail logs every API call across all regions with S3 log integrity validation so tampering is detectable. AWS Config records resource configuration at every change — who changed what, when, and from what to what. All three must be active in every region you use, not just your primary region.

The Terraform to enable GuardDuty across all regions with a delegated administrator account:

infra/modules/security/guardduty.tfTERRAFORM
resource "aws_guardduty_detector" "main" {
  enable = true

  datasources {
    s3_logs { enable = true }
    kubernetes { audit_logs { enable = true } }
    malware_protection {
      scan_ec2_instance_with_findings {
        ebs_volumes { enable = true }
      }
    }
  }

  tags = {
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

# Multi-region: repeat per region using provider aliases
# Enable threat intelligence feed (known malicious IPs)
resource "aws_guardduty_ipset" "threat_intel" {
  activate    = true
  detector_id = aws_guardduty_detector.main.id
  format      = "TXT"
  location    = "s3://${aws_s3_bucket.threat_intel.bucket}/known-bad-ips.txt"
  name        = "NovaGuardThreatIntel"
}

# CloudTrail with integrity validation
resource "aws_cloudtrail" "main" {
  name                          = "org-cloudtrail"
  s3_bucket_name                = aws_s3_bucket.cloudtrail_logs.bucket
  include_global_service_events = true
  is_multi_region_trail         = true
  enable_log_file_validation    = true   # SHA-256 digest per log file

  event_selector {
    read_write_type           = "All"
    include_management_events = true

    data_resource {
      type   = "AWS::S3::Object"
      values = ["arn:aws:s3:::"]    # Log all S3 object-level events
    }
  }
}
04

Security Hub with CIS & Foundational Standards

Security Hub aggregates findings from GuardDuty, Inspector, Macie, IAM Access Analyzer, and Config into a single prioritized view. We enable the AWS Foundational Security Best Practices (FSBP) standard and the CIS Benchmark standard, giving you a continuous compliance score across 200+ controls. Each finding has a severity, a specific resource, and a remediation recommendation. The alternative — checking GuardDuty, Config, Inspector, and IAM Access Analyzer separately — means most findings get missed.

05

Alert Routing to Slack via EventBridge + SNS

Security findings are useless if nobody sees them. We configure EventBridge rules for GuardDuty HIGH and CRITICAL severity findings, routing through SNS to your Slack security channel. We build structured Slack messages that include the finding title, affected resource ARN, severity, account and region, and a direct deep-link to the finding in the Security Hub console. Runbook links in the alert message mean the person who gets paged knows what to do — not just that something is wrong.

infra/modules/security/alerts.tfTERRAFORM
# EventBridge rule: catch GuardDuty HIGH + CRITICAL findings
resource "aws_cloudwatch_event_rule" "guardduty_high" {
  name        = "guardduty-high-critical-findings"
  description = "Route HIGH and CRITICAL GuardDuty findings to Slack"

  event_pattern = jsonencode({
    source      = ["aws.guardduty"]
    detail-type = ["GuardDuty Finding"]
    detail = {
      severity = [{ numeric = [">=", 7] }]   # 7.0+ = HIGH, 9.0+ = CRITICAL
    }
  })
}

resource "aws_cloudwatch_event_target" "to_sns" {
  rule      = aws_cloudwatch_event_rule.guardduty_high.name
  target_id = "SendToSNS"
  arn       = aws_sns_topic.security_alerts.arn

  # Transform the raw GuardDuty finding into a structured Slack message
  input_transformer {
    input_paths = {
      severity    = "$.detail.severity"
      finding_type = "$.detail.type"
      account     = "$.account"
      region      = "$.region"
      resource    = "$.detail.resource.resourceType"
      finding_id  = "$.detail.id"
    }
    input_template = <<-EOT
      {
        "text": "*[GuardDuty Alert]* <finding_type>",
        "attachments": [{
          "color": "danger",
          "fields": [
            {"title": "Severity", "value": "<severity>", "short": true},
            {"title": "Account", "value": "<account>", "short": true},
            {"title": "Region",  "value": "<region>",  "short": true},
            {"title": "Resource","value": "<resource>", "short": true}
          ],
          "footer": "Console: https://console.aws.amazon.com/guardduty/home?region=<region>#/findings?macros=current&fId=<finding_id>"
        }]
      }
    EOT
  }
}

What a Real GuardDuty Finding Looks Like

When GuardDuty fires on a compromised credential, the finding contains everything needed to triage and respond — the actor IP, affected IAM principal, and API calls made:

GuardDuty Finding — Credential Exfiltration (HIGH)JSON
{
  "schemaVersion": "2.0",
  "id": "f2b9d4c1a3e57890abcdef12345",
  "type": "UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration.OutsideAWS",
  "severity": 8.0,
  "createdAt": "2025-11-14T03:22:18.000Z",
  "description": "EC2 instance credentials are being used from an external IP address.",
  "service": {
    "action": {
      "actionType": "AWS_API_CALL",
      "awsApiCallAction": {
        "api": "GetSecretValue",
        "serviceName": "secretsmanager.amazonaws.com",
        "remoteIpDetails": {
          "ipAddressV4": "185.220.101.47",   // Known Tor exit node
          "country": { "countryName": "Germany" },
          "organization": { "asn": "396356", "asnOrg": "Tor Project" }
        }
      }
    },
    "resourceRole": "TARGET",
    "affectedResources": {
      "AccessKeyDetails": {
        "accessKeyId": "ASIA3EXAMPLE123456",
        "principalId": "AROA3EXAMPLEROLEID:i-0abc123def456",
        "userType": "AssumedRole",
        "userName": "ecs-task-role/production-api"
      }
    }
  }
}

# Immediate response runbook:
# 1. Revoke active sessions for the role:
aws iam update-assume-role-policy --role-name production-api \
  --policy-document '{"Version":"2012-10-17","Statement":[]}'
# 2. Identify which secrets were accessed: CloudTrail + Secrets Manager audit log
# 3. Rotate all secrets the role had access to
# 4. Investigate the EC2 instance for the initial compromise vector

Tools We Use

Everything is AWS-native where possible, reducing cost and operational overhead. All configured via Terraform for repeatability.

AWS GuardDuty AWS CloudTrail AWS Config AWS Security Hub AWS Inspector IAM Access Analyzer EventBridge SNS Terraform

Common Mistakes We Prevent

  • Enabling GuardDuty only in the primary region — GuardDuty must be enabled in every region to detect threats from resources running there
  • Setting up Security Hub without enabling specific standards — Security Hub without the FSBP or CIS standard enabled gives you a finding aggregator but no automated compliance scoring
  • Creating CloudTrail logs without enabling S3 bucket integrity validation — without log file validation, a sophisticated attacker can modify or delete CloudTrail logs and you'd have no way to detect it
  • Routing all Security Hub findings to Slack regardless of severity — LOW severity findings in Slack create alert fatigue that causes HIGH severity findings to be ignored

Most impactful quick win: Enabling GuardDuty and routing HIGH/CRITICAL findings to Slack takes under two hours and immediately surfaces active threats that may have been present for months without detection. In our experience, roughly 30% of AWS accounts we do this for have at least one active GuardDuty finding on day one of enablement.

What You Get

  • Hardened AWS account configuration aligned with CIS AWS Foundations Benchmark Level 1
  • GuardDuty enabled and configured in all active regions with threat intelligence feeds enabled
  • Multi-region CloudTrail with S3 log bucket, integrity validation, and 90-day retention
  • AWS Config rules for continuous compliance monitoring across critical controls
  • Security Hub with FSBP and CIS Benchmark standards enabled, findings aggregated
  • EventBridge + SNS + Slack alert routing for HIGH/CRITICAL findings with runbook links
  • IAM Access Analyzer enabled with findings reviewed and addressed
  • All configuration implemented in Terraform with documentation for your team

Timeline & What to Expect

Day 1 Account hardening (root MFA, password policy, IAM user audit), access key rotation for stale credentials
Day 2 GuardDuty enablement in all regions, CloudTrail multi-region trail setup, S3 log bucket with integrity validation
Day 3 AWS Config rules, Security Hub setup with FSBP + CIS standards, IAM Access Analyzer enablement
Day 4 EventBridge alert routing, Slack integration, runbook creation, initial finding triage, Terraform documentation

After the 4-day implementation, your account has active threat detection and compliance monitoring. Day 5 is a review session where we walk through all initial Security Hub findings with your team, triage them by severity, and create a remediation plan for any existing issues found during implementation.

Frequently Asked Questions

Is GuardDuty enough on its own?

GuardDuty is an excellent threat detection layer, but it's not a complete security baseline. GuardDuty detects active threats; AWS Config detects configuration drift; Security Hub aggregates both alongside Inspector and other services; CloudTrail provides the audit log. Each serves a different purpose. GuardDuty alone with no CloudTrail is like having a burglar alarm but no security camera — you know something happened but have no investigation capability.

How many false positives will we get?

GuardDuty has a very low false positive rate compared to traditional SIEM tools because it uses behavioral baselines and threat intelligence rather than static rules. In a stable environment, you might see 2–5 findings per week, most of which are LOW severity and informational. HIGH and CRITICAL findings require investigation but are rare in clean environments — typically 0–2 per month. We configure alert routing to only page on HIGH/CRITICAL so your team isn't inundated.

What does a typical finding look like?

A common HIGH severity finding is "UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration.OutsideAWS" — an EC2 instance's IAM role credentials were used from an IP address outside AWS, indicating likely credential theft. The finding includes the IAM principal, the API calls made, the source IP, and the timeframe. The runbook for this finding: immediately revoke the role's sessions, rotate any secrets the role had access to, investigate the EC2 instance for compromise, and trace the credential path to understand how exfiltration occurred.

When This Is the Right Fit

This engagement is right for any AWS-hosted startup that hasn't systematically configured security fundamentals, for teams that have received security questionnaires from enterprise customers asking about your cloud security controls, or for teams preparing for a SOC2 audit where GuardDuty, CloudTrail, and Config are commonly required controls. It's also a natural follow-on to a cloud security audit — we often implement these controls as part of the remediation phase after an audit engagement.

This is not a replacement for a security audit — it implements the detection and monitoring layer, but doesn't assess what vulnerabilities already exist in your environment. For a comprehensive picture of your current risk, pair this engagement with a cloud security audit. The audit finds what's already wrong; the security baseline ensures you detect what happens next.