Skip to main content

CloudTrail Multi-Region Enabled

Overview

This check verifies that AWS CloudTrail is logging API activity across all AWS regions. CloudTrail records every API call made in your AWS account, but by default, a trail only captures events in the region where it was created. A multi-region trail ensures you have visibility into API activity everywhere in your account.

Risk

Without multi-region logging, attackers can operate undetected in regions where you have no visibility. This creates serious security blind spots:

  • Unauthorized resources (like crypto-mining EC2 instances) can be launched in unmonitored regions
  • Data exfiltration through S3 buckets or other services in obscure regions goes unnoticed
  • Privilege escalation and IAM changes in unmonitored regions leave no audit trail
  • Forensic investigations are incomplete when incidents span multiple regions
  • Compliance requirements (PCI DSS, HIPAA, SOC 2) typically mandate complete audit coverage

Remediation Steps

Prerequisites

You need:

  • AWS Console access with permissions to create or modify CloudTrail trails
  • An S3 bucket for storing CloudTrail logs (or permission to create one)
Required IAM permissions (for administrators)

Your IAM user or role needs these permissions:

  • cloudtrail:CreateTrail
  • cloudtrail:UpdateTrail
  • cloudtrail:DescribeTrails
  • cloudtrail:StartLogging
  • s3:CreateBucket (if creating a new bucket)
  • s3:PutBucketPolicy
  • s3:GetBucketPolicy

AWS Console Method

  1. Open CloudTrail in the AWS Console

  2. Check existing trails

    • Click Trails in the left sidebar
    • Look for a trail that shows "Yes" under the Multi-region column
    • If you already have one with logging enabled, you're done
  3. Create a new multi-region trail (if needed)

    • Click Create trail
    • Enter a Trail name (e.g., organization-trail)
    • Under Storage location, choose to create a new S3 bucket or use an existing one
    • If creating new, enter a bucket name (must be globally unique)
  4. Enable multi-region logging

    • Under Additional settings, find Trail apply to all regions
    • Select Yes to make this a multi-region trail
    • Optionally enable Log file validation for tamper detection
  5. Configure log events (optional)

    • Choose which events to log: Management events, Data events, or both
    • Management events are usually sufficient for security monitoring
  6. Complete the setup

    • Click Create trail
    • Verify the trail shows as Logging in the Trails list

Updating an existing trail:

  • Click on the trail name
  • Click Edit in the General details section
  • Change Multi-region trail to Yes
  • Click Save changes
AWS CLI (optional)

Create a new multi-region trail

First, create an S3 bucket for CloudTrail logs (replace <your-unique-bucket-name>):

aws s3api create-bucket \
--bucket <your-unique-bucket-name> \
--region us-east-1

Apply the required bucket policy for CloudTrail (replace placeholders):

cat > /tmp/cloudtrail-bucket-policy.json << 'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AWSCloudTrailAclCheck",
"Effect": "Allow",
"Principal": {
"Service": "cloudtrail.amazonaws.com"
},
"Action": "s3:GetBucketAcl",
"Resource": "arn:aws:s3:::<your-unique-bucket-name>"
},
{
"Sid": "AWSCloudTrailWrite",
"Effect": "Allow",
"Principal": {
"Service": "cloudtrail.amazonaws.com"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::<your-unique-bucket-name>/AWSLogs/<your-account-id>/*",
"Condition": {
"StringEquals": {
"s3:x-amz-acl": "bucket-owner-full-control"
}
}
}
]
}
EOF

aws s3api put-bucket-policy \
--bucket <your-unique-bucket-name> \
--policy file:///tmp/cloudtrail-bucket-policy.json

Create the multi-region trail:

aws cloudtrail create-trail \
--name organization-trail \
--s3-bucket-name <your-unique-bucket-name> \
--is-multi-region-trail \
--enable-log-file-validation \
--region us-east-1

Start logging:

aws cloudtrail start-logging \
--name organization-trail \
--region us-east-1

Update an existing trail to multi-region

aws cloudtrail update-trail \
--name <trail-name> \
--is-multi-region-trail \
--region us-east-1

Ensure logging is enabled:

aws cloudtrail start-logging \
--name <trail-name> \
--region us-east-1
CloudFormation (optional)

This template creates a multi-region CloudTrail trail with an S3 bucket:

AWSTemplateFormatVersion: '2010-09-09'
Description: Multi-region CloudTrail trail with S3 bucket

Parameters:
TrailName:
Type: String
Description: Name for the CloudTrail trail
Default: organization-trail

BucketPrefix:
Type: String
Description: Prefix for the S3 bucket name (account ID will be appended)
Default: cloudtrail-logs

Resources:
CloudTrailBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub ${BucketPrefix}-${AWS::AccountId}
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
VersioningConfiguration:
Status: Enabled

CloudTrailBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref CloudTrailBucket
PolicyDocument:
Version: '2012-10-17'
Statement:
- Sid: AWSCloudTrailAclCheck
Effect: Allow
Principal:
Service: cloudtrail.amazonaws.com
Action: s3:GetBucketAcl
Resource: !GetAtt CloudTrailBucket.Arn
- Sid: AWSCloudTrailWrite
Effect: Allow
Principal:
Service: cloudtrail.amazonaws.com
Action: s3:PutObject
Resource: !Sub ${CloudTrailBucket.Arn}/AWSLogs/${AWS::AccountId}/*
Condition:
StringEquals:
s3:x-amz-acl: bucket-owner-full-control

MultiRegionTrail:
Type: AWS::CloudTrail::Trail
DependsOn: CloudTrailBucketPolicy
Properties:
TrailName: !Ref TrailName
S3BucketName: !Ref CloudTrailBucket
IsMultiRegionTrail: true
IsLogging: true
EnableLogFileValidation: true
IncludeGlobalServiceEvents: true

Outputs:
TrailArn:
Description: ARN of the CloudTrail trail
Value: !GetAtt MultiRegionTrail.Arn

BucketName:
Description: S3 bucket storing CloudTrail logs
Value: !Ref CloudTrailBucket

Deploy with:

aws cloudformation deploy \
--template-file cloudtrail-multi-region.yaml \
--stack-name cloudtrail-multi-region \
--parameter-overrides TrailName=organization-trail \
--region us-east-1
Terraform (optional)
# Variables
variable "trail_name" {
description = "Name of the CloudTrail trail"
type = string
default = "organization-trail"
}

variable "bucket_prefix" {
description = "Prefix for the S3 bucket name"
type = string
default = "cloudtrail-logs"
}

# Data sources
data "aws_caller_identity" "current" {}

# S3 bucket for CloudTrail logs
resource "aws_s3_bucket" "cloudtrail" {
bucket = "${var.bucket_prefix}-${data.aws_caller_identity.current.account_id}"
}

resource "aws_s3_bucket_versioning" "cloudtrail" {
bucket = aws_s3_bucket.cloudtrail.id
versioning_configuration {
status = "Enabled"
}
}

resource "aws_s3_bucket_server_side_encryption_configuration" "cloudtrail" {
bucket = aws_s3_bucket.cloudtrail.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}

resource "aws_s3_bucket_public_access_block" "cloudtrail" {
bucket = aws_s3_bucket.cloudtrail.id

block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}

# Bucket policy for CloudTrail
resource "aws_s3_bucket_policy" "cloudtrail" {
bucket = aws_s3_bucket.cloudtrail.id

policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "AWSCloudTrailAclCheck"
Effect = "Allow"
Principal = {
Service = "cloudtrail.amazonaws.com"
}
Action = "s3:GetBucketAcl"
Resource = aws_s3_bucket.cloudtrail.arn
},
{
Sid = "AWSCloudTrailWrite"
Effect = "Allow"
Principal = {
Service = "cloudtrail.amazonaws.com"
}
Action = "s3:PutObject"
Resource = "${aws_s3_bucket.cloudtrail.arn}/AWSLogs/${data.aws_caller_identity.current.account_id}/*"
Condition = {
StringEquals = {
"s3:x-amz-acl" = "bucket-owner-full-control"
}
}
}
]
})
}

# Multi-region CloudTrail trail
resource "aws_cloudtrail" "main" {
name = var.trail_name
s3_bucket_name = aws_s3_bucket.cloudtrail.id
is_multi_region_trail = true
enable_logging = true
enable_log_file_validation = true
include_global_service_events = true

depends_on = [aws_s3_bucket_policy.cloudtrail]
}

# Outputs
output "trail_arn" {
description = "ARN of the CloudTrail trail"
value = aws_cloudtrail.main.arn
}

output "bucket_name" {
description = "S3 bucket storing CloudTrail logs"
value = aws_s3_bucket.cloudtrail.id
}

Deploy with:

terraform init
terraform plan -var="trail_name=organization-trail"
terraform apply -var="trail_name=organization-trail"

Verification

After making changes, verify multi-region logging is working:

  1. In the AWS Console:

    • Go to CloudTrail > Trails
    • Confirm your trail shows Yes under the Multi-region column
    • Click the trail name and verify Logging is ON
  2. Test from another region:

    • Switch to a different region (e.g., eu-west-1)
    • Perform any AWS action (like listing EC2 instances)
    • Return to your S3 bucket and verify logs appear for that region
CLI verification commands

List all trails and check multi-region status:

aws cloudtrail describe-trails \
--region us-east-1 \
--query 'trailList[*].{Name:Name,IsMultiRegion:IsMultiRegionTrail,S3Bucket:S3BucketName}'

Check if logging is enabled for a specific trail:

aws cloudtrail get-trail-status \
--name <trail-name> \
--region us-east-1 \
--query '{IsLogging:IsLogging,LatestDeliveryTime:LatestDeliveryTime}'

Expected output for a properly configured trail:

{
"IsLogging": true,
"LatestDeliveryTime": "2024-01-15T10:30:00.000000+00:00"
}

Run the Prowler check again to confirm remediation:

prowler aws --checks cloudtrail_multi_region_enabled

Additional Resources

Notes

  • One trail is usually enough: A single multi-region trail captures events from all regions. You do not need separate trails per region.
  • Global services: Enable "Include global service events" to capture IAM, CloudFront, and other global service events (only in the home region to avoid duplicates).
  • Organization trails: If using AWS Organizations, consider creating an organization trail that logs events for all member accounts.
  • Costs: CloudTrail charges per 100,000 events after the first management event copy. Multi-region trails may increase costs, but the security benefits typically outweigh this.
  • Log file validation: Always enable log file validation to detect if logs have been tampered with.
  • Encryption: Consider enabling KMS encryption for CloudTrail logs for additional security (see cloudtrail_kms_encryption_enabled check).