From 9ceaefb663eeb18e5c6edea5b6f905b69db77c1e Mon Sep 17 00:00:00 2001 From: Pepe Fagoaga Date: Wed, 10 May 2023 15:44:14 +0200 Subject: [PATCH] fix(access-analyzer): Handle ResourceNotFoundException (#2336) --- .../accessanalyzer/accessanalyzer_service.py | 20 ++++- ...sanalyzer_enabled_without_findings_test.py | 85 +++++++++++++++---- 2 files changed, 83 insertions(+), 22 deletions(-) diff --git a/prowler/providers/aws/services/accessanalyzer/accessanalyzer_service.py b/prowler/providers/aws/services/accessanalyzer/accessanalyzer_service.py index dfe75d4c..47dcce19 100644 --- a/prowler/providers/aws/services/accessanalyzer/accessanalyzer_service.py +++ b/prowler/providers/aws/services/accessanalyzer/accessanalyzer_service.py @@ -1,6 +1,7 @@ import threading from typing import Optional +from botocore.exceptions import ClientError from pydantic import BaseModel from prowler.lib.logger import logger @@ -79,10 +80,21 @@ class AccessAnalyzer: if analyzer.status == "ACTIVE": regional_client = self.regional_clients[analyzer.region] for finding in analyzer.findings: - finding_information = regional_client.get_finding( - analyzerArn=analyzer.arn, id=finding.id - ) - finding.status = finding_information["finding"]["status"] + try: + finding_information = regional_client.get_finding( + analyzerArn=analyzer.arn, id=finding.id + ) + finding.status = finding_information["finding"]["status"] + except ClientError as error: + if ( + error.response["Error"]["Code"] + == "ResourceNotFoundException" + ): + logger.warning( + f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + finding.status = "" + continue except Exception as error: logger.error( diff --git a/tests/providers/aws/services/accessanalyzer/accessanalyzer_enabled_without_findings/accessanalyzer_enabled_without_findings_test.py b/tests/providers/aws/services/accessanalyzer/accessanalyzer_enabled_without_findings/accessanalyzer_enabled_without_findings_test.py index bc3fdcbe..d4260bc9 100644 --- a/tests/providers/aws/services/accessanalyzer/accessanalyzer_enabled_without_findings/accessanalyzer_enabled_without_findings_test.py +++ b/tests/providers/aws/services/accessanalyzer/accessanalyzer_enabled_without_findings/accessanalyzer_enabled_without_findings_test.py @@ -5,6 +5,10 @@ from prowler.providers.aws.services.accessanalyzer.accessanalyzer_service import Finding, ) +AWS_REGION_1 = "eu-west-1" +AWS_REGION_2 = "eu-west-2" +AWS_ACCOUNT_NUMBER = "123456789012" + class Test_accessanalyzer_enabled_without_findings: def test_no_analyzers(self): @@ -30,11 +34,12 @@ class Test_accessanalyzer_enabled_without_findings: accessanalyzer_client.analyzers = [ Analyzer( arn="", - name="012345678910", + name=AWS_ACCOUNT_NUMBER, status="NOT_AVAILABLE", tags=[], type="", - region="eu-west-1", + fidings=[], + region=AWS_REGION_1, ) ] with mock.patch( @@ -52,20 +57,21 @@ class Test_accessanalyzer_enabled_without_findings: assert result[0].status == "FAIL" assert ( result[0].status_extended - == "IAM Access Analyzer in account 012345678910 is not enabled" + == f"IAM Access Analyzer in account {AWS_ACCOUNT_NUMBER} is not enabled" ) - assert result[0].resource_id == "012345678910" + assert result[0].resource_id == AWS_ACCOUNT_NUMBER def test_two_analyzers(self): accessanalyzer_client = mock.MagicMock accessanalyzer_client.analyzers = [ Analyzer( arn="", - name="012345678910", + name=AWS_ACCOUNT_NUMBER, status="NOT_AVAILABLE", tags=[], + fidings=[], type="", - region="eu-west-1", + region=AWS_REGION_1, ), Analyzer( arn="", @@ -83,7 +89,7 @@ class Test_accessanalyzer_enabled_without_findings: ], tags=[], type="", - region="eu-west-2", + region=AWS_REGION_2, ), ] @@ -104,17 +110,17 @@ class Test_accessanalyzer_enabled_without_findings: assert result[0].status == "FAIL" assert ( result[0].status_extended - == "IAM Access Analyzer in account 012345678910 is not enabled" + == f"IAM Access Analyzer in account {AWS_ACCOUNT_NUMBER} is not enabled" ) - assert result[0].resource_id == "012345678910" - assert result[0].region == "eu-west-1" + assert result[0].resource_id == AWS_ACCOUNT_NUMBER + assert result[0].region == AWS_REGION_1 assert result[1].status == "FAIL" assert ( result[1].status_extended == "IAM Access Analyzer Test Analyzer has 1 active findings" ) assert result[1].resource_id == "Test Analyzer" - assert result[1].region == "eu-west-2" + assert result[1].region == AWS_REGION_2 def test_one_active_analyzer_without_findings(self): accessanalyzer_client = mock.MagicMock @@ -124,8 +130,9 @@ class Test_accessanalyzer_enabled_without_findings: name="Test Analyzer", status="ACTIVE", tags=[], + fidings=[], type="", - region="eu-west-2", + region=AWS_REGION_2, ) ] @@ -148,18 +155,19 @@ class Test_accessanalyzer_enabled_without_findings: == "IAM Access Analyzer Test Analyzer does not have active findings" ) assert result[0].resource_id == "Test Analyzer" - assert result[0].region == "eu-west-2" + assert result[0].region == AWS_REGION_2 def test_one_active_analyzer_not_active(self): accessanalyzer_client = mock.MagicMock accessanalyzer_client.analyzers = [ Analyzer( arn="", - name="012345678910", + name=AWS_ACCOUNT_NUMBER, status="NOT_AVAILABLE", tags=[], + fidings=[], type="", - region="eu-west-1", + region=AWS_REGION_1, ), ] # Patch AccessAnalyzer Client @@ -179,7 +187,48 @@ class Test_accessanalyzer_enabled_without_findings: assert result[0].status == "FAIL" assert ( result[0].status_extended - == "IAM Access Analyzer in account 012345678910 is not enabled" + == f"IAM Access Analyzer in account {AWS_ACCOUNT_NUMBER} is not enabled" ) - assert result[0].resource_id == "012345678910" - assert result[0].region == "eu-west-1" + assert result[0].resource_id == AWS_ACCOUNT_NUMBER + assert result[0].region == AWS_REGION_1 + + def test_analyzer_finding_without_status(self): + accessanalyzer_client = mock.MagicMock + accessanalyzer_client.analyzers = [ + Analyzer( + arn="", + name="Test Analyzer", + status="ACTIVE", + findings=[ + Finding( + id="test-finding-1", + status="", + ), + ], + tags=[], + type="", + region=AWS_REGION_1, + ), + ] + + # Patch AccessAnalyzer Client + with mock.patch( + "prowler.providers.aws.services.accessanalyzer.accessanalyzer_service.AccessAnalyzer", + new=accessanalyzer_client, + ): + # Test Check + from prowler.providers.aws.services.accessanalyzer.accessanalyzer_enabled_without_findings.accessanalyzer_enabled_without_findings import ( + accessanalyzer_enabled_without_findings, + ) + + check = accessanalyzer_enabled_without_findings() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == "IAM Access Analyzer Test Analyzer does not have active findings" + ) + assert result[0].resource_id == "Test Analyzer" + assert result[0].region == AWS_REGION_1