For the last 90 days of management events, use the CloudTrail console (Event history → Download events → JSON) or aws cloudtrail lookup-events. For anything older, or for data events like S3 object reads, read your trail’s log files in S3. They sit under s3://<bucket>/AWSLogs/<account-id>/CloudTrail/<region>/YYYY/MM/DD/.
CloudTrail is the audit log of your AWS control plane: every console login, every API call, every role assumption. In a cloud incident, it’s the first thing everyone asks for. Prime Core has 262 detection rules for CloudTrail, mapped to 177 MITRE ATT&CK techniques. Among them: misuse of cloud accounts (T1078.004), attackers switching off cloud logging (T1562.008) and data theft from cloud storage (T1530).
Before you start
Event history and trails are different things. Event history is always on and free. It keeps 90 days of management events, per region. A trail is something you configure: it writes to S3, keeps logs as long as you like, and can include data events. Check what you have:
aws cloudtrail describe-trails
aws cloudtrail get-trail-status --name <trail-name>
IsLogging: false on a trail that should be running is a finding in itself.
Regions matter. Event history is per region, and events from global services like IAM usually land in us-east-1. If you’re looking for a CreateUser call in eu-west-1, you won’t find it.
Permissions. cloudtrail:LookupEvents for event history. For trail files, s3:ListBucket and s3:GetObject on the bucket, plus kms:Decrypt if the trail is encrypted with a KMS key.
Option 1: Console download
Open CloudTrail, go to Event history, set the time range and any filters (event name, user, resource), then choose Download events → JSON. The download respects your filters, so check them first. It covers the current region only.
Option 2: lookup-events from the CLI
aws cloudtrail lookup-events --region us-east-1 \
--start-time 2026-10-19T00:00:00Z --end-time 2026-10-20T00:00:00Z \
--output json > ct_use1_1019.json
Two things to know. First, each result wraps the actual event as a JSON string in CloudTrailEvent. Unwrap it into one clean event per line:
jq -c '.Events[].CloudTrailEvent | fromjson' ct_use1_1019.json > ct_use1_1019.jsonl
Second, lookup-events is rate limited per account and region, and it accepts only one –lookup-attributes filter per call. Wide time windows take a while, so narrow them where you can. To cover every region, loop over aws ec2 describe-regions –query ‘Regions[].RegionName’ –output text.
Option 3: Trail files from S3
This is the route for history beyond 90 days and for data events:
aws s3 cp s3://my-trail-bucket/AWSLogs/123456789012/CloudTrail/eu-west-1/2026/10/19/ ./ct/ --recursive
gunzip ./ct/*.json.gz
jq -c '.Records[]' ./ct/*.json > ct_euw1_1019.jsonl
Each file holds a Records array, and the jq line flattens all of them into one event per line. Organization trails add the organization ID to the path: AWSLogs/<org-id>/<account-id>/CloudTrail/…. If you use CloudTrail Lake, you can run SQL over your events and save the results instead.
What to look for
| Event | Why it matters |
|---|---|
| ConsoleLogin | Check additionalEventData.MFAUsed, failures, and source IPs you don’t recognize |
| CreateUser, CreateAccessKey, AttachUserPolicy | New identities and keys: classic persistence and privilege escalation |
| StopLogging, DeleteTrail, PutEventSelectors | Someone reducing what CloudTrail sees |
| AssumeRole from odd sources | Lateral movement between roles and accounts |
| Bursts of errorCode: AccessDenied | Reconnaissance with stolen credentials |
| GetSecretValue, GetObject bursts | Data access; GetObject appears only if S3 data events are on |
Upload, sanitize and review in LogTotal
- Upload. Open logtotal.com and drop in the .jsonl (or .json file).
- Sanitize. [what gets masked: account IDs, ARNs, IPs, access key IDs, usernames]. Look it over before you continue.
- Review.
When it goes wrong
| Symptom | Likely cause | Fix |
|---|---|---|
| lookup-events returns nothing | Wrong region; IAM events usually live in us-east-1 | Query us-east-1, or loop over all regions |
| Nothing older than 90 days | Event history retention | Use the trail files in S3 |
| No GetObject events | S3 data events aren’t enabled on the trail | Expected; enable them for the future |
| AccessDenied reading trail files | Missing kms:Decrypt, or the bucket policy | Fix IAM or the bucket policy |
| ThrottlingException | lookup-events rate limit | Smaller windows; let the CLI retry |
FAQ
Does event history include data events?
No. Only management events. Data events exist only if a trail or event data store was set up to record them.
How quickly do events show up?
Usually within minutes of the API call. Trail files in S3 arrive in batches, so a very recent event may not be in a file yet