diff --git a/prowler/providers/aws/services/guardduty/guardduty_lambda_protection_enabled/__init__.py b/prowler/providers/aws/services/guardduty/guardduty_lambda_protection_enabled/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/aws/services/guardduty/guardduty_lambda_protection_enabled/guardduty_lambda_protection_enabled.metadata.json b/prowler/providers/aws/services/guardduty/guardduty_lambda_protection_enabled/guardduty_lambda_protection_enabled.metadata.json new file mode 100644 index 0000000000..57fda8b12f --- /dev/null +++ b/prowler/providers/aws/services/guardduty/guardduty_lambda_protection_enabled/guardduty_lambda_protection_enabled.metadata.json @@ -0,0 +1,32 @@ +{ + "Provider": "aws", + "CheckID": "guardduty_lambda_protection_enabled", + "CheckTitle": "Check if GuardDuty Lambda Protection is enabled.", + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices" + ], + "ServiceName": "guardduty", + "SubServiceName": "", + "ResourceIdTemplate": "arn:aws:guardduty:region:account-id/detector-id", + "Severity": "high", + "ResourceType": "", + "Description": "GuardDuty Lambda Protection helps you identify potential security threats when an AWS Lambda function gets invoked. After you enable Lambda Protection, GuardDuty starts monitoring Lambda network activity logs associated with the Lambda functions in your AWS account.", + "Risk": "If Lambda Protection is not enabled, GuardDuty will not be able to monitor Lambda network activity logs and may miss potential security threats.", + "RelatedUrl": "https://docs.aws.amazon.com/guardduty/latest/ug/lambda-protection.html", + "Remediation": { + "Code": { + "CLI": "aws guardduty update-detector --detector-id --features Name=LAMBDA_NETWORK_LOGS,Status=ENABLED", + "NativeIaC": "", + "Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/guardduty-controls.html#guardduty-6", + "Terraform": "" + }, + "Recommendation": { + "Text": "Enable Lambda Protection in your GuardDuty detector to start monitoring Lambda Network Activity in your account.", + "Url": "https://docs.aws.amazon.com/guardduty/latest/ug/configure-lambda-protection-standalone-acc.html" + } + }, + "Categories": [], + "Notes": "", + "DependsOn": [], + "RelatedTo": [] +} diff --git a/prowler/providers/aws/services/guardduty/guardduty_lambda_protection_enabled/guardduty_lambda_protection_enabled.py b/prowler/providers/aws/services/guardduty/guardduty_lambda_protection_enabled/guardduty_lambda_protection_enabled.py new file mode 100644 index 0000000000..b304f8f788 --- /dev/null +++ b/prowler/providers/aws/services/guardduty/guardduty_lambda_protection_enabled/guardduty_lambda_protection_enabled.py @@ -0,0 +1,21 @@ +from prowler.lib.check.models import Check, Check_Report_AWS +from prowler.providers.aws.services.guardduty.guardduty_client import guardduty_client + + +class guardduty_lambda_protection_enabled(Check): + def execute(self): + findings = [] + for detector in guardduty_client.detectors: + if detector.status: + report = Check_Report_AWS(self.metadata()) + report.region = detector.region + report.resource_id = detector.id + report.resource_arn = detector.arn + report.resource_tags = detector.tags + report.status = "FAIL" + report.status_extended = f"GuardDuty detector {detector.id} does not have Lambda Protection enabled." + if detector.lambda_protection: + report.status = "PASS" + report.status_extended = f"GuardDuty detector {detector.id} has Lambda Protection enabled." + findings.append(report) + return findings diff --git a/prowler/providers/aws/services/guardduty/guardduty_service.py b/prowler/providers/aws/services/guardduty/guardduty_service.py index a21f09e2db..01ce461919 100644 --- a/prowler/providers/aws/services/guardduty/guardduty_service.py +++ b/prowler/providers/aws/services/guardduty/guardduty_service.py @@ -53,44 +53,58 @@ class GuardDuty(AWSService): def _get_detector(self, detector): logger.info("GuardDuty - getting detector info...") try: - if detector.id and detector.enabled_in_account: - detector_info = self.regional_clients[detector.region].get_detector( - DetectorId=detector.id - ) - if "Status" in detector_info and detector_info["Status"] == "ENABLED": - detector.status = True - - data_sources = detector_info.get("DataSources", {}) - - s3_logs = data_sources.get("S3Logs", {}) - if s3_logs.get("Status", "DISABLED") == "ENABLED": - detector.s3_protection = True - - detector.eks_audit_log_protection = ( - True - if data_sources.get("Kubernetes", {}) - .get("AuditLogs", {}) - .get("Status", "DISABLED") - == "ENABLED" - else False - ) - - detector.ec2_malware_protection = ( - True - if data_sources.get("MalwareProtection", {}) - .get("ScanEc2InstanceWithFindings", {}) - .get("EbsVolumes", {}) - .get("Status", "DISABLED") - == "ENABLED" - else False - ) - - for feat in detector_info.get("Features", []): + try: + if detector.id and detector.enabled_in_account: + detector_info = self.regional_clients[detector.region].get_detector( + DetectorId=detector.id + ) if ( - feat.get("Name") == "RDS_LOGIN_EVENTS" - and feat.get("Status", "DISABLED") == "ENABLED" + "Status" in detector_info + and detector_info["Status"] == "ENABLED" ): - detector.rds_protection = True + detector.status = True + + data_sources = detector_info.get("DataSources", {}) + + s3_logs = data_sources.get("S3Logs", {}) + if s3_logs.get("Status", "DISABLED") == "ENABLED": + detector.s3_protection = True + + detector.eks_audit_log_protection = ( + True + if data_sources.get("Kubernetes", {}) + .get("AuditLogs", {}) + .get("Status", "DISABLED") + == "ENABLED" + else False + ) + + detector.ec2_malware_protection = ( + True + if data_sources.get("MalwareProtection", {}) + .get("ScanEc2InstanceWithFindings", {}) + .get("EbsVolumes", {}) + .get("Status", "DISABLED") + == "ENABLED" + else False + ) + + for feat in detector_info.get("Features", []): + if ( + feat.get("Name", "") == "RDS_LOGIN_EVENTS" + and feat.get("Status", "DISABLED") == "ENABLED" + ): + detector.rds_protection = True + elif ( + feat.get("Name", "") == "LAMBDA_NETWORK_LOGS" + and feat.get("Status", "DISABLED") == "ENABLED" + ): + detector.lambda_protection = True + + except Exception as error: + logger.error( + f"{error.__class__.__name__}:{error.__traceback__.tb_lineno} -- {error}" + ) except Exception as error: logger.error( f"{error.__class__.__name__}:{error.__traceback__.tb_lineno} -- {error}" @@ -214,4 +228,5 @@ class Detector(BaseModel): s3_protection: bool = False rds_protection: bool = False eks_audit_log_protection: bool = False + lambda_protection: bool = False ec2_malware_protection: bool = False diff --git a/tests/providers/aws/services/guardduty/guardduty_lambda_protection_enabled/guardduty_lambda_protection_enabled_test.py b/tests/providers/aws/services/guardduty/guardduty_lambda_protection_enabled/guardduty_lambda_protection_enabled_test.py new file mode 100644 index 0000000000..78eb2cc9ad --- /dev/null +++ b/tests/providers/aws/services/guardduty/guardduty_lambda_protection_enabled/guardduty_lambda_protection_enabled_test.py @@ -0,0 +1,148 @@ +from unittest.mock import patch + +import botocore +from boto3 import client +from moto import mock_aws + +from tests.providers.aws.utils import ( + AWS_ACCOUNT_NUMBER, + AWS_REGION_EU_WEST_1, + set_mocked_aws_provider, +) + +orig = botocore.client.BaseClient._make_api_call + + +class Test_guardduty_lambda_protection_enabled: + def test_no_detectors(self): + aws_provider = set_mocked_aws_provider() + + from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty + + with patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), patch( + "prowler.providers.aws.services.guardduty.guardduty_lambda_protection_enabled.guardduty_lambda_protection_enabled.guardduty_client", + new=GuardDuty(aws_provider), + ): + # Test Check + from prowler.providers.aws.services.guardduty.guardduty_lambda_protection_enabled.guardduty_lambda_protection_enabled import ( + guardduty_lambda_protection_enabled, + ) + + check = guardduty_lambda_protection_enabled() + result = check.execute() + + assert len(result) == 0 + + @mock_aws + def test_detector_disabled(self): + guardduty_client = client("guardduty", region_name=AWS_REGION_EU_WEST_1) + + guardduty_client.create_detector(Enable=False) + + aws_provider = set_mocked_aws_provider() + + from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty + + with patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), patch( + "prowler.providers.aws.services.guardduty.guardduty_lambda_protection_enabled.guardduty_lambda_protection_enabled.guardduty_client", + new=GuardDuty(aws_provider), + ): + # Test Check + from prowler.providers.aws.services.guardduty.guardduty_lambda_protection_enabled.guardduty_lambda_protection_enabled import ( + guardduty_lambda_protection_enabled, + ) + + check = guardduty_lambda_protection_enabled() + result = check.execute() + + assert len(result) == 0 + + @mock_aws + def test_detector_lambda_protection_enabled(self): + guardduty_client = client("guardduty", region_name=AWS_REGION_EU_WEST_1) + + detector_id = guardduty_client.create_detector( + Enable=True, + Features=[{"Name": "LAMBDA_NETWORK_LOGS", "Status": "ENABLED"}], + )["DetectorId"] + + aws_provider = set_mocked_aws_provider() + + from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty + + with patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), patch( + "prowler.providers.aws.services.guardduty.guardduty_lambda_protection_enabled.guardduty_lambda_protection_enabled.guardduty_client", + new=GuardDuty(aws_provider), + ): + # Test Check + from prowler.providers.aws.services.guardduty.guardduty_lambda_protection_enabled.guardduty_lambda_protection_enabled import ( + guardduty_lambda_protection_enabled, + ) + + check = guardduty_lambda_protection_enabled() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"GuardDuty detector {detector_id} has Lambda Protection enabled." + ) + assert result[0].resource_id == detector_id + assert result[0].region == AWS_REGION_EU_WEST_1 + assert ( + result[0].resource_arn + == f"arn:aws:guardduty:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:detector/{detector_id}" + ) + assert result[0].resource_tags == [] + + @mock_aws + def test_detector_lambda_protection_disabled(self): + guardduty_client = client("guardduty", region_name=AWS_REGION_EU_WEST_1) + + detector_id = guardduty_client.create_detector( + Enable=True, + Features=[{"Name": "LAMBDA_NETWORK_LOGS", "Status": "DISABLED"}], + )["DetectorId"] + + aws_provider = set_mocked_aws_provider() + + from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty + + with patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), patch( + "prowler.providers.aws.services.guardduty.guardduty_lambda_protection_enabled.guardduty_lambda_protection_enabled.guardduty_client", + new=GuardDuty(aws_provider), + ): + # Test Check + from prowler.providers.aws.services.guardduty.guardduty_lambda_protection_enabled.guardduty_lambda_protection_enabled import ( + guardduty_lambda_protection_enabled, + ) + + check = guardduty_lambda_protection_enabled() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"GuardDuty detector {detector_id} does not have Lambda Protection enabled." + ) + assert result[0].resource_id == detector_id + assert result[0].region == AWS_REGION_EU_WEST_1 + assert ( + result[0].resource_arn + == f"arn:aws:guardduty:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:detector/{detector_id}" + ) + assert result[0].resource_tags == [] diff --git a/tests/providers/aws/services/guardduty/guardduty_service_test.py b/tests/providers/aws/services/guardduty/guardduty_service_test.py index e401419c13..532020f083 100644 --- a/tests/providers/aws/services/guardduty/guardduty_service_test.py +++ b/tests/providers/aws/services/guardduty/guardduty_service_test.py @@ -115,6 +115,7 @@ class Test_GuardDuty_Service: "S3Logs": {"Enable": True}, "Kubernetes": {"AuditLogs": {"Enable": True}}, }, + Features=[{"Name": "LAMBDA_NETWORK_LOGS", "Status": "ENABLED"}], ) aws_provider = set_mocked_aws_provider() @@ -133,6 +134,7 @@ class Test_GuardDuty_Service: assert guardduty.detectors[0].s3_protection assert not guardduty.detectors[0].rds_protection assert guardduty.detectors[0].eks_audit_log_protection + assert guardduty.detectors[0].lambda_protection assert not guardduty.detectors[0].ec2_malware_protection assert guardduty.detectors[0].region == AWS_REGION_EU_WEST_1 assert guardduty.detectors[0].tags == [{"test": "test"}]