From 2d5de6ff99cc3003d72aebec5d8925d7f0ec8726 Mon Sep 17 00:00:00 2001 From: Nacho Rivera Date: Tue, 14 Feb 2023 11:23:31 +0100 Subject: [PATCH] fix(cross account): cloudtrail s3 bucket logging (#1902) --- ...l_logs_s3_bucket_access_logging_enabled.py | 19 +++++--- ...s_s3_bucket_access_logging_enabled_test.py | 48 +++++++++++++++++++ 2 files changed, 61 insertions(+), 6 deletions(-) diff --git a/prowler/providers/aws/services/cloudtrail/cloudtrail_logs_s3_bucket_access_logging_enabled/cloudtrail_logs_s3_bucket_access_logging_enabled.py b/prowler/providers/aws/services/cloudtrail/cloudtrail_logs_s3_bucket_access_logging_enabled/cloudtrail_logs_s3_bucket_access_logging_enabled.py index 0fed2c46..7bd1bf62 100644 --- a/prowler/providers/aws/services/cloudtrail/cloudtrail_logs_s3_bucket_access_logging_enabled/cloudtrail_logs_s3_bucket_access_logging_enabled.py +++ b/prowler/providers/aws/services/cloudtrail/cloudtrail_logs_s3_bucket_access_logging_enabled/cloudtrail_logs_s3_bucket_access_logging_enabled.py @@ -10,6 +10,7 @@ class cloudtrail_logs_s3_bucket_access_logging_enabled(Check): findings = [] for trail in cloudtrail_client.trails: if trail.name: + trail_bucket_is_in_account = False trail_bucket = trail.s3_bucket report = Check_Report_AWS(self.metadata()) report.region = trail.region @@ -21,13 +22,19 @@ class cloudtrail_logs_s3_bucket_access_logging_enabled(Check): else: report.status_extended = f"Single region Trail {trail.name} S3 bucket access logging is not enabled for bucket {trail_bucket}" for bucket in s3_client.buckets: - if trail_bucket == bucket.name and bucket.logging: - report.status = "PASS" - if trail.is_multiregion: - report.status_extended = f"Multiregion trail {trail.name} S3 bucket access logging is enabled for bucket {trail_bucket}" - else: - report.status_extended = f"Single region trail {trail.name} S3 bucket access logging is enabled for bucket {trail_bucket}" + if trail_bucket == bucket.name: + trail_bucket_is_in_account = True + if bucket.logging: + report.status = "PASS" + if trail.is_multiregion: + report.status_extended = f"Multiregion trail {trail.name} S3 bucket access logging is enabled for bucket {trail_bucket}" + else: + report.status_extended = f"Single region trail {trail.name} S3 bucket access logging is enabled for bucket {trail_bucket}" + break + # check if trail is delivering logs in a cross account bucket + if not trail_bucket_is_in_account: + report.status_extended = f"Trail {trail.name} is delivering logs in a cross-account bucket {trail_bucket} in another account out of Prowler's permissions scope, please check it manually" findings.append(report) return findings diff --git a/tests/providers/aws/services/cloudtrail/cloudtrail_logs_s3_bucket_access_logging_enabled/cloudtrail_logs_s3_bucket_access_logging_enabled_test.py b/tests/providers/aws/services/cloudtrail/cloudtrail_logs_s3_bucket_access_logging_enabled/cloudtrail_logs_s3_bucket_access_logging_enabled_test.py index f9f513c2..4f17086e 100644 --- a/tests/providers/aws/services/cloudtrail/cloudtrail_logs_s3_bucket_access_logging_enabled/cloudtrail_logs_s3_bucket_access_logging_enabled_test.py +++ b/tests/providers/aws/services/cloudtrail/cloudtrail_logs_s3_bucket_access_logging_enabled/cloudtrail_logs_s3_bucket_access_logging_enabled_test.py @@ -115,3 +115,51 @@ class Test_cloudtrail_logs_s3_bucket_access_logging_enabled: ) assert result[0].resource_id == trail_name_us assert result[0].resource_arn == trail_us["TrailARN"] + + @mock_cloudtrail + @mock_s3 + def test_bucket_cross_account(self): + cloudtrail_client_us_east_1 = client("cloudtrail", region_name="us-east-1") + s3_client_us_east_1 = client("s3", region_name="us-east-1") + trail_name_us = "trail_test_us" + bucket_name_us = "bucket_test_us" + s3_client_us_east_1.create_bucket(Bucket=bucket_name_us) + trail_us = cloudtrail_client_us_east_1.create_trail( + Name=trail_name_us, S3BucketName=bucket_name_us, IsMultiRegionTrail=False + ) + + from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info + from prowler.providers.aws.services.cloudtrail.cloudtrail_service import ( + Cloudtrail, + ) + from prowler.providers.aws.services.s3.s3_service import S3 + + current_audit_info.audited_partition = "aws" + + with mock.patch( + "prowler.providers.aws.services.cloudtrail.cloudtrail_logs_s3_bucket_access_logging_enabled.cloudtrail_logs_s3_bucket_access_logging_enabled.cloudtrail_client", + new=Cloudtrail(current_audit_info), + ): + with mock.patch( + "prowler.providers.aws.services.cloudtrail.cloudtrail_logs_s3_bucket_access_logging_enabled.cloudtrail_logs_s3_bucket_access_logging_enabled.s3_client", + new=S3(current_audit_info), + ) as s3_client: + # Test Check + from prowler.providers.aws.services.cloudtrail.cloudtrail_logs_s3_bucket_access_logging_enabled.cloudtrail_logs_s3_bucket_access_logging_enabled import ( + cloudtrail_logs_s3_bucket_access_logging_enabled, + ) + + # Empty s3 buckets to simulate the bucket is in another account + s3_client.buckets = [] + + check = cloudtrail_logs_s3_bucket_access_logging_enabled() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert search( + "in another account out of Prowler's permissions scope, please check it manually", + result[0].status_extended, + ) + assert result[0].resource_id == trail_name_us + assert result[0].resource_arn == trail_us["TrailARN"]