From fcc56ad6f72b1f43a57c6030f4ed33263db39570 Mon Sep 17 00:00:00 2001 From: Pepe Fagoaga Date: Mon, 30 Oct 2023 09:52:59 +0100 Subject: [PATCH] chore(allowlist): Extract allowlist from report (#2975) --- prowler/lib/check/check.py | 6 +++ prowler/lib/outputs/outputs.py | 13 ------- .../providers/aws/lib/allowlist/allowlist.py | 26 ++++++++++++- .../aws/lib/allowlist/allowlist_test.py | 38 ++++++++++++++++++- 4 files changed, 68 insertions(+), 15 deletions(-) diff --git a/prowler/lib/check/check.py b/prowler/lib/check/check.py index 0fa107ac..71f80356 100644 --- a/prowler/lib/check/check.py +++ b/prowler/lib/check/check.py @@ -20,6 +20,7 @@ from prowler.lib.check.models import Check, load_check_metadata from prowler.lib.logger import logger from prowler.lib.outputs.outputs import report from prowler.lib.utils.utils import open_file, parse_json_file +from prowler.providers.aws.lib.allowlist.allowlist import allowlist_findings from prowler.providers.common.models import Audit_Metadata from prowler.providers.common.outputs import Provider_Output_Options @@ -554,6 +555,11 @@ def execute( audit_info.audit_metadata, services_executed, checks_executed ) + # Allowlist findings + check_findings = allowlist_findings( + audit_output_options.allowlist_file, audit_info.audited_account, check_findings + ) + # Report the check's findings report(check_findings, audit_output_options, audit_info) diff --git a/prowler/lib/outputs/outputs.py b/prowler/lib/outputs/outputs.py index fce5d225..cd114012 100644 --- a/prowler/lib/outputs/outputs.py +++ b/prowler/lib/outputs/outputs.py @@ -12,9 +12,7 @@ from prowler.lib.outputs.models import ( Check_Output_JSON_ASFF, generate_provider_output_csv, generate_provider_output_json, - unroll_tags, ) -from prowler.providers.aws.lib.allowlist.allowlist import is_allowlisted from prowler.providers.aws.lib.audit_info.models import AWS_Audit_Info from prowler.providers.azure.lib.audit_info.models import Azure_Audit_Info @@ -56,17 +54,6 @@ def report(check_findings, output_options, audit_info): if check_findings: for finding in check_findings: - # Check if finding is allowlisted - if output_options.allowlist_file: - if is_allowlisted( - output_options.allowlist_file, - audit_info.audited_account, - finding.check_metadata.CheckID, - finding.region, - finding.resource_id, - unroll_tags(finding.resource_tags), - ): - finding.status = "WARNING" # Print findings by stdout color = set_report_color(finding.status) stdout_report( diff --git a/prowler/providers/aws/lib/allowlist/allowlist.py b/prowler/providers/aws/lib/allowlist/allowlist.py index 00ffe4cc..5becf54d 100644 --- a/prowler/providers/aws/lib/allowlist/allowlist.py +++ b/prowler/providers/aws/lib/allowlist/allowlist.py @@ -1,11 +1,13 @@ import re import sys +from typing import Any import yaml from boto3.dynamodb.conditions import Attr from schema import Optional, Schema from prowler.lib.logger import logger +from prowler.lib.outputs.models import unroll_tags allowlist_schema = Schema( { @@ -113,7 +115,29 @@ def parse_allowlist_file(audit_info, allowlist_file): sys.exit(1) -def is_allowlisted(allowlist, audited_account, check, region, resource, tags): +def allowlist_findings( + allowlist: dict, + audited_account: str, + check_findings: [Any], +): + # Check if finding is allowlisted + if allowlist: + for finding in check_findings: + if is_allowlisted( + allowlist, + audited_account, + finding.check_metadata.CheckID, + finding.region, + finding.resource_id, + unroll_tags(finding.resource_tags), + ): + finding.status = "WARNING" + return check_findings + + +def is_allowlisted( + allowlist: dict, audited_account: str, check: str, region: str, resource: str, tags +): try: allowlisted_checks = {} # By default is not allowlisted diff --git a/tests/providers/aws/lib/allowlist/allowlist_test.py b/tests/providers/aws/lib/allowlist/allowlist_test.py index 1270b61d..4bd624be 100644 --- a/tests/providers/aws/lib/allowlist/allowlist_test.py +++ b/tests/providers/aws/lib/allowlist/allowlist_test.py @@ -1,8 +1,10 @@ import yaml from boto3 import resource, session +from mock import MagicMock from moto import mock_dynamodb, mock_s3 from prowler.providers.aws.lib.allowlist.allowlist import ( + allowlist_findings, is_allowlisted, is_allowlisted_in_check, is_allowlisted_in_region, @@ -158,7 +160,41 @@ class Test_Allowlist: )["Accounts"]["*"]["Checks"]["*"]["Tags"] ) - # Allowlist checks + # Allowlist tests + + def test_allowlist_findings(self): + # Allowlist example + allowlist = { + "Accounts": { + "*": { + "Checks": { + "check_test": { + "Regions": [AWS_REGION, "eu-west-1"], + "Resources": ["prowler", "^test", "prowler-pro"], + } + } + } + } + } + + # Check Findings + check_findings = [] + finding_1 = MagicMock + finding_1.check_metadata = MagicMock + finding_1.check_metadata.CheckID = "check_test" + finding_1.status = "FAIL" + finding_1.region = AWS_REGION + finding_1.resource_id = "prowler" + finding_1.resource_tags = [] + + check_findings.append(finding_1) + + allowlisted_findings = allowlist_findings( + allowlist, AWS_ACCOUNT_NUMBER, check_findings + ) + assert len(allowlisted_findings) == 1 + assert allowlisted_findings[0].status == "WARNING" + def test_is_allowlisted(self): # Allowlist example allowlist = {