SCS Lab 03 - Alarm on root-account console login

Scaffold: 3/5. The log group, the metric filter, the alarm, and the SNS topic are all built and wired. What is missing is the one thing that carries the security decision: the metric-filter pattern that recognises a root-account console sign-in in the CloudTrail JSON. You write that; everything else is done.

The scenario

Someone signs in to the AWS console as the account root. Not an IAM user, not a role: the root identity itself, the one that can do anything and cannot be constrained by IAM. That should be a rare, deliberate, break-glass event, and security should hear about it within seconds. In this account the raw evidence is already there. CloudTrail records the ConsoleLogin, the record lands in a log group, and it sits in the logs saying userIdentity.type is Root. Nothing is watching for it. The login happens, the log line is written, and no one is paged.

The fix is the CIS benchmark’s root-usage monitor: a metric filter that recognises the root sign-in on the CloudTrail JSON, a custom metric that counts it, and an alarm that pages an SNS topic on the first hit. Root usage is a red flag, so there is no burst threshold to clear. One matching event is enough.

The gap

Open src/template.yaml. The metric filter ships with a placeholder pattern:

FilterPattern: '{ $.userIdentity.type = "NoSuchType" }'

It is valid CloudWatch Logs metric-filter syntax, so the stack deploys cleanly, but it selects on a userIdentity.type value no CloudTrail record ever carries. RootAccountUsageCount never moves, and a root console login sails straight past. Your task is to replace it with the pattern that matches a root-account console sign-in. On the CloudTrail JSON, that is the record where:

A JSON metric-filter selector is wrapped in { } and joins its terms with &&. Leave the metric transformations alone; only the FilterPattern needs work.

Run it

# Defaults: stack scs-lab-03, region ap-southeast-2.
./scripts/deploy.sh          # deploys src/template.yaml
./scripts/test.sh            # writes CloudTrail-shaped events and watches the alarm
./scripts/teardown.sh        # deletes everything

test.sh never launches compute, so it stays cheap. It writes CloudTrail-shaped log events with put-log-events and polls describe-alarms. First it writes an ordinary IAM-user ConsoleLogin and confirms the alarm ignores it, because an everyday login is not a page; then it writes a root ConsoleLogin and confirms the alarm fires. Metric filters and alarms take a minute or three to react, so the test polls patiently and prints each reading.

What success looks like

./scripts/test.sh ends with:

  t+90s  alarm=ALARM
PASS: the ordinary login was ignored and the root console login paged.
Note that the IAM-user event alone would never trip this alarm -- only
the root sign-in does, which is exactly the red flag you want to catch.

If it fails

Reveal the solution

Deploy the complete reference template without editing anything:

SRC=solution ./scripts/deploy.sh && ./scripts/test.sh

What you just learned

Next

The rest of the hands-on lab tracks are listed in labs/README-scs.md.