Back to Checks
aws

Region has at least one CloudTrail trail logging

cloudtrail_multi_region_enabled
Service: cloudtrailSeverity: high
OfficialBuilt-inVerified
Categories:loggingforensics-ready
Resource Type:AwsCloudTrailTrail

AWS CloudTrail has at least one trail with logging enabled in every region. A multi-region trail or a regional trail counts for coverage in that region.

Risk

Missing coverage in any region creates visibility gaps.

Attackers can use lesser-monitored regions to run API actions, hide unauthorized changes, and exfiltrate data without audit trails, weakening detective controls, hindering forensics, and delaying response (confidentiality and integrity).

Run this check with Prowler

Run in Prowler Cloud
Run
prowler aws --checks cloudtrail_multi_region_enabled

Recommendation

Use a multi-region CloudTrail trail or per-region trails so logging is active in every region, including unused ones.

Centralize logs, enforce least privilege to log stores, and add defense-in-depth with encryption, integrity validation, and retention. Continuously monitor trail health to catch gaps.

Remediation

Terraform

# Terraform: Multi-region CloudTrail with logging enabled
resource "aws_cloudtrail" "<example_resource_name>" {
  name           = "<example_resource_name>"
  s3_bucket_name = "<example_resource_name>"

  is_multi_region_trail = true  # Critical: applies the trail to all regions
  enable_logging        = true  # Critical: ensures the trail is logging
}

NativeIaC

# CloudFormation: Create a multi-region CloudTrail and start logging
Resources:
  <example_resource_name>:
    Type: AWS::CloudTrail::Trail
    Properties:
      TrailName: <example_resource_name>
      S3BucketName: <example_resource_name>
      IsMultiRegionTrail: true  # Critical: applies the trail to all regions
      IsLogging: true           # Critical: ensures the trail is logging

Other

1In the AWS Console, go to CloudTrail > Trails
2If no trail exists: Click Create trail, enter a name, choose an S3 bucket, set Apply trail to all regions = Yes, then Create (logging starts)
3If a trail exists: Select it, click Edit, set Apply trail to all regions = Yes, Save
4If Status shows Not logging, click Start logging

Check Code

from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.cloudtrail.cloudtrail_client import (
    cloudtrail_client,
)


class cloudtrail_multi_region_enabled(Check):
    def execute(self):
        findings = []
        if cloudtrail_client.trails is not None:
            for region in cloudtrail_client.regional_clients.keys():
                trail_is_logging = False
                for trail in cloudtrail_client.trails.values():
                    if trail.region == region or trail.is_multiregion:
                        report = Check_Report_AWS(
                            metadata=self.metadata(), resource=trail
                        )
                        report.region = region
                        if trail.is_logging:
                            trail_is_logging = True
                            report.status = "PASS"
                            if trail.is_multiregion:
                                report.status_extended = f"Trail {trail.name} is multiregion and it is logging."
                            else:
                                report.status_extended = f"Trail {trail.name} is not multiregion and it is logging."
                            # Since there exists a logging trail in that region there is no point in checking the remaining trails
                            # Store the finding and exit the loop
                            findings.append(report)
                            break
                # If there are no trails logging it is needed to store the FAIL once all the trails have been checked
                if not trail_is_logging:
                    report = Check_Report_AWS(
                        metadata=self.metadata(),
                        resource={},
                    )
                    report.status = "FAIL"
                    report.status_extended = (
                        "No CloudTrail trails enabled with logging were found."
                    )
                    report.region = region
                    report.resource_arn = cloudtrail_client._get_trail_arn_template(
                        region
                    )
                    report.resource_id = cloudtrail_client.audited_account
                    findings.append(report)
        return findings