Tarek Cheikh
Founder & AWS Security Expert
AWS CloudTrail is the foundation of security visibility in any AWS environment. Every API call -- whether from the console, CLI, SDK, or another AWS service -- is recorded by CloudTrail. Without properly configured trails, you are flying blind: unable to detect unauthorized access, investigate incidents, meet compliance requirements, or understand who changed what and when.
In 2025, AWS significantly expanded CloudTrail capabilities with Network Activity Events for VPC endpoints (February 2025 GA) and Insights for data events with event aggregation (November 2025). These features close critical visibility gaps that previously required third-party tooling. Meanwhile, the CIS AWS Foundations Benchmark v5.0 (October 2025) tightened CloudTrail requirements, making comprehensive trail configuration a compliance baseline rather than a stretch goal.
This guide covers 12 battle-tested CloudTrail best practices, each with real AWS CLI commands, audit procedures, and the latest 2025-2026 updates from AWS.
A single-region, single-account trail leaves massive blind spots. Attackers routinely pivot to unused regions (e.g., ap-southeast-3) to launch resources where no one is watching. An organization trail in AWS Organizations automatically covers all member accounts and all regions, including new regions as they launch.
# Create an organization trail with multi-region and log file validation
aws cloudtrail create-trail --name org-security-trail --s3-bucket-name my-org-cloudtrail-logs --is-multi-region-trail --is-organization-trail --enable-log-file-validation --kms-key-id arn:aws:kms:us-east-1:123456789012:key/abcd1234-5678-90ab-cdef-EXAMPLE
# Start logging
aws cloudtrail start-logging --name org-security-trail
# Verify the trail is logging
aws cloudtrail get-trail-status --name org-security-trail
Security Hub: [CloudTrail.1] requires at least one multi-region trail with read and write management events. [CloudTrail.3] requires at least one trail to be enabled.
CIS Benchmark: Control 3.1 (ensure CloudTrail is enabled in all regions).
By default, CloudTrail logs are encrypted with Amazon S3 server-side encryption (SSE-S3). While this provides encryption at rest, it does not give you control over key rotation, key policies, or access auditing. A customer-managed KMS key (CMK) provides full control over who can decrypt trail logs and creates an additional audit trail via KMS key usage logging.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowCloudTrailEncrypt",
"Effect": "Allow",
"Principal": {"Service": "cloudtrail.amazonaws.com"},
"Action": "kms:GenerateDataKey*",
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:SourceArn": "arn:aws:cloudtrail:us-east-1:123456789012:trail/org-security-trail"
},
"StringLike": {
"kms:EncryptionContext:aws:cloudtrail:arn": "arn:aws:cloudtrail:*:123456789012:trail/*"
}
}
},
{
"Sid": "AllowSecurityTeamDecrypt",
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::123456789012:role/SecurityAuditRole"},
"Action": ["kms:Decrypt", "kms:DescribeKey"],
"Resource": "*"
}
]
}
# Update an existing trail to use KMS encryption
aws cloudtrail update-trail --name org-security-trail --kms-key-id arn:aws:kms:us-east-1:123456789012:key/abcd1234-5678-90ab-cdef-EXAMPLE
# Verify encryption is enabled
aws cloudtrail describe-trails --trail-name-list org-security-trail --query "trailList[0].KmsKeyId"
Security Hub: [CloudTrail.2] requires encryption at rest with SSE-KMS. [CloudTrail.10] requires customer-managed KMS keys for CloudTrail Lake event data stores.
CIS Benchmark: Control 3.7 (ensure CloudTrail logs are encrypted at rest using KMS CMKs).
Log file integrity validation uses SHA-256 hashing and RSA digital signatures to produce digest files every hour. These digest files allow you to cryptographically verify that no log files have been modified, deleted, or forged after delivery. Without validation, an attacker who gains access to the S3 bucket could alter logs to cover their tracks.
# Enable validation on an existing trail
aws cloudtrail update-trail --name org-security-trail --enable-log-file-validation
# Validate log file integrity for the past 24 hours
aws cloudtrail validate-logs --trail-arn arn:aws:cloudtrail:us-east-1:123456789012:trail/org-security-trail --start-time $(date -u -v-1d +%Y-%m-%dT%H:%M:%SZ) --end-time $(date -u +%Y-%m-%dT%H:%M:%SZ)
How it works: CloudTrail delivers a digest file to a separate prefix in the same S3 bucket every hour. The digest contains the SHA-256 hash of each log file delivered in that period and is signed with a private key. The validate-logs command checks both the digest chain and individual file hashes.
Security Hub: [CloudTrail.4] requires log file validation to be enabled.
CIS Benchmark: Control 3.2 (ensure CloudTrail log file validation is enabled).
The S3 bucket storing CloudTrail logs is a high-value target. If an attacker can read the logs, they gain intelligence about your environment. If they can delete or modify them, they erase evidence. A dedicated, hardened S3 bucket for trail logs is essential.
# Block all public access
aws s3api put-public-access-block --bucket my-org-cloudtrail-logs --public-access-block-configuration BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true
# Enable versioning
aws s3api put-bucket-versioning --bucket my-org-cloudtrail-logs --versioning-configuration Status=Enabled
# Enable server access logging
aws s3api put-bucket-logging --bucket my-org-cloudtrail-logs --bucket-logging-status '{
"LoggingEnabled": {
"TargetBucket": "my-s3-access-logs-bucket",
"TargetPrefix": "cloudtrail-bucket-access/"
}
}'
# Apply restrictive bucket policy
aws s3api put-bucket-policy --bucket my-org-cloudtrail-logs --policy '{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyUnencryptedTransport",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::my-org-cloudtrail-logs",
"arn:aws:s3:::my-org-cloudtrail-logs/*"
],
"Condition": {
"Bool": {"aws:SecureTransport": "false"}
}
},
{
"Sid": "DenyDeleteActions",
"Effect": "Deny",
"Principal": "*",
"Action": ["s3:DeleteObject", "s3:DeleteObjectVersion"],
"Resource": "arn:aws:s3:::my-org-cloudtrail-logs/*",
"Condition": {
"StringNotEquals": {
"aws:PrincipalArn": "arn:aws:iam::123456789012:role/SecurityBreakGlass"
}
}
}
]
}'
Security Hub: [CloudTrail.6] (S3 bucket not publicly accessible -- Critical severity). [CloudTrail.7] (S3 bucket access logging enabled).
CIS Benchmark: Control 3.3 (S3 bucket used for CloudTrail is not publicly accessible), Control 3.4 (CloudTrail trails integrated with CloudWatch Logs), Control 3.6 (S3 bucket access logging enabled on CloudTrail bucket).
CloudTrail delivers logs to S3 with a typical delay of 5-15 minutes. For real-time threat detection, send trail events to CloudWatch Logs and configure metric filters with alarms for critical security events.
# Configure CloudTrail to send logs to CloudWatch Logs
aws cloudtrail update-trail --name org-security-trail --cloud-watch-logs-log-group-arn arn:aws:logs:us-east-1:123456789012:log-group:CloudTrail/SecurityEvents:* --cloud-watch-logs-role-arn arn:aws:iam::123456789012:role/CloudTrail_CloudWatchLogs_Role
Create CloudWatch metric filters for the following high-priority events:
# Metric filter: CloudTrail configuration changes
aws logs put-metric-filter --log-group-name CloudTrail/SecurityEvents --filter-name CloudTrailConfigChanges --filter-pattern '{ ($.eventName = CreateTrail) || ($.eventName = UpdateTrail) || ($.eventName = DeleteTrail) || ($.eventName = StartLogging) || ($.eventName = StopLogging) }' --metric-transformations metricName=CloudTrailConfigChangeCount,metricNamespace=SecurityMetrics,metricValue=1
# Metric filter: Console sign-in without MFA
aws logs put-metric-filter --log-group-name CloudTrail/SecurityEvents --filter-name ConsoleSignInWithoutMFA --filter-pattern '{ ($.eventName = "ConsoleLogin") && ($.additionalEventData.MFAUsed != "Yes") && ($.userIdentity.type = "IAMUser") }' --metric-transformations metricName=ConsoleSignInWithoutMFACount,metricNamespace=SecurityMetrics,metricValue=1
# Create an alarm for CloudTrail changes
aws cloudwatch put-metric-alarm --alarm-name CloudTrailConfigChangeAlarm --metric-name CloudTrailConfigChangeCount --namespace SecurityMetrics --statistic Sum --period 300 --threshold 1 --comparison-operator GreaterThanOrEqualToThreshold --evaluation-periods 1 --alarm-actions arn:aws:sns:us-east-1:123456789012:SecurityAlerts
Security Hub: [CloudTrail.5] requires CloudTrail trails to be integrated with CloudWatch Logs.
CIS Benchmark: Control 3.4 (CloudTrail integrated with CloudWatch Logs), Controls 4.1-4.14 (metric filters and alarms for security-critical events).
Management events (control plane) capture actions like creating or deleting resources. Data events (data plane) capture the actual reads and writes to the resources themselves -- S3 GetObject/PutObject, Lambda Invoke, DynamoDB GetItem/PutItem. Without data events, you cannot detect data exfiltration, unauthorized data access, or anomalous function invocations.
# Enable S3 data events for all buckets
aws cloudtrail put-event-selectors --trail-name org-security-trail --advanced-event-selectors '[
{
"Name": "S3DataEvents",
"FieldSelectors": [
{"Field": "eventCategory", "Equals": ["Data"]},
{"Field": "resources.type", "Equals": ["AWS::S3::Object"]}
]
},
{
"Name": "LambdaDataEvents",
"FieldSelectors": [
{"Field": "eventCategory", "Equals": ["Data"]},
{"Field": "resources.type", "Equals": ["AWS::Lambda::Function"]}
]
},
{
"Name": "DynamoDBDataEvents",
"FieldSelectors": [
{"Field": "eventCategory", "Equals": ["Data"]},
{"Field": "resources.type", "Equals": ["AWS::DynamoDB::Table"]}
]
}
]'
# Verify event selectors
aws cloudtrail get-event-selectors --trail-name org-security-trail
Cost management: Data events can generate significant volume. Use advanced event selectors to filter by specific buckets, functions, or tables. For example, exclude read-heavy buckets used by analytics workloads while capturing all writes:
{
"Name": "S3WriteOnlyForAnalytics",
"FieldSelectors": [
{"Field": "eventCategory", "Equals": ["Data"]},
{"Field": "resources.type", "Equals": ["AWS::S3::Object"]},
{"Field": "resources.ARN", "StartsWith": ["arn:aws:s3:::sensitive-data-bucket/"]},
{"Field": "readOnly", "Equals": ["false"]}
]
}
2025 Update: CloudTrail now supports data events for over 20 service resource types, including Amazon ECS task actions (October 2025). Review the full list of supported services periodically.
Released as GA in February 2025, Network Activity Events are a new category of CloudTrail events that capture API calls made through VPC endpoints. This closes a critical visibility gap: previously, you could see what API calls were made but not which VPC endpoint they traversed. Network Activity Events reveal who is accessing resources within your network, enabling you to identify unauthorized cross-account access or data exfiltration through VPC endpoints.
# Enable Network Activity Events using advanced event selectors
aws cloudtrail put-event-selectors --trail-name org-security-trail --advanced-event-selectors '[
{
"Name": "NetworkActivityS3",
"FieldSelectors": [
{"Field": "eventCategory", "Equals": ["NetworkActivity"]},
{"Field": "resources.type", "Equals": ["AWS::S3::AccessPoint"]}
]
},
{
"Name": "NetworkActivityKMS",
"FieldSelectors": [
{"Field": "eventCategory", "Equals": ["NetworkActivity"]},
{"Field": "resources.type", "Equals": ["AWS::KMS::Key"]}
]
}
]'
# Filter to only log accessDenied calls (cost-effective option)
aws cloudtrail put-event-selectors --trail-name org-security-trail --advanced-event-selectors '[
{
"Name": "NetworkActivityDeniedOnly",
"FieldSelectors": [
{"Field": "eventCategory", "Equals": ["NetworkActivity"]},
{"Field": "resources.type", "Equals": ["AWS::EC2::Snapshot"]},
{"Field": "errorCode", "Equals": ["VpceAccessDenied"]}
]
}
]'
Use case: Detect data perimeter violations. If a VPC endpoint policy restricts access to specific principals and an unauthorized entity attempts access, Network Activity Events log the VpceAccessDenied error with the source identity, VPC endpoint ID, and target resource. This is essential for organizations implementing AWS data perimeter controls.
Launched in November 2025, CloudTrail Insights for data events extends anomaly detection beyond management events to cover data plane activity. Insights establishes baselines of normal API call rates and error rates, then generates an Insight event when it detects statistically significant deviations.
s3:DeleteObject calls could indicate ransomware or data destruction.AccessDenied errors on Lambda invocations could indicate credential stuffing or privilege escalation attempts.GetObject calls from unfamiliar principals.# Enable Insights for both management and data events
aws cloudtrail put-insight-selectors --trail-name org-security-trail --insight-selectors '[
{"InsightType": "ApiCallRateInsight"},
{"InsightType": "ApiErrorRateInsight"}
]'
# Check current Insights configuration
aws cloudtrail get-insight-selectors --trail-name org-security-trail
# Query recent Insight events
aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventSource,AttributeValue=insights.cloudtrail.amazonaws.com --max-results 10
Companion feature -- Data Event Aggregation (November 2025): CloudTrail can now consolidate high-volume data events into 5-minute summaries, reducing noise and cost while maintaining security visibility. Aggregated events include total call counts, error counts, and top callers for each API action.
Best practice: Enable Insights on trails that already have data events enabled. Insights analyzes the same event stream -- there is no additional data collection required, only an Insights processing charge.
The first thing a sophisticated attacker does after gaining access is disable logging. Service Control Policies (SCPs) in AWS Organizations provide the strongest protection because they cannot be overridden by any IAM policy in member accounts -- not even by the account root user.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyCloudTrailTampering",
"Effect": "Deny",
"Action": [
"cloudtrail:StopLogging",
"cloudtrail:DeleteTrail",
"cloudtrail:UpdateTrail",
"cloudtrail:PutEventSelectors",
"cloudtrail:PutInsightSelectors"
],
"Resource": "arn:aws:cloudtrail:*:*:trail/org-security-trail",
"Condition": {
"ArnNotLike": {
"aws:PrincipalARN": [
"arn:aws:iam::*:role/OrganizationSecurityAdmin"
]
}
}
},
{
"Sid": "DenyCloudTrailBucketDeletion",
"Effect": "Deny",
"Action": [
"s3:DeleteBucket",
"s3:DeleteBucketPolicy",
"s3:PutBucketPolicy"
],
"Resource": "arn:aws:s3:::my-org-cloudtrail-logs",
"Condition": {
"ArnNotLike": {
"aws:PrincipalARN": [
"arn:aws:iam::*:role/OrganizationSecurityAdmin"
]
}
}
}
]
}
# Apply the SCP to the root OU (covers all accounts)
aws organizations create-policy --name "DenyCloudTrailTampering" --description "Prevent modification or deletion of organization trail" --type SERVICE_CONTROL_POLICY --content file://cloudtrail-scp.json
aws organizations attach-policy --policy-id p-EXAMPLE --target-id r-ROOT
Best practice: Also protect the KMS key used for trail encryption. If an attacker disables or schedules deletion of the CMK, all future log decryption fails. Add kms:DisableKey and kms:ScheduleKeyDeletion to the SCP deny list for the trail encryption key.
CloudTrail Lake is a managed audit and security data lake that lets you aggregate, immutably store, and query CloudTrail events using SQL. Unlike traditional S3-based trails that require Athena setup and Glue crawlers, CloudTrail Lake provides a fully managed query experience with built-in dashboards.
# Create an organization event data store with 7-year retention
aws cloudtrail create-event-data-store --name "OrgSecurityLake" --organization-enabled --retention-period 2557 --multi-region-enabled --kms-key-id arn:aws:kms:us-east-1:123456789012:key/abcd1234-5678-90ab-cdef-EXAMPLE
# Run a SQL query: find all IAM policy changes in the last 7 days
aws cloudtrail start-query --query-statement "SELECT eventTime, userIdentity.arn, eventName, requestParameters
FROM abcd1234-5678-90ab-cdef-EXAMPLE
WHERE eventSource = 'iam.amazonaws.com'
AND eventName IN ('AttachRolePolicy', 'DetachRolePolicy', 'PutRolePolicy', 'CreatePolicy')
AND eventTime > date_add('day', -7, now())
ORDER BY eventTime DESC"
# Get query results
aws cloudtrail get-query-results --query-id QUERY_ID_EXAMPLE
Security Hub: [CloudTrail.10] requires CloudTrail Lake event data stores to be encrypted with customer-managed KMS keys.
Cost tip: Use CloudTrail Lake for compliance and investigation queries. For high-volume ad-hoc analytics, consider the Athena integration described in the next section.
For organizations that already store CloudTrail logs in S3, Amazon Athena provides serverless, pay-per-query SQL analysis without the ongoing cost of CloudTrail Lake. Combined with Security Hub, this creates a comprehensive detection and investigation pipeline.
# Create an Athena table for CloudTrail logs (run in Athena console or API)
aws athena start-query-execution --query-string "CREATE EXTERNAL TABLE cloudtrail_logs (
eventVersion STRING, userIdentity STRUCT,
eventTime STRING, eventSource STRING, eventName STRING, awsRegion STRING,
sourceIPAddress STRING, userAgent STRING, errorCode STRING, errorMessage STRING,
requestParameters STRING, responseElements STRING, resources ARRAY>
)
PARTITIONED BY (account STRING, region STRING, year STRING, month STRING, day STRING)
ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
LOCATION 's3://my-org-cloudtrail-logs/AWSLogs/'
TBLPROPERTIES ('projection.enabled'='true')" --work-group primary --result-configuration OutputLocation=s3://my-athena-results/
# Enable CloudTrail controls in Security Hub
aws securityhub batch-enable-standards --standards-subscription-requests '[{
"StandardsArn": "arn:aws:securityhub:::standards/aws-foundational-security-best-practices/v/1.0.0"
}]'
# Query Security Hub for CloudTrail-related findings
aws securityhub get-findings --filters '{
"GeneratorId": [{"Value": "aws-foundational-security-best-practices/v/1.0.0/CloudTrail", "Comparison": "PREFIX"}],
"ComplianceStatus": [{"Value": "FAILED", "Comparison": "EQUALS"}]
}'
SIEM integration: Forward CloudTrail events to your SIEM (Splunk, Elastic, Microsoft Sentinel) via S3-to-SQS-to-SIEM pipelines or CloudWatch Logs subscription filters. For GuardDuty, CloudTrail management events are automatically analyzed -- no additional configuration required.
Manual CloudTrail audits do not scale. Use AWS Config rules, Security Hub controls, and automation to continuously validate your CloudTrail configuration.
# CloudTrail is enabled
aws configservice put-config-rule --config-rule '{
"ConfigRuleName": "cloudtrail-enabled",
"Source": {"Owner": "AWS", "SourceIdentifier": "CLOUD_TRAIL_ENABLED"}
}'
# CloudTrail encryption enabled
aws configservice put-config-rule --config-rule '{
"ConfigRuleName": "cloudtrail-encryption-enabled",
"Source": {"Owner": "AWS", "SourceIdentifier": "CLOUD_TRAIL_ENCRYPTION_ENABLED"}
}'
# CloudTrail log file validation enabled
aws configservice put-config-rule --config-rule '{
"ConfigRuleName": "cloudtrail-log-file-validation-enabled",
"Source": {"Owner": "AWS", "SourceIdentifier": "CLOUD_TRAIL_LOG_FILE_VALIDATION_ENABLED"}
}'
# CloudTrail CloudWatch Logs integration
aws configservice put-config-rule --config-rule '{
"ConfigRuleName": "cloudtrail-cloudwatch-logs-enabled",
"Source": {"Owner": "AWS", "SourceIdentifier": "CLOUD_TRAIL_CLOUD_WATCH_LOGS_ENABLED"}
}'
# CloudTrail S3 bucket not publicly accessible
aws configservice put-config-rule --config-rule '{
"ConfigRuleName": "cloudtrail-s3-bucket-public-read-prohibited",
"Source": {"Owner": "AWS", "SourceIdentifier": "S3_BUCKET_PUBLIC_READ_PROHIBITED"},
"Scope": {"ComplianceResourceTypes": ["AWS::S3::Bucket"]}
}'
# Auto-remediate: re-enable logging if stopped
aws configservice put-remediation-configurations --remediation-configurations '[{
"ConfigRuleName": "cloudtrail-enabled",
"TargetType": "SSM_DOCUMENT",
"TargetId": "AWSConfigRemediation-EnableCloudTrail",
"Automatic": true,
"MaximumAutomaticAttempts": 3,
"RetryAttemptSeconds": 60
}]'
CIS Benchmark v5.0: Security Hub now supports automated evaluation of all CIS v5.0 controls for CloudTrail (October 2025). Enable the standard to get continuous compliance scoring across your organization.
| Misconfiguration | Risk | Detection |
|---|---|---|
| Single-region trail only | API calls in other regions go undetected | [CloudTrail.1]: multi-region trail required |
| No KMS encryption on logs | Logs readable by anyone with S3 access | [CloudTrail.2]: SSE-KMS required |
| Log file validation disabled | Tampered logs go undetected | [CloudTrail.4]: validation must be enabled |
| Public CloudTrail S3 bucket | Attackers can read your entire API history | [CloudTrail.6]: Critical severity finding |
| No CloudWatch Logs integration | No real-time alerting on security events | [CloudTrail.5]: CloudWatch Logs required |
| Data events not enabled | Data exfiltration and unauthorized access invisible | Manual audit: get-event-selectors |
| No SCP protection on trails | Compromised admin can disable logging | Review SCP policies in Organizations |
| # | Practice | Priority |
|---|---|---|
| 1 | Organization trail across all regions | Critical |
| 2 | KMS encryption for trail logs | High |
| 3 | Log file integrity validation | High |
| 4 | S3 bucket hardening (BPA, versioning, MFA delete) | Critical |
| 5 | CloudWatch Logs integration with metric filters | High |
| 6 | Data event logging for S3, Lambda, DynamoDB | High |
| 7 | Network Activity Events for VPC endpoints | Medium |
| 8 | Insights for data events (anomaly detection) | Medium |
| 9 | SCP anti-tampering protection | Critical |
| 10 | CloudTrail Lake for long-term queryable storage | Medium |
| 11 | Athena + Security Hub integration | Medium |
| 12 | Continuous audit with Config rules | High |
This article is just the start. Get the full picture with our free whitepaper - 8 chapters covering IAM, S3, VPC, monitoring, agentic AI security, compliance, and a prioritized action plan with 50+ CLI commands.
Comprehensive guide to securing AWS Identity and Access Management. Covers MFA enforcement, least privilege, IAM Identity Center, SCPs, Access Analyzer, and credential management.
Comprehensive guide to securing AWS Key Management Service. Covers key policies, separation of duties, automatic rotation, encryption context, envelope encryption, cross-account access, multi-Region keys, and continuous compliance monitoring.
Comprehensive guide to securing Amazon S3. Covers Block Public Access, encryption (SSE-KMS, SSE-C deprecation), Object Lock, MFA Delete, VPC endpoints, presigned URLs, and GuardDuty S3 Protection.