How to export CloudTrail, VPC Flow and S3 logs for forensics
Export CloudTrail logs from the trail bucket, event history or CloudTrail Lake, plus VPC Flow Logs, S3 access logs, GuardDuty findings and IAM reports.
TL;DR. Collect first, analyse second. The best CloudTrail source is the trail's S3 bucket (AWSLogs/<account-id>/CloudTrail/<region>/YYYY/MM/DD/*.json.gz): copy it with aws s3 sync, keep the files compressed and untouched. No trail? Download event history per region — 90 days, management events only. Then grab VPC Flow Logs, S3 server access logs, GuardDuty findings and the IAM credential report. Take a few quiet days before the incident too: baselines need them.
Attackers with admin rights delete trails and detectors. Retention settings quietly expire objects. Event history rolls over after 90 days. The single most useful thing you can do in the first hour of an AWS incident is to put a copy of the evidence somewhere the attacker cannot reach, before anyone starts "cleaning up".
Before you start: scope and a safe destination
- Time window. From a few days before the first suspicious event to now. Detections that compare against normal behaviour (a key's usual IP addresses, the regions you normally use) need that quiet period.
- Accounts and regions. Organization trails put every account under one bucket; single-account trails may be per region. List them with
aws cloudtrail describe-trails --include-shadow-trails. - Credentials for collection. Use a principal the attacker has not touched, ideally a dedicated read-only role. Do not collect with the compromised key.
- Destination. A local encrypted disk or a separate account. Record SHA-256 hashes of what you downloaded for the case file.
1. CloudTrail from the trail's S3 bucket (best source)
A CloudTrail trail delivers gzip-compressed JSON files to S3, about every five minutes according to AWS's description of how CloudTrail works. The key layout is predictable:
s3://<bucket>/[<prefix>/]AWSLogs/[<org-id>/]<account-id>/CloudTrail/<region>/YYYY/MM/DD/<account>_CloudTrail_<region>_<timestamp>_<id>.json.gz
Copy the window you need:
aws s3 sync s3://<bucket>/AWSLogs/<account-id>/CloudTrail/ ./cloudtrail \
--exclude "*" --include "*/2026/09/1*"
Notes from the field:
- Keep the
.json.gzfiles as they are. Recompressing or merging them loses the per-file names that carry the region and delivery time. - Digest files under
CloudTrail-Digest/are signed hash chains, not events. Keep them for the case file — they let you run log file integrity validation — but analysis tools skip them. - Data events (S3
GetObject, LambdaInvoke…) land in the same files if the trail was configured for them. They are not logged by default (AWS documentation), so check the trail's event selectors to know what you can expect to see. - CloudTrail Insights events, when enabled, sit under a separate
CloudTrail-Insight/prefix.
2. CloudTrail event history (no trail configured)
Every account has event history: the last 90 days of management events, per region, without data events. It is better than nothing and it is independent of trails, so an attacker deleting a trail does not remove it.
- Console: CloudTrail → Event history, in each region, remove the default read-only filter, choose the time range, then Download events → JSON (preferred) or CSV. A single download holds up to 200,000 events.
- CLI, per region:
for r in $(aws ec2 describe-regions --query 'Regions[].RegionName' --output text); do
aws cloudtrail lookup-events --region "$r" \
--start-time 2026-09-01T00:00:00Z --output json > "events-$r.json"
done
lookup-events returns each event as a JSON string in the CloudTrailEvent field; keep the output as-is, analysis tools parse it.
3. CloudTrail Lake
If you have an event data store, query it and save the results to S3:
SELECT eventJson FROM <event-data-store-id>
WHERE eventTime > '2026-09-01 00:00:00'
Selecting the full eventJson column keeps every field. Flat column selections work for quick reviews but drop nested fields such as requestParameters.
4. VPC Flow Logs
VPC Flow Logs go to S3, CloudWatch Logs or Firehose.
- S3:
AWSLogs/<account-id>/vpcflowlogs/<region>/YYYY/MM/DD/*.log.gz. Sync it like CloudTrail. Plain-text delivery includes a header line naming the fields; keep it, because custom formats change the column order. Parquet is a delivery option too, but not every tool reads it. - CloudWatch Logs: create an export task to S3 (
aws logs create-export-task) or page throughaws logs filter-log-eventsfor a narrow window.
Flow logs record metadata (addresses, ports, bytes, accept/reject), not payloads. The VPC Flow Logs analysis post explains what that can prove.
5. S3 server access logs
If server access logging was enabled on the bucket that matters, the logs sit in the target bucket and prefix you configured:
aws s3 sync s3://<log-bucket>/<prefix>/ ./s3-access
The objects have no extension and one space-delimited line per request. Delivery is best effort: AWS states that completeness and timeliness are not guaranteed (documentation). Use them alongside CloudTrail data events when both exist.
6. GuardDuty findings
GuardDuty retains findings for 90 days; an S3 publishing destination keeps them longer (export documentation). Export them early — deleting a detector is a common attacker move.
DET=$(aws guardduty list-detectors --query 'DetectorIds[0]' --output text)
aws guardduty list-findings --detector-id "$DET" --query 'FindingIds' --output text \
| xargs -n 50 aws guardduty get-findings --detector-id "$DET" --finding-ids > findings.json
Repeat per region where GuardDuty is enabled.
7. IAM credential report
The credential report lists every user with password, MFA and access-key status, including last-used dates. IAM generates at most one report every four hours (documentation).
aws iam generate-credential-report
aws iam get-credential-report --query Content --output text | base64 -d > credential-report.csv
Checklist
| Source | Where | Retention to worry about | Priority |
|---|---|---|---|
| CloudTrail trail | S3 bucket AWSLogs/…/CloudTrail/ | Bucket lifecycle rules | 1 |
| Event history | Console / lookup-events, per region | 90 days | 1 if no trail |
| GuardDuty findings | get-findings or S3 export | 90 days in GuardDuty | 2 |
| Credential report | IAM | Snapshot of now | 2 |
| S3 data events | Same trail files | Only if configured | 2 |
| S3 server access logs | Target bucket | Bucket lifecycle | 3 |
| VPC Flow Logs | S3 / CloudWatch Logs | Log group retention | 3 |
Next step
Once collected, drop everything at once into the in-browser analyzer: trail folders, event-history JSON or CSV, Lake CSV, flow logs, access logs, findings and the credential report are recognised automatically, and nothing leaves your machine. The CloudTrail log analysis guide walks through reading the results, and the incident response overview puts collection in the wider containment plan.