SaveMyCert
Log in
5 of 5 free questions left today·for unlimited practice
Detection

Troubleshooting Security Monitoring, Logging, and Alerting on AWS

14 min readSCS-C03 · DetectionUpdated

When a security signal goes missing on AWS, the failure is almost always at one of four stages: the source never generated the event, a delivery permission was revoked, the destination refused or could not decrypt the write, or the consumer — a rule, alarm, or subscriber — silently failed to match or lacked permission to act. Task 1.3 tests whether you can walk that chain deliberately instead of guessing. This lesson gives you the triage method and then applies it to the classic breakages: CloudTrail trails that stop delivering after a bucket-policy or KMS change, VPC Flow Logs that never appear, CloudWatch Logs subscription chains with a broken link, GuardDuty muted by suppression rules or a disabled Region, Security Hub findings that never reach the aggregation Region, EventBridge rules that never fire, alarms that never page, and a stopped AWS Config recorder. Designing these pipelines belongs to Tasks 1.1 and 1.2 — here, you fix them.

What you’ll learn
  • Apply a four-stage triage method — source, delivery, destination permissions, consumer — to any broken monitoring pipeline
  • Diagnose CloudTrail delivery failures caused by S3 bucket policy, KMS key policy, missing data event selectors, or organization-trail access
  • Trace missing VPC Flow Logs and CloudWatch Logs subscription failures to the IAM role, resource policy, or destination at fault
  • Explain why GuardDuty and Security Hub stay silent: disabled Regions, suppression rules, trusted IP lists, disabled controls, and aggregation misconfiguration
  • Debug EventBridge and alarm pipelines end to end, including event-pattern mismatches, wrong-Region buses, unconfirmed SNS subscriptions, and KMS-encrypted topic permissions
  • Recognize when a stopped Config recorder or failed delivery channel is the reason compliance detection went stale

A systematic triage method for broken security pipelines

Triage every broken detection pipeline in the same order: source → delivery → destination permissions → consumer. First, confirm the event was generated at all — is the trail logging, is GuardDuty enabled in that Region, did the API call actually happen there? Second, check delivery: does the producing service still hold the permissions it needs to write, and is the delivery role or resource policy intact? Third, check the destination: does its bucket policy, log group resource policy, or KMS key policy still allow the writing principal, and does the destination still exist under the same name? Fourth, check the consumer: does the EventBridge pattern actually match the real event JSON, is the rule enabled and in the right Region, is the alarm on the right statistic, is the subscription confirmed and allowed to receive? Working in this order matters because later stages fail silently — a rule that matches nothing raises no error anywhere.

SymptomFirst place to look
CloudTrail objects stopped arriving in S3LatestDeliveryError in trail status; bucket policy and KMS key policy for cloudtrail.amazonaws.com
No S3 object-level or Lambda invoke events in CloudTrailData event selectors — data events are not logged by default
VPC Flow Log empty or erroredDelivery IAM role and destination permissions; distinguish NODATA from SKIPDATA
GuardDuty silent in one RegionIs the detector enabled there; suppression rules; trusted IP lists
Findings absent from the aggregation RegionSecurity Hub cross-Region aggregation and linked-Region configuration
EventBridge rule never firesRule Region versus the finding's Region; event pattern versus real finding JSON
Alarm never paged anyoneMetric filter pattern and casing; alarm statistic and period; SNS subscription state; topic KMS key policy
Compliance data staleConfig recorder status and delivery channel

Why CloudTrail logs go missing or arrive incomplete

CloudTrail stops delivering for one of five reasons: the trail was stopped, the S3 bucket policy no longer allows CloudTrail, the KMS key policy denies it, the bucket was deleted or renamed, or the events you expect were never in scope. Start with the trail status: it reports whether the trail is logging and surfaces LatestDeliveryError. If logging is off, someone called StopLogging — check CloudTrail's own management events for who. If logging is on but delivery errors show access denied, inspect the bucket policy: CloudTrail needs s3:GetBucketAcl on the bucket and s3:PutObject on the AWSLogs/ prefix, granted to the principal cloudtrail.amazonaws.com, with the bucket-owner-full-control ACL condition. If the trail uses SSE-KMS, the customer managed key's policy must also allow cloudtrail.amazonaws.com to call kms:GenerateDataKey* — tighten that key policy and delivery stops immediately even though the bucket policy is untouched. A deleted or renamed bucket produces a no-such-bucket delivery error; the trail keeps pointing at the old name until you update it.

Incomplete logs are usually a scope problem, not a delivery problem. Trails record management events by default; S3 object-level operations and Lambda invocations are data events and are only logged when you enable them through event selectors. If an investigation finds no record of an object being read, check the selectors before suspecting tampering. Finally, with an organization trail, logs from every member account land in the central bucket under per-account prefixes — member-account engineers can see the trail exists but have no access to that bucket by default, so "missing" logs are often an access-model misunderstanding rather than a delivery failure.

Walkthrough: CloudTrail stopped delivering after a bucket-policy change

Here is the method applied to the most common Task 1.3 scenario. The security team hardened the central logging bucket's policy last Tuesday; today an analyst notices no new CloudTrail objects since exactly that change. Source: the trail status shows logging is still on, so events are being recorded — the source is healthy, and the gap is downstream. Delivery: LatestDeliveryError reports an access-denied error against the bucket, which localizes the fault precisely. Destination permissions: diff the bucket policy against its previous version. The hardening added an aws:SourceArn condition to the CloudTrail statements, but it referenced the wrong trail ARN — so the statements granting cloudtrail.amazonaws.com the s3:GetBucketAcl and s3:PutObject permissions now never match, and every delivery attempt is refused. This is the signature failure mode of well-intentioned confused-deputy hardening: aws:SourceArn and aws:SourceAccount conditions are correct practice, but one wrong account ID or trail name silently severs delivery. Fix and verify: correct the condition value, then confirm new objects arrive and the delivery error clears from the trail status. CloudTrail retries failed deliveries for a limited period, so a prompt fix typically backfills the gap — but treat the outage window as unverified and reconcile against CloudTrail Lake or Event history, which are unaffected by S3 delivery failures. The exam-relevant lesson: a trail that says it is logging can still be delivering nothing, and the delivery error string tells you which stage to inspect — never start by rebuilding the trail.

Diagnosing missing VPC Flow Logs and CloudWatch Logs delivery failures

A VPC Flow Log that shows nothing has one of three problems: broken delivery permissions, a destination that refuses the write, or traffic that was never eligible for capture. When the destination is CloudWatch Logs, delivery runs through an IAM role that must trust vpc-flow-logs.amazonaws.com and allow logs:CreateLogGroup, logs:CreateLogStream, and logs:PutLogEvents; if the role or its trust policy is edited, the flow log's delivery status reports the failure. When the destination is S3, there is no role — the log delivery service writes directly, and the bucket policy must allow delivery.logs.amazonaws.com. Read the records themselves before declaring a fault: NODATA means there was simply no traffic in the aggregation interval, while SKIPDATA means records were skipped because of a capacity constraint or internal error. And some absences are by design — flow logs never capture instance metadata traffic to 169.254.169.254, DHCP, or DNS queries to the Amazon-provided resolver, so do not chase those as delivery bugs.

CloudWatch Logs has two permission surfaces of its own. Services that deliver logs into a log group — Route 53 Resolver query logging, for example — require a log group resource policy naming the service principal; without it, delivery is refused. Downstream, subscription filters forward log events to Kinesis Data Streams, Firehose, or Lambda, and each target has a different permission chain: streams and Firehose need an IAM role that CloudWatch Logs assumes to put records, while Lambda needs a resource-based policy allowing the CloudWatch Logs service principal to invoke it. When logs land in the group but never reach the SIEM, the subscription filter's role or the target's policy is the broken link.

Why GuardDuty findings never appear

GuardDuty stays silent for four reasons, and only one of them is "there was no threat." First, GuardDuty is a Regional, per-account service: the detector must be enabled in every Region of every account, and activity in a Region where the detector is disabled generates nothing at all. Attackers deliberately operate in unmonitored Regions, so an org-wide, all-Region enablement check is the first diagnostic step when findings seem thin. Second, suppression rules auto-archive matching findings — GuardDuty still generates them, but they go straight to the archive and never surface to your downstream consumers, so a suppression rule written too broadly (for example, matching an entire severity range or a whole CIDR block) mutes real detections invisibly. Review suppression rules whenever a finding type you expect simply never shows up. Third, trusted IP lists tell GuardDuty not to generate findings for traffic involving the listed addresses; an over-broad list — a corporate range that also contains a compromised host — blinds detection for exactly the traffic you care about. Fourth, feature-specific findings require their protection plan to be enabled: no S3 Protection means no S3-specific findings, no Malware Protection means no malware scan results, and the same holds for the EKS, RDS, and Lambda plans — each is enabled per account and per Region. In an organization, also confirm the member account is actually enabled under the delegated administrator, not merely invited. The diagnostic order mirrors the triage method: is the detector on (source), is anything archiving or excluding it (suppression, trusted IPs), and is the specific detection capability licensed on (protection plan)?

Security Hub gaps: disabled controls and aggregation misconfiguration

When Security Hub shows fewer findings than reality, check four settings in order: standards, controls, integrations, and aggregation. A security standard must be enabled before any of its controls evaluate, and individual controls can be disabled per account and Region — a disabled control produces no compliance findings, so a resource can drift out of compliance with nothing on the dashboard. Disabling noisy controls is legitimate tuning, but it is also the first thing to audit when a known-bad configuration shows no finding. Next, integrations: Security Hub only receives findings from products whose integration is enabled. If the GuardDuty integration is off, GuardDuty findings exist in GuardDuty but never appear in Security Hub. Third-party tools send findings in AWS Security Finding Format (ASFF) through the batch-import API; findings that are not valid ASFF are rejected at ingest, so a partner product that "stopped reporting" may be sending malformed payloads rather than nothing.

Cross-Region gaps are their own class. Security Hub findings live in the Region where they were created; cross-Region aggregation replicates them to a single aggregation Region you designate, from linked Regions you specify. If the console looks empty, confirm you are in the aggregation Region, that the source Region is actually linked, and — in an organization — that you are looking at the delegated administrator account, which is the only place member-account findings roll up. A finding created in a Region outside the linked set will never replicate, which reads as "Security Hub lost my finding" but is purely configuration. Note that aggregation moves Security Hub findings only; it does not move the underlying service's events, which matters for the alerting failure covered next.

Walkthrough: a GuardDuty finding never paged on-call

Second walkthrough, same method. A high-severity GuardDuty finding appeared in us-west-2 on Saturday; on-call was never paged. The alert pipeline is an EventBridge rule targeting an SNS topic, built in us-east-1. Source: the finding exists in the GuardDuty console in us-west-2, so detection worked — and it was not suppressed, since suppressed findings land in the archive. Consumer, part one — Region: GuardDuty emits finding events to the default event bus in the Region where the finding was generated. The only rule lives in us-east-1, so the us-west-2 event met no rule at all. This is the single most common alerting gap: detection is multi-Region, alerting is single-Region. The fix is to deploy the rule in every Region where detectors run, or forward events cross-Region to a central bus. Consumer, part two — pattern: even in the right Region, the rule must match the real finding JSON. Event patterns are exact: a pattern matching severity as the string "8" never matches the numeric 8 in the actual event, a wrong source or detail-type value matches nothing, and a disabled rule matches everything and does nothing. Test with GuardDuty's sample findings rather than waiting for a real one. Consumer, part three — target: the SNS topic's access policy must allow events.amazonaws.com to publish; a Lambda target needs a resource-based permission for EventBridge; a cross-account bus needs a bus policy. Any of these fails silently — EventBridge records a failed invocation metric, but nothing pages you about your paging pipeline. Alarm on that metric.

Metric filters, alarm math, encrypted SNS topics, and the Config recorder

An alarm that never fires usually failed at the filter, the math, or the notification hop — in that order. Metric filters are literal and case-sensitive: a filter watching for "UnauthorizedOperation" will not match "unauthorizedOperation", and term-based patterns match whole terms, so verify the pattern against real log lines with the filter-testing tools before trusting it. Filters also apply only to log events ingested after the filter exists — they never backfill, so a freshly created filter proves nothing about last week. Alarm math comes next: a count-style metric alarmed on Average instead of Sum may never cross its threshold, a long period smooths a short burst below the line, and because a metric filter emits no datapoint at all when nothing matches, the missing-data treatment decides whether silence reads as OK, alarm, or insufficient data. The notification hop hides two classics. An email or HTTPS subscription stuck in pending-confirmation delivers nothing until confirmed — the alarm fires, SNS accepts the publish, the subscriber hears silence. And a topic encrypted with a KMS key silently rejects publishes from CloudWatch alarms or EventBridge unless the key policy grants the publishing service kms:GenerateDataKey* and kms:Decrypt; the AWS managed aws/sns key cannot be used for this because its policy is not editable, so encrypted alerting topics must use a customer managed key. Finally, AWS Config: if the configuration recorder is stopped, resource changes go unrecorded and rules stop evaluating changes, so compliance dashboards quietly freeze at their last state; if the delivery channel's bucket policy or KMS key breaks, history and snapshot delivery fail. Check recorder and delivery channel status whenever compliance data looks stale rather than wrong.

Tip. Task 1.3 questions hand you a broken pipeline and ask for the most likely cause or the first diagnostic step. "Logs stopped after a KMS or bucket-policy change" points at a key or bucket policy that no longer allows cloudtrail.amazonaws.com; "the alarm never fired" points at a metric filter pattern or casing mismatch, alarm statistic, or an unconfirmed or KMS-blocked SNS subscription. "No findings in the aggregation Region" points at cross-Region aggregation or linked-Region configuration, and "the finding exists but no one was alerted" points at an EventBridge rule in the wrong Region or a pattern that does not match the real finding JSON. Expect distractors that suggest rebuilding the trail, detector, or rule — the correct answer is almost always the specific permission or configuration that broke.

Key takeaways
  • Triage every broken pipeline in order — source, delivery, destination permissions, consumer — because downstream stages fail silently with no error anywhere.
  • A trail that reports it is logging can still deliver nothing: check LatestDeliveryError, then the S3 bucket policy and KMS key policy for cloudtrail.amazonaws.com — an aws:SourceArn condition with a wrong value severs delivery invisibly.
  • CloudTrail records management events by default; S3 object-level and Lambda invoke data events only exist if event selectors enabled them — check selectors before suspecting tampering.
  • GuardDuty is enabled per Region per account; suppression rules auto-archive findings, trusted IP lists stop them being generated, and each protection plan gates its own finding types.
  • GuardDuty and Security Hub events emit in the finding's Region — an EventBridge rule in another Region matches nothing, and patterns are exact about types, casing, and values.
  • A KMS-encrypted SNS topic needs a customer managed key whose policy grants the publishing service kms:GenerateDataKey* and kms:Decrypt; the aws/sns managed key cannot grant this, so alarms publish into a void.
  • Metric filters are case-sensitive and never retroactive; alarms fail on wrong statistic, period, or missing-data treatment; subscriptions deliver nothing until confirmed.
  • Stale compliance data means a stopped Config recorder or a broken delivery channel before it means anything else.

Frequently asked questions

Why did CloudTrail stop delivering logs to S3?

Check the trail status first: if logging was stopped, someone called StopLogging; if logging is on, LatestDeliveryError tells you why delivery fails. The usual causes are a bucket policy that no longer grants cloudtrail.amazonaws.com the s3:GetBucketAcl and s3:PutObject permissions (often a well-intentioned aws:SourceArn condition with a wrong value), a KMS key policy on an SSE-KMS trail that no longer allows cloudtrail.amazonaws.com to call kms:GenerateDataKey*, or a destination bucket that was deleted or renamed while the trail still points at the old name.

Why are my VPC Flow Logs missing or full of NODATA records?

NODATA is not a failure — it means no traffic occurred in that aggregation interval; SKIPDATA is the record that indicates real loss from capacity constraints or internal errors. Genuinely missing logs are a delivery-permission problem: for a CloudWatch Logs destination, the IAM role must trust vpc-flow-logs.amazonaws.com and hold the logs write permissions; for S3, the bucket policy must allow delivery.logs.amazonaws.com. Also remember flow logs never capture instance metadata, DHCP, or Amazon-resolver DNS traffic by design.

Why is GuardDuty not generating any findings?

Confirm the detector is enabled in that Region and account — GuardDuty is Regional, and a disabled Region produces nothing. If the detector is on, look for suppression rules (they auto-archive matching findings so they never surface downstream) and trusted IP lists (findings are not generated for listed addresses). Feature-specific findings also require their protection plan: without S3 Protection there are no S3 findings, without Malware Protection no scan results, and so on per plan, per account, per Region.

Why does my EventBridge rule never fire for GuardDuty or Security Hub findings?

The most common cause is Region: findings emit events to the default event bus in the Region where the finding was generated, so a rule in another Region never sees them. After that, verify the event pattern against a real finding's JSON — patterns are exact, so a numeric severity written as a string, or a wrong source or detail-type, matches nothing — and confirm the rule is enabled and its target grants permission, such as an SNS topic policy allowing events.amazonaws.com to publish.

Why didn't my CloudWatch alarm send an SNS notification?

Work backwards: confirm the alarm actually changed state — if not, the metric filter pattern may match nothing (patterns are case-sensitive and only apply to events ingested after the filter was created), or the alarm uses the wrong statistic or period for the metric. If the alarm fired but nobody was notified, check that the subscription is confirmed rather than pending, and whether the topic is encrypted with KMS: alarms cannot publish to a topic using the aws/sns managed key, because the key policy must grant CloudWatch kms:GenerateDataKey* and kms:Decrypt, which only a customer managed key allows.

Why are Security Hub findings missing from my aggregation Region?

Cross-Region aggregation only replicates findings from Regions you have linked into the aggregation Region you designated — a finding created in an unlinked Region stays there. Also confirm you are viewing the delegated administrator account in an organization, that the relevant standard and control are enabled (a disabled control produces no findings at all), and that the product integration is enabled, since Security Hub never ingests from an integration that is turned off.

Test yourself on this topic
Practice questions with full explanations.
Practice now

Sign up free to mark lessons complete, bookmark topics and track your exam readiness.