diff --git a/prowler/providers/aws/services/awslambda/awslambda_function_invoke_api_operations_cloudtrail_logging_enabled/awslambda_function_invoke_api_operations_cloudtrail_logging_enabled.py b/prowler/providers/aws/services/awslambda/awslambda_function_invoke_api_operations_cloudtrail_logging_enabled/awslambda_function_invoke_api_operations_cloudtrail_logging_enabled.py index 385fc6c9..c6524312 100644 --- a/prowler/providers/aws/services/awslambda/awslambda_function_invoke_api_operations_cloudtrail_logging_enabled/awslambda_function_invoke_api_operations_cloudtrail_logging_enabled.py +++ b/prowler/providers/aws/services/awslambda/awslambda_function_invoke_api_operations_cloudtrail_logging_enabled/awslambda_function_invoke_api_operations_cloudtrail_logging_enabled.py @@ -21,15 +21,27 @@ class awslambda_function_invoke_api_operations_cloudtrail_logging_enabled(Check) lambda_recorded_cloudtrail = False for trail in cloudtrail_client.trails: for data_event in trail.data_events: - if "DataResources" in data_event.event_selector: - for resource in data_event.event_selector["DataResources"]: + # classic event selectors + if not data_event.is_advanced: + if "DataResources" in data_event.event_selector: + for resource in data_event.event_selector["DataResources"]: + if resource["Type"] == "AWS::Lambda::Function" and ( + function.arn in resource["Values"] + or "arn:aws:lambda" in resource["Values"] + ): + lambda_recorded_cloudtrail = True + break + elif data_event.is_advanced: + for field_selector in data_event.event_selector[ + "FieldSelectors" + ]: if ( - resource["Type"] == "AWS::Lambda::Function" - and function.arn in resource["Values"] + field_selector["Field"] == "resources.type" + and field_selector["Equals"][0] + == "AWS::Lambda::Function" ): lambda_recorded_cloudtrail = True break - if lambda_recorded_cloudtrail: break if lambda_recorded_cloudtrail: diff --git a/tests/providers/aws/services/awslambda/awslambda_function_invoke_api_operations_cloudtrail_logging_enabled/awslambda_function_invoke_api_operations_cloudtrail_logging_enabled_test.py b/tests/providers/aws/services/awslambda/awslambda_function_invoke_api_operations_cloudtrail_logging_enabled/awslambda_function_invoke_api_operations_cloudtrail_logging_enabled_test.py index 541e3749..be805a77 100644 --- a/tests/providers/aws/services/awslambda/awslambda_function_invoke_api_operations_cloudtrail_logging_enabled/awslambda_function_invoke_api_operations_cloudtrail_logging_enabled_test.py +++ b/tests/providers/aws/services/awslambda/awslambda_function_invoke_api_operations_cloudtrail_logging_enabled/awslambda_function_invoke_api_operations_cloudtrail_logging_enabled_test.py @@ -121,7 +121,6 @@ class Test_awslambda_function_invoke_api_operations_cloudtrail_logging_enabled: "prowler.providers.aws.services.awslambda.awslambda_function_invoke_api_operations_cloudtrail_logging_enabled.awslambda_function_invoke_api_operations_cloudtrail_logging_enabled.cloudtrail_client", new=Cloudtrail(self.set_mocked_audit_info()), ): - # Test Check from prowler.providers.aws.services.awslambda.awslambda_function_invoke_api_operations_cloudtrail_logging_enabled.awslambda_function_invoke_api_operations_cloudtrail_logging_enabled import ( awslambda_function_invoke_api_operations_cloudtrail_logging_enabled, @@ -144,7 +143,7 @@ class Test_awslambda_function_invoke_api_operations_cloudtrail_logging_enabled: @mock_cloudtrail @mock_s3 - def test_lambda_recorded_by_cloudtrail(self): + def test_lambda_recorded_by_cloudtrail_classic_event_selector(self): # Lambda Client lambda_client = mock.MagicMock function_name = "test-lambda" @@ -197,7 +196,157 @@ class Test_awslambda_function_invoke_api_operations_cloudtrail_logging_enabled: "prowler.providers.aws.services.awslambda.awslambda_function_invoke_api_operations_cloudtrail_logging_enabled.awslambda_function_invoke_api_operations_cloudtrail_logging_enabled.cloudtrail_client", new=Cloudtrail(self.set_mocked_audit_info()), ): - + # Test Check + from prowler.providers.aws.services.awslambda.awslambda_function_invoke_api_operations_cloudtrail_logging_enabled.awslambda_function_invoke_api_operations_cloudtrail_logging_enabled import ( + awslambda_function_invoke_api_operations_cloudtrail_logging_enabled, + ) + + check = ( + awslambda_function_invoke_api_operations_cloudtrail_logging_enabled() + ) + result = check.execute() + + assert len(result) == 1 + assert result[0].region == AWS_REGION + assert result[0].resource_id == function_name + assert result[0].resource_arn == function_arn + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Lambda function {function_name} is recorded by CloudTrail {trail_name}" + ) + + @mock_cloudtrail + @mock_s3 + def test_lambda_recorded_by_cloudtrail_advanced_event_selector(self): + # Lambda Client + lambda_client = mock.MagicMock + function_name = "test-lambda" + function_runtime = "python3.9" + function_arn = ( + f"arn:aws:lambda:{AWS_REGION}:{DEFAULT_ACCOUNT_ID}:function/{function_name}" + ) + lambda_client.functions = { + function_name: Function( + name=function_name, + arn=function_arn, + region=AWS_REGION, + runtime=function_runtime, + ) + } + + # CloudTrail Client + cloudtrail_client = client("cloudtrail", region_name=AWS_REGION) + s3_client = client("s3", region_name=AWS_REGION) + trail_name = "test-trail" + bucket_name = "test-bucket" + s3_client.create_bucket(Bucket=bucket_name) + cloudtrail_client.create_trail( + Name=trail_name, S3BucketName=bucket_name, IsMultiRegionTrail=False + ) + _ = cloudtrail_client.put_event_selectors( + TrailName=trail_name, + AdvancedEventSelectors=[ + { + "Name": "lambda", + "FieldSelectors": [ + {"Field": "eventCategory", "Equals": ["Data"]}, + { + "Field": "resources.type", + "Equals": ["AWS::Lambda::Function"], + }, + ], + }, + ], + ) + + from prowler.providers.aws.services.cloudtrail.cloudtrail_service import ( + Cloudtrail, + ) + + with mock.patch( + "prowler.providers.aws.services.awslambda.awslambda_service.Lambda", + new=lambda_client, + ), mock.patch( + "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", + self.set_mocked_audit_info(), + ), mock.patch( + "prowler.providers.aws.services.awslambda.awslambda_function_invoke_api_operations_cloudtrail_logging_enabled.awslambda_function_invoke_api_operations_cloudtrail_logging_enabled.cloudtrail_client", + new=Cloudtrail(self.set_mocked_audit_info()), + ): + # Test Check + from prowler.providers.aws.services.awslambda.awslambda_function_invoke_api_operations_cloudtrail_logging_enabled.awslambda_function_invoke_api_operations_cloudtrail_logging_enabled import ( + awslambda_function_invoke_api_operations_cloudtrail_logging_enabled, + ) + + check = ( + awslambda_function_invoke_api_operations_cloudtrail_logging_enabled() + ) + result = check.execute() + + assert len(result) == 1 + assert result[0].region == AWS_REGION + assert result[0].resource_id == function_name + assert result[0].resource_arn == function_arn + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Lambda function {function_name} is recorded by CloudTrail {trail_name}" + ) + + @mock_cloudtrail + @mock_s3 + def test_all_lambdas_recorded_by_cloudtrail(self): + # Lambda Client + lambda_client = mock.MagicMock + function_name = "test-lambda" + function_runtime = "python3.9" + function_arn = "arn:aws:lambda" + lambda_client.functions = { + function_name: Function( + name=function_name, + arn=function_arn, + region=AWS_REGION, + runtime=function_runtime, + ) + } + + # CloudTrail Client + cloudtrail_client = client("cloudtrail", region_name=AWS_REGION) + s3_client = client("s3", region_name=AWS_REGION) + trail_name = "test-trail" + bucket_name = "test-bucket" + s3_client.create_bucket(Bucket=bucket_name) + cloudtrail_client.create_trail( + Name=trail_name, S3BucketName=bucket_name, IsMultiRegionTrail=False + ) + _ = cloudtrail_client.put_event_selectors( + TrailName=trail_name, + EventSelectors=[ + { + "ReadWriteType": "All", + "IncludeManagementEvents": True, + "DataResources": [ + {"Type": "AWS::Lambda::Function", "Values": [function_arn]} + ], + } + ], + ) + + from prowler.providers.aws.services.cloudtrail.cloudtrail_service import ( + Cloudtrail, + ) + + with mock.patch( + "prowler.providers.aws.services.awslambda.awslambda_service.Lambda", + new=lambda_client, + ), mock.patch( + "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", + self.set_mocked_audit_info(), + ), mock.patch( + "prowler.providers.aws.services.awslambda.awslambda_function_invoke_api_operations_cloudtrail_logging_enabled.awslambda_function_invoke_api_operations_cloudtrail_logging_enabled.cloudtrail_client", + new=Cloudtrail(self.set_mocked_audit_info()), + ): # Test Check from prowler.providers.aws.services.awslambda.awslambda_function_invoke_api_operations_cloudtrail_logging_enabled.awslambda_function_invoke_api_operations_cloudtrail_logging_enabled import ( awslambda_function_invoke_api_operations_cloudtrail_logging_enabled,