The security monitoring gap your CloudWatch alarms don't cover
A team with a dozen well-tuned CloudWatch alarms on CPU, memory, and 5xx rates can still have zero alarms for a compromised IAM credential, a public S3 bucket, or root account login. Infrastructure alarms and security alarms are built from completely different data sources — and only one of them is on by default. Here's the gap, what it costs to close, and the specific alarms worth setting up first.
- What's the security monitoring gap in most AWS accounts?
- Enable GuardDuty first — what it actually costs
- GuardDuty findings don't page anyone by default
- The CIS-recommended CloudWatch alarms most teams don't have
- Wiring a CloudTrail alarm end to end
- What to enable this week
What's the security monitoring gap in most AWS accounts?
CloudWatch's built-in AWS/* namespaces (EC2, ECS, RDS, Lambda) give you infrastructure metrics automatically. Security signals don't work the same way: GuardDuty is opt-in per account and region, and AWS CloudTrail — which records every API call — logs to S3 by default without alerting anyone unless you explicitly wire it to CloudWatch. A team can have thorough infrastructure alarm coverage and simultaneously have no alarm at all for a leaked access key being used from an unfamiliar country.
Enable GuardDuty first — what it actually costs
GuardDuty is Amazon's threat detection service — it analyzes CloudTrail management events, VPC Flow Logs, and DNS query logs for signs of compromise (unusual API call patterns, traffic to known-malicious IPs, credential exfiltration signatures) without you having to write any detection logic yourself.
| What's analyzed | Price |
|---|---|
| CloudTrail management events | Billed per 1 million events/month |
| VPC Flow Logs + DNS logs — first 500 GB/month | $1.00/GB |
| VPC Flow Logs + DNS logs — next 2,000 GB/month | $0.50/GB |
| VPC Flow Logs + DNS logs — next 7,500 GB/month | $0.25/GB |
| VPC Flow Logs + DNS logs — over 10,000 GB/month | $0.15/GB |
Every AWS account gets a 30-day free trial the first time GuardDuty is enabled, and the console shows an estimated daily cost during the trial before you commit to paying for it — enable it, watch the trial estimate for a week, and decide from real numbers instead of guessing.
GuardDuty findings don't page anyone by default
Enabling GuardDuty alone doesn't create an alarm. Findings publish automatically to Amazon EventBridge, and it's on you to add an EventBridge rule that routes findings (or findings above a severity threshold) to an SNS topic, Slack webhook, or Lambda function. Skip this step and GuardDuty accumulates findings silently in a console tab nobody checks until an audit or an incident sends them looking.
# Route GuardDuty findings of Medium severity or higher to an SNS topic
aws events put-rule \
--name guardduty-to-sns \
--event-pattern '{"source":["aws.guardduty"],"detail":{"severity":[{"numeric":[">=", 4.0]}]}}'
aws events put-targets \
--rule guardduty-to-sns \
--targets "Id"="1","Arn"="arn:aws:sns:REGION:ACCOUNT_ID:security-alerts"The CIS-recommended CloudWatch alarms most teams don't have
The CIS AWS Foundations Benchmark dedicates a full monitoring section to CloudWatch alarms built from CloudTrail activity via CloudWatch Logs metric filters — around 14 categories in total. Most small teams have implemented none of them, because none of these alarms exist until someone deliberately creates the metric filter.
| Alarm category | Why it matters |
|---|---|
| Root account usage | The root account should almost never be used day-to-day — any use is worth investigating |
| Unauthorized API calls | A spike in access-denied errors often means compromised credentials or an attacker probing your account |
| Console sign-in without MFA | Flags accounts that can authenticate with a password alone |
| IAM policy changes | Privilege escalation usually starts with a policy edit, not a login |
| CloudTrail configuration changes | An attacker's first move is often disabling the logging that would catch them |
| S3 bucket policy changes | The most common path to an accidentally public bucket |
| Security group changes | Catches an inbound rule opened to 0.0.0.0/0 before it's exploited, not after |
| CMK disabling or deletion | A KMS key deletion is a 7-30 day irreversible countdown — you want to know immediately |
As a concrete example, the CIS-recommended metric filter pattern for detecting root account usage is:
{ $.userIdentity.type = "Root" && $.userIdentity.invokedBy NOT EXISTS && $.eventType != "AwsServiceEvent" }Wiring a CloudTrail alarm end to end
The pattern is the same for every category above: CloudTrail must already be logging to a CloudWatch Logs log group (not just S3), then a metric filter turns matching log entries into a CloudWatch metric, then a standard CloudWatch alarm fires on that metric like any other.
- Confirm your CloudTrail trail delivers to a CloudWatch Logs log group — this isn't the default until you configure it in the trail settings.
- Create a metric filter on that log group with the CIS-recommended pattern for the event you're targeting.
- Create a CloudWatch alarm on the resulting metric — threshold ≥ 1 over a 5-minute period is standard for security events, since even one occurrence is worth a look.
- Point the alarm at an SNS topic your team actually monitors — the same one your infrastructure alarms use, or a dedicated #security-alerts channel.
What to enable this week
- Turn on GuardDuty in every account and region you run workloads in — use the 30-day trial to see real cost before committing.
- Add one EventBridge rule routing GuardDuty findings (Medium severity and above) to the SNS topic your team already watches.
- Confirm CloudTrail is delivering to CloudWatch Logs, not just S3 — check trail settings if you're not sure.
- Start with three metric filter alarms: root account usage, unauthorized API calls, and security group changes — the three with the fastest blast radius if missed.
Frequently asked questions
Is GuardDuty on by default in AWS accounts?
No. GuardDuty is opt-in per AWS account and region. It must be manually enabled — it doesn't start analyzing CloudTrail events, VPC Flow Logs, or DNS logs until you turn it on.
How much does Amazon GuardDuty cost?
GuardDuty bills CloudTrail management event analysis per 1 million events/month, and VPC Flow Log plus DNS log analysis on a tiered per-GB basis: $1.00/GB for the first 500 GB/month, $0.50/GB for the next 2,000 GB, $0.25/GB for the next 7,500 GB, and $0.15/GB above 10,000 GB. Every account gets a 30-day free trial the first time it's enabled, with a cost estimate shown in the console during the trial.
Does GuardDuty send alerts automatically?
No. GuardDuty publishes findings to Amazon EventBridge, but nothing notifies your team until you add an EventBridge rule routing findings (typically filtered by severity) to an SNS topic, Slack webhook, or Lambda function. Without that rule, findings accumulate silently in the GuardDuty console.
What are the CIS AWS Foundations Benchmark CloudWatch alarms?
A set of around 14 recommended CloudWatch alarms built from CloudTrail activity via CloudWatch Logs metric filters, covering events like root account usage, unauthorized API calls, console sign-in without MFA, IAM policy changes, CloudTrail configuration changes, S3 bucket policy changes, security group changes, and CMK disabling or deletion.
What threshold should security CloudWatch alarms use?
Almost always 1 occurrence over a short period (commonly 5 minutes), unlike infrastructure alarms that use percentage or sustained-duration thresholds. A single root account login or CloudTrail configuration change is worth investigating immediately, not waiting for a recurring pattern.
Related reading
Not sure your alarm coverage is actually solid?
Run a free Nuberio Audit — hygiene score, missing alarms, and security findings in about 5 minutes.