DEV Community

Cover image for How to Build an Audit-Ready CloudTrail and Config Baseline
Ilyas Rufai
Ilyas Rufai

Posted on

How to Build an Audit-Ready CloudTrail and Config Baseline

An auditor asks: "Show who disabled logging in production last quarter." You open three accounts, find CloudTrail off in one, logs scattered in local S3 buckets, and AWS Config never enabled in the region where the incident happened.

Audit-ready logging is not "turn on CloudTrail somewhere." It is organization-wide trails, immutable central storage, Config recorders in every active region, and queries you have tested before the audit.

This article shows how to build an audit-ready CloudTrail and AWS Config baseline with AWS CLI examples and verification checks.

Who this is for: Platform and DevSecOps engineers preparing for SOC 2, ISO 27001, internal security reviews on AWS.

Prerequisites:

  • AWS Organizations management account access
  • Dedicated log archive account recommended
  • S3 bucket for centralized logs with encryption

TL;DR

  • Organization CloudTrail should write to a central, encrypted S3 bucket with log file validation turned on.
  • AWS Config needs a recorder and delivery channel in every active region, plus an aggregator for org-wide visibility.
  • Managed rules or a conformance pack should cover critical controls like public S3 access, root MFA, and CloudTrail enabled.
  • Saved queries in Athena or CloudTrail Lake should answer common audit questions without manual console digging.
  • Block log tampering with bucket policy, MFA delete, and SCP denies on StopLogging.

Why Per-Account Ad-Hoc Logging Fails

Gap Audit impact
Trail only in one region Actions in other regions invisible
Logs in member account buckets Deleted during account compromise
No Config Cannot prove continuous compliance state
No saved queries Week-long manual click-through during audit

Key idea: Detective controls must survive the account they monitor.

CloudTrail org trail to log archive S3 with Config aggregator

Create the Log Archive Account and Bucket

In the log archive account:

aws s3api create-bucket \
  --bucket org-cloudtrail-logs-ACCOUNT_ID \
  --region eu-west-1 \
  --create-bucket-configuration LocationConstraint=eu-west-1
Enter fullscreen mode Exit fullscreen mode

Enable versioning, encryption, and block public access:

aws s3api put-public-access-block \
  --bucket org-cloudtrail-logs-ACCOUNT_ID \
  --public-access-block-configuration \
    BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true
Enter fullscreen mode Exit fullscreen mode

Use a CMK in the log archive account for bucket encryption.

Enable Organization CloudTrail

From the management account:

aws cloudtrail create-trail \
  --name organization-trail \
  --s3-bucket-name org-cloudtrail-logs-ACCOUNT_ID \
  --is-organization-trail \
  --enable-log-file-validation

aws cloudtrail start-logging --name organization-trail
Enter fullscreen mode Exit fullscreen mode

Verify all regions and management events:

aws cloudtrail put-event-selectors \
  --trail-name organization-trail \
  --event-selectors '[{
    "ReadWriteType": "All",
    "IncludeManagementEvents": true
  }]'
Enter fullscreen mode Exit fullscreen mode

Bucket policy must allow the CloudTrail service to write; use the AWS documentation template for organization trails.

Enable AWS Config in Active Regions

For each region in use, in the member or delegated admin account:

aws configservice put-configuration-recorder \
  --configuration-recorder name=default,roleARN=arn:aws:iam::ACCOUNT_ID:role/config-role \
  --recording-group allSupported=true,includeGlobalResourceTypes=true

aws configservice put-delivery-channel \
  --delivery-channel name=default,s3BucketName=org-config-snapshots-ACCOUNT_ID

aws configservice start-configuration-recorder --configuration-recorder-name default
Enter fullscreen mode Exit fullscreen mode

Use AWS Config aggregators for org-wide view:

aws configservice put-configuration-aggregator \
  --configuration-aggregator-name org-aggregator \
  --account-aggregation-sources AccountIds=111111111111,222222222222,333333333333
Enter fullscreen mode Exit fullscreen mode

Deploy Managed Rules or a Conformance Pack

Example critical rules:

Rule Proves
cloudtrail-enabled Trail active
s3-bucket-public-read-prohibited No public data leaks
root-account-mfa-enabled Root protected
encrypted-volumes EBS encryption default

Deploy conformance pack (example):

aws configservice put-conformance-pack \
  --conformance-pack-name baseline-security \
  --template-body file://conformance-pack.yaml \
  --delivery-s3-bucket org-config-snapshots-ACCOUNT_ID
Enter fullscreen mode Exit fullscreen mode

Protect Logs From Tampering

SCP on workload OUs (see SCP tutorial):

{
  "Effect": "Deny",
  "Action": [
    "cloudtrail:StopLogging",
    "cloudtrail:DeleteTrail",
    "s3:DeleteBucket",
    "s3:PutBucketPolicy"
  ],
  "Resource": "*",
  "Condition": {
    "StringNotEquals": {
      "aws:PrincipalAccount": ["LOG_ARCHIVE_ACCOUNT_ID"]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Restrict S3 delete on log buckets to break-glass roles only.

Build Saved Queries

CloudTrail Lake or Athena query, who changed security groups:

SELECT eventTime, userIdentity.arn, eventSource, eventName, sourceIPAddress
FROM cloudtrail_logs
WHERE eventName = 'AuthorizeSecurityGroupIngress'
  AND eventTime > current_timestamp - interval '7' day
ORDER BY eventTime DESC;
Enter fullscreen mode Exit fullscreen mode

Save as security-group-changes. Run weekly in security sync.

Tabletop Verification

Run these scenarios:

  1. Create test IAM user with access key, appears in CloudTrail within 15 minutes.
  2. Toggle public S3 block; Config flags non-compliance.
  3. Attempt StopLogging from workload account, denied by SCP.

Document results in docs/audit-evidence.md.

How to Verify the Baseline

Check Command / location
Org trail logging aws cloudtrail get-trail-status --name organization-trail
Log validation Trail settings show LogFileValidationEnabled: true
Config recording aws configservice describe-configuration-recorder-status
Aggregator Config console → Aggregators → all accounts green

When This Breaks Down

  1. Cost at scale: high-volume APIs fill S3, use data events selectively, lifecycle to Glacier.
  2. Multi-region delay: Config and CloudTrail are regional; enable every region you operate in.
  3. Delegated admin confusion: Security Hub admin ≠ Config aggregator admin; document roles.
  4. Evidence without process: Logs exist, but nobody runs queries until audit week.

Conclusion

In this tutorial, you learned how to build audit-ready CloudTrail and AWS Config controls: organization trail, central S3, Config recorders, conformance rules, tamper protection, and saved queries.

Use it as evidence of how you design controls that survive account compromise, prove compliance, and turn audit questions into repeatable checks.

References

Top comments (0)