From a980b2606bd1697fd3d0b0f0b62be53161676b85 Mon Sep 17 00:00:00 2001 From: Pepe Fagoaga Date: Fri, 15 Sep 2023 11:36:40 +0200 Subject: [PATCH] fix(cloudtrail_s3_dataevents_read/write_enabled): Handle S3 ARN (#2844) --- .../cloudtrail_s3_dataevents_read_enabled.py | 2 + .../cloudtrail_s3_dataevents_write_enabled.py | 2 + ...udtrail_s3_dataevents_read_enabled_test.py | 63 +++++++++++++++++++ ...dtrail_s3_dataevents_write_enabled_test.py | 63 +++++++++++++++++++ 4 files changed, 130 insertions(+) diff --git a/prowler/providers/aws/services/cloudtrail/cloudtrail_s3_dataevents_read_enabled/cloudtrail_s3_dataevents_read_enabled.py b/prowler/providers/aws/services/cloudtrail/cloudtrail_s3_dataevents_read_enabled/cloudtrail_s3_dataevents_read_enabled.py index 5496e9f6..a46a6e7b 100644 --- a/prowler/providers/aws/services/cloudtrail/cloudtrail_s3_dataevents_read_enabled/cloudtrail_s3_dataevents_read_enabled.py +++ b/prowler/providers/aws/services/cloudtrail/cloudtrail_s3_dataevents_read_enabled/cloudtrail_s3_dataevents_read_enabled.py @@ -26,6 +26,8 @@ class cloudtrail_s3_dataevents_read_enabled(Check): if "AWS::S3::Object" == resource["Type"] and ( f"arn:{cloudtrail_client.audited_partition}:s3" in resource["Values"] + or f"arn:{cloudtrail_client.audited_partition}:s3:::" + in resource["Values"] or f"arn:{cloudtrail_client.audited_partition}:s3:::*/*" in resource["Values"] ): diff --git a/prowler/providers/aws/services/cloudtrail/cloudtrail_s3_dataevents_write_enabled/cloudtrail_s3_dataevents_write_enabled.py b/prowler/providers/aws/services/cloudtrail/cloudtrail_s3_dataevents_write_enabled/cloudtrail_s3_dataevents_write_enabled.py index 942be579..d2ca2e62 100644 --- a/prowler/providers/aws/services/cloudtrail/cloudtrail_s3_dataevents_write_enabled/cloudtrail_s3_dataevents_write_enabled.py +++ b/prowler/providers/aws/services/cloudtrail/cloudtrail_s3_dataevents_write_enabled/cloudtrail_s3_dataevents_write_enabled.py @@ -26,6 +26,8 @@ class cloudtrail_s3_dataevents_write_enabled(Check): if "AWS::S3::Object" == resource["Type"] and ( f"arn:{cloudtrail_client.audited_partition}:s3" in resource["Values"] + or f"arn:{cloudtrail_client.audited_partition}:s3:::" + in resource["Values"] or f"arn:{cloudtrail_client.audited_partition}:s3:::*/*" in resource["Values"] ): diff --git a/tests/providers/aws/services/cloudtrail/cloudtrail_s3_dataevents_read_enabled/cloudtrail_s3_dataevents_read_enabled_test.py b/tests/providers/aws/services/cloudtrail/cloudtrail_s3_dataevents_read_enabled/cloudtrail_s3_dataevents_read_enabled_test.py index 54c643d7..40a4d9d1 100644 --- a/tests/providers/aws/services/cloudtrail/cloudtrail_s3_dataevents_read_enabled/cloudtrail_s3_dataevents_read_enabled_test.py +++ b/tests/providers/aws/services/cloudtrail/cloudtrail_s3_dataevents_read_enabled/cloudtrail_s3_dataevents_read_enabled_test.py @@ -261,3 +261,66 @@ class Test_cloudtrail_s3_dataevents_read_enabled: assert result[0].resource_arn == trail_us["TrailARN"] assert result[0].resource_tags == [] assert result[0].region == AWS_REGION + + @mock_cloudtrail + @mock_s3 + def test_trail_with_s3_three_colons(self): + cloudtrail_client_us_east_1 = client("cloudtrail", region_name=AWS_REGION) + s3_client_us_east_1 = client("s3", region_name=AWS_REGION) + 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 + ) + _ = cloudtrail_client_us_east_1.put_event_selectors( + TrailName=trail_name_us, + EventSelectors=[ + { + "ReadWriteType": "All", + "IncludeManagementEvents": True, + "DataResources": [ + { + "Type": "AWS::DynamoDB::Table", + "Values": ["arn:aws:dynamodb"], + }, + {"Type": "AWS::S3::Object", "Values": ["arn:aws:s3:::"]}, + {"Type": "AWS::Lambda::Function", "Values": ["arn:aws:lambda"]}, + ], + "ExcludeManagementEventSources": [], + } + ], + )["EventSelectors"] + + from prowler.providers.aws.services.cloudtrail.cloudtrail_service import ( + Cloudtrail, + ) + + current_audit_info = self.set_mocked_audit_info() + + with mock.patch( + "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", + new=current_audit_info, + ): + with mock.patch( + "prowler.providers.aws.services.cloudtrail.cloudtrail_s3_dataevents_read_enabled.cloudtrail_s3_dataevents_read_enabled.cloudtrail_client", + new=Cloudtrail(current_audit_info), + ): + # Test Check + from prowler.providers.aws.services.cloudtrail.cloudtrail_s3_dataevents_read_enabled.cloudtrail_s3_dataevents_read_enabled import ( + cloudtrail_s3_dataevents_read_enabled, + ) + + check = cloudtrail_s3_dataevents_read_enabled() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert search( + "has a classic data event selector to record all S3 object-level API operations.", + result[0].status_extended, + ) + assert result[0].resource_id == trail_name_us + assert result[0].resource_arn == trail_us["TrailARN"] + assert result[0].resource_tags == [] + assert result[0].region == AWS_REGION diff --git a/tests/providers/aws/services/cloudtrail/cloudtrail_s3_dataevents_write_enabled/cloudtrail_s3_dataevents_write_enabled_test.py b/tests/providers/aws/services/cloudtrail/cloudtrail_s3_dataevents_write_enabled/cloudtrail_s3_dataevents_write_enabled_test.py index f223a436..f811db1b 100644 --- a/tests/providers/aws/services/cloudtrail/cloudtrail_s3_dataevents_write_enabled/cloudtrail_s3_dataevents_write_enabled_test.py +++ b/tests/providers/aws/services/cloudtrail/cloudtrail_s3_dataevents_write_enabled/cloudtrail_s3_dataevents_write_enabled_test.py @@ -259,3 +259,66 @@ class Test_cloudtrail_s3_dataevents_write_enabled: assert result[0].resource_arn == trail_us["TrailARN"] assert result[0].resource_tags == [] assert result[0].region == AWS_REGION + + @mock_cloudtrail + @mock_s3 + def test_trail_with_s3_three_colons(self): + cloudtrail_client_us_east_1 = client("cloudtrail", region_name=AWS_REGION) + s3_client_us_east_1 = client("s3", region_name=AWS_REGION) + 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 + ) + _ = cloudtrail_client_us_east_1.put_event_selectors( + TrailName=trail_name_us, + EventSelectors=[ + { + "ReadWriteType": "All", + "IncludeManagementEvents": True, + "DataResources": [ + { + "Type": "AWS::DynamoDB::Table", + "Values": ["arn:aws:dynamodb"], + }, + {"Type": "AWS::S3::Object", "Values": ["arn:aws:s3:::"]}, + {"Type": "AWS::Lambda::Function", "Values": ["arn:aws:lambda"]}, + ], + "ExcludeManagementEventSources": [], + } + ], + )["EventSelectors"] + + from prowler.providers.aws.services.cloudtrail.cloudtrail_service import ( + Cloudtrail, + ) + + current_audit_info = self.set_mocked_audit_info() + + with mock.patch( + "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", + new=current_audit_info, + ): + with mock.patch( + "prowler.providers.aws.services.cloudtrail.cloudtrail_s3_dataevents_write_enabled.cloudtrail_s3_dataevents_write_enabled.cloudtrail_client", + new=Cloudtrail(current_audit_info), + ): + # Test Check + from prowler.providers.aws.services.cloudtrail.cloudtrail_s3_dataevents_write_enabled.cloudtrail_s3_dataevents_write_enabled import ( + cloudtrail_s3_dataevents_write_enabled, + ) + + check = cloudtrail_s3_dataevents_write_enabled() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert search( + "has a classic data event selector to record all S3 object-level API operations.", + result[0].status_extended, + ) + assert result[0].resource_id == trail_name_us + assert result[0].resource_arn == trail_us["TrailARN"] + assert result[0].resource_tags == [] + assert result[0].region == AWS_REGION