Building an Event-Driven Audit Trail with S3 and Lambda

Have you ever wondered who did what inside your AWS account? Maybe a bucket was deleted, a role was modified, or an instance was spun up out of nowhere. AWS gives you a built-in security camera for this exact purpose, and it's called CloudTrail.

In this post, we'll walk through setting up CloudTrail step by step so you can record, store, and review every API action that happens in your account.

Intro What Is CloudTrail, and Why Should You Care?

Think of your AWS account as a house. Every door or window is an API, and every time someone opens one, CloudTrail makes a note of it.

This means you always know who did something, what they did, when they did it, and where they did it from.

By default, CloudTrail keeps a short history of events. But to really benefit, you'll want to create a trail that stores logs in Amazon S3, streams them to CloudWatch Logs, and gives you the ability to search or alert on unusual behavior.

Stack The Services You'll Use

CloudTrail
The camera system recording every API call across your account.
S3
The file cabinet where your log files live long-term.
CloudWatch Logs
A motion sensor that alerts you if something unusual happens.
Optional
Athena / CT Lake
The detective who digs through logs when you need answers.
Optional
KMS
The lockbox that encrypts your logs for extra security.
Optional
Step 01 Create a Trail

Log into the AWS Management Console, open CloudTrail, and navigate to Trails → Create trail.

  1. Name it something easy to remember, like acct-main-trail.
  2. Apply it to all regions so you don't miss activity outside your home region.
  3. Under log events, turn on Management events and select both read and write.
  4. Leave data events off for now unless you want deep logging for S3 or Lambda.
{
  "TrailName": "acct-main-trail",
  "IsMultiRegionTrail": true,
  "IncludeGlobalServiceEvents": true,
  "EventSelectors": [
    {
      "ReadWriteType": "All",        // capture both reads and writes
      "IncludeManagementEvents": true,
      "DataResources": []             // add S3/Lambda ARNs here later
    }
  ]
}
Step 02 Set Up Storage

CloudTrail needs somewhere to drop its files. During trail creation:

  1. Choose Create new S3 bucket.
  2. Give it a unique name: ct-logs-<account-id>-<region>.
  3. Keep Block all public access enabled.
  4. Leave the default encryption, or step up to KMS if you need stronger control.

A consistent bucket naming convention like ct-logs-123456789012-us-east-1 makes cross-account log management much easier as your organization grows.

Step 03 Strengthen Your Setup

These are optional but worth doing from the start:

Step 04 Stream to CloudWatch Logs

If you want real-time alerts, such as "notify me if CloudTrail is turned off," streaming to CloudWatch is the way to do it.

  1. Expand the CloudWatch Logs section during trail creation.
  2. Create a new log group, for example /aws/cloudtrail/acct-main-trail.
  3. Let AWS create the suggested IAM role for permissions.
# Create the log group manually if needed
aws logs create-log-group \
  --log-group-name "/aws/cloudtrail/acct-main-trail" \
  --region us-east-1
Step 05 Review and Create

Click Create trail and your account is now under watch. CloudTrail will begin delivering log files to your S3 bucket within a few minutes of the first API activity.

Step 06 Test It

Don't just assume it's working. Verify it:

  1. Open S3 in a new tab and create then delete a test bucket.
  2. Go back to CloudTrail → Event history and filter by s3.amazonaws.com. Within minutes your actions will appear.
  3. Check your S3 bucket for .gz log files organized in a time-based folder structure.
  4. If you enabled CloudWatch, open the log group and confirm new log streams are appearing.

If you don't see events within 15 minutes, verify the S3 bucket policy allows CloudTrail to write to it. A misconfigured bucket policy is the most common reason logs stop delivering silently.

Cleanup If This Was Just Practice

  1. Delete the trail in CloudTrail.
  2. Delete the CloudWatch log group if you created one.
  3. Empty and delete the S3 bucket.
  4. Schedule deletion of the KMS key if you created one.

In real environments, CloudTrail should stay on permanently. Only clean it up in a sandbox to avoid clutter or small ongoing costs.

Next Optional Enhancements

Once your baseline is solid, here's where to go next:

-- Example: find all IAM changes in the last 7 days using Athena
SELECT
  eventtime,
  useridentity.arn,
  eventname,
  sourceipaddress
FROM cloudtrail_logs
WHERE eventsource = 'iam.amazonaws.com'
  AND date_diff('day', from_iso8601_timestamp(eventtime), now()) <= 7
ORDER BY eventtime DESC;

Wrapping Up

You've now built a baseline CloudTrail setup that gives you full visibility into your AWS account. With CloudTrail logging into S3, and optionally CloudWatch, Athena, or CloudTrail Lake, you can answer the questions that matter most:

In other words, you just installed a reliable security camera system for your AWS account.