From fa4b27dd0e2ea0035024508dbd49707a0b15d198 Mon Sep 17 00:00:00 2001 From: Pepe Fagoaga Date: Thu, 16 Feb 2023 12:47:39 +0100 Subject: [PATCH] fix(compliance): Set Version as optional and fix list (#1899) Co-authored-by: Sergio Garcia --- prowler/__main__.py | 17 +++++++++-------- prowler/lib/check/check.py | 17 +++++++++-------- prowler/lib/check/compliance_models.py | 15 +++++++++++++-- prowler/lib/outputs/compliance.py | 19 ++++++++++--------- 4 files changed, 41 insertions(+), 27 deletions(-) diff --git a/prowler/__main__.py b/prowler/__main__.py index 5d073eb6..bb46dc6d 100644 --- a/prowler/__main__.py +++ b/prowler/__main__.py @@ -216,14 +216,15 @@ def prowler(): ) if compliance_framework and findings: - # Display compliance table - display_compliance_table( - findings, - bulk_checks_metadata, - compliance_framework, - audit_output_options.output_filename, - audit_output_options.output_directory, - ) + for compliance in compliance_framework: + # Display compliance table + display_compliance_table( + findings, + bulk_checks_metadata, + compliance, + audit_output_options.output_filename, + audit_output_options.output_directory, + ) # If there are failed findings exit code 3, except if -z is input if not args.ignore_exit_code_3 and stats["total_fail"] > 0: diff --git a/prowler/lib/check/check.py b/prowler/lib/check/check.py index 430d33fc..11511dc7 100644 --- a/prowler/lib/check/check.py +++ b/prowler/lib/check/check.py @@ -179,17 +179,18 @@ def print_compliance_requirements( bulk_compliance_frameworks: dict, compliance_frameworks: list ): for compliance_framework in compliance_frameworks: - for compliance in bulk_compliance_frameworks.values(): - # Workaround until we have more Compliance Frameworks - split_compliance = compliance_framework.split("_") - framework = split_compliance[0].upper() - version = split_compliance[1].upper() - provider = split_compliance[2].upper() - if framework in compliance.Framework and compliance.Version == version: + for key in bulk_compliance_frameworks.keys(): + framework = bulk_compliance_frameworks[key].Framework + provider = bulk_compliance_frameworks[key].Provider + version = bulk_compliance_frameworks[key].Version + requirements = bulk_compliance_frameworks[key].Requirements + # We can list the compliance requirements for a given framework using the + # bulk_compliance_frameworks keys since they are the compliance specification file name + if compliance_framework == key: print( f"Listing {framework} {version} {provider} Compliance Requirements:\n" ) - for requirement in compliance.Requirements: + for requirement in requirements: checks = "" for check in requirement.Checks: checks += f" {Fore.YELLOW}\t\t{check}\n{Style.RESET_ALL}" diff --git a/prowler/lib/check/compliance_models.py b/prowler/lib/check/compliance_models.py index e7867fa9..02d574a6 100644 --- a/prowler/lib/check/compliance_models.py +++ b/prowler/lib/check/compliance_models.py @@ -2,7 +2,7 @@ import sys from enum import Enum from typing import Optional, Union -from pydantic import BaseModel, ValidationError +from pydantic import BaseModel, ValidationError, root_validator from prowler.lib.logger import logger @@ -107,10 +107,21 @@ class Compliance_Base_Model(BaseModel): Framework: str Provider: str - Version: str + Version: Optional[str] Description: str Requirements: list[Compliance_Requirement] + @root_validator(pre=True) + # noqa: F841 - since vulture raises unused variable 'cls' + def framework_and_provider_must_not_be_empty(cls, values): # noqa: F841 + framework, provider = ( + values.get("Framework"), + values.get("Provider"), + ) + if framework == "" or provider == "": + raise ValueError("Framework or Provider must not be empty") + return values + # Testing Pending def load_compliance_framework( diff --git a/prowler/lib/outputs/compliance.py b/prowler/lib/outputs/compliance.py index ddc39397..61705d81 100644 --- a/prowler/lib/outputs/compliance.py +++ b/prowler/lib/outputs/compliance.py @@ -4,7 +4,7 @@ from csv import DictWriter from colorama import Fore, Style from tabulate import tabulate -from prowler.config.config import timestamp, orange_color +from prowler.config.config import orange_color, timestamp from prowler.lib.logger import logger from prowler.lib.outputs.models import ( Check_Output_CSV_CIS, @@ -167,7 +167,7 @@ def display_compliance_table( output_directory: str, ): try: - if "ens_rd2022_aws" in compliance_framework: + if "ens_rd2022_aws" == compliance_framework: marcos = {} ens_compliance_table = { "Proveedor": [], @@ -266,9 +266,9 @@ def display_compliance_table( ) print(f"\nResultados detallados de {compliance_fm} en:") print( - f" - CSV: {output_directory}/{output_filename}_{compliance_framework[0]}.csv\n" + f" - CSV: {output_directory}/{output_filename}_{compliance_framework}.csv\n" ) - elif "cis_1." in str(compliance_framework): + elif "cis_1." in compliance_framework: sections = {} cis_compliance_table = { "Provider": [], @@ -281,8 +281,9 @@ def display_compliance_table( check = bulk_checks_metadata[finding.check_metadata.CheckID] check_compliances = check.Compliance for compliance in check_compliances: - if compliance.Framework == "CIS" and compliance.Version in str( - compliance_framework + if ( + compliance.Framework == "CIS" + and compliance.Version in compliance_framework ): compliance_version = compliance.Version compliance_fm = compliance.Framework @@ -360,12 +361,12 @@ def display_compliance_table( ) print(f"\nDetailed results of {compliance_fm} are in:") print( - f" - CSV: {output_directory}/{output_filename}_{compliance_framework[0]}.csv\n" + f" - CSV: {output_directory}/{output_filename}_{compliance_framework}.csv\n" ) else: - print(f"\nDetailed results of {compliance_framework[0].upper()} are in:") + print(f"\nDetailed results of {compliance_framework.upper()} are in:") print( - f" - CSV: {output_directory}/{output_filename}_{compliance_framework[0]}.csv\n" + f" - CSV: {output_directory}/{output_filename}_{compliance_framework}.csv\n" ) except Exception as error: logger.critical(