Merge branch 'PRWLR-7300-create-ia-c-provider' into PRWLR-7318-add-ia-c-provider-tests

This commit is contained in:
Andoni A.
2025-05-28 16:25:09 +02:00
8 changed files with 48 additions and 49 deletions
+2 -23
View File
@@ -612,20 +612,9 @@ class CheckReportM365(Check_Report):
class CheckReportIAC(Check_Report):
"""Contains the IAC Check's finding information using Checkov."""
metadata: dict
check_id: str
check_name: str
check_result: dict
check_result_status: str
file_path: str
file_line_range: list
guideline: str
resource: str
severity: str
# TODO: comparing with the others, are all the above are necesary? review
resource_name: str
resource_id: str
location: str
resource_path: str
resource_line_range: str
def __init__(self, metadata: dict = {}, finding: dict = {}) -> None:
"""
@@ -637,16 +626,6 @@ class CheckReportIAC(Check_Report):
"""
super().__init__(metadata, finding)
self.check_id = finding.get("check_id", "")
self.check_name = finding.get("check_name", "")
self.check_result = finding.get("check_result", {})
self.check_result_status = self.check_result.get("result", "UNKNOWN")
self.file_path = finding.get("file_path", "")
self.file_line_range = finding.get("file_line_range", [])
self.guideline = finding.get("guideline", "")
self.resource = finding
self.severity = finding.get("severity", "UNKNOWN")
# TODO: same question above
self.resource_name = getattr(finding, "resource", "")
self.resource_path = getattr(finding, "file_path", "")
self.resource_line_range = getattr(finding, "file_line_range", "")
+6 -6
View File
@@ -16,7 +16,7 @@ class AWSCISModel(BaseModel):
Requirements_Id: str
Requirements_Description: str
Requirements_Attributes_Section: str
Requirements_Attributes_SubSection: Optional[str]
Requirements_Attributes_SubSection: Optional[str] = None
Requirements_Attributes_Profile: str
Requirements_Attributes_AssessmentStatus: str
Requirements_Attributes_Description: str
@@ -50,7 +50,7 @@ class AzureCISModel(BaseModel):
Requirements_Id: str
Requirements_Description: str
Requirements_Attributes_Section: str
Requirements_Attributes_SubSection: Optional[str]
Requirements_Attributes_SubSection: Optional[str] = None
Requirements_Attributes_Profile: str
Requirements_Attributes_AssessmentStatus: str
Requirements_Attributes_Description: str
@@ -82,7 +82,7 @@ class M365CISModel(BaseModel):
Requirements_Id: str
Requirements_Description: str
Requirements_Attributes_Section: str
Requirements_Attributes_SubSection: Optional[str]
Requirements_Attributes_SubSection: Optional[str] = None
Requirements_Attributes_Profile: str
Requirements_Attributes_AssessmentStatus: str
Requirements_Attributes_Description: str
@@ -114,7 +114,7 @@ class GCPCISModel(BaseModel):
Requirements_Id: str
Requirements_Description: str
Requirements_Attributes_Section: str
Requirements_Attributes_SubSection: Optional[str]
Requirements_Attributes_SubSection: Optional[str] = None
Requirements_Attributes_Profile: str
Requirements_Attributes_AssessmentStatus: str
Requirements_Attributes_Description: str
@@ -145,8 +145,8 @@ class KubernetesCISModel(BaseModel):
Requirements_Id: str
Requirements_Description: str
Requirements_Attributes_Section: str
Requirements_Attributes_SubSection: Optional[str]
Requirements_Attributes_Profile: str
Requirements_Attributes_SubSection: Optional[str] = None
Requirements_Attributes_Profile: Optional[str] = None
Requirements_Attributes_AssessmentStatus: str
Requirements_Attributes_Description: str
Requirements_Attributes_RationaleStatement: str
+1 -2
View File
@@ -288,8 +288,7 @@ class Finding(BaseModel):
output_data["account_name"] = "iac"
output_data["resource_name"] = check_output.resource["resource"]
output_data["resource_uid"] = check_output.resource["resource"]
output_data["region"] = check_output.file_path
output_data["resource_path"] = check_output.resource_path
output_data["region"] = check_output.resource_path
output_data["resource_line_range"] = check_output.resource_line_range
output_data["framework"] = (
check_output.check_metadata.ServiceName
+3 -1
View File
@@ -1,3 +1,5 @@
from typing import Optional
from pydantic import BaseModel
from prowler.config.config import output_file_timestamp
@@ -15,7 +17,7 @@ class AzureIdentityInfo(BaseModel):
class AzureRegionConfig(BaseModel):
name: str = ""
authority: str = None
authority: Optional[str] = None
base_url: str = ""
credential_scopes: list = []
-1
View File
@@ -247,7 +247,6 @@ class Provider(ABC):
provider_class(
scan_path=arguments.scan_path,
config_path=arguments.config_file,
mutelist_path=arguments.mutelist_file,
fixer_config=fixer_config,
)
+1 -1
View File
@@ -14,7 +14,7 @@ class GCPOrganization(BaseModel):
id: str
name: str
# TODO: the name needs to be retrieved from another API
display_name: Optional[str]
display_name: Optional[str] = None
class GCPProject(BaseModel):
+34 -14
View File
@@ -5,6 +5,10 @@ from typing import List
from colorama import Fore, Style
from prowler.config.config import (
default_config_file_path,
load_and_validate_config_file,
)
from prowler.lib.check.models import CheckReportIAC
from prowler.lib.logger import logger
from prowler.lib.utils.utils import print_boxes
@@ -22,8 +26,6 @@ class IacProvider(Provider):
config_path: str = None,
config_content: dict = None,
fixer_config: dict = {},
mutelist_path: str = None,
mutelist_content: dict = None,
):
logger.info("Instantiating IAC Provider...")
@@ -33,8 +35,18 @@ class IacProvider(Provider):
self._session = None
self._identity = "prowler"
self._audit_config = config_content if config_content else {}
# Audit Config
if config_content:
self._audit_config = config_content
else:
if not config_path:
config_path = default_config_file_path
self._audit_config = load_and_validate_config_file(self._type, config_path)
# Fixer Config
self._fixer_config = fixer_config
# Mutelist (not needed for IAC since Checkov has its own mutelist logic)
self._mutelist = None
self.audit_metadata = Audit_Metadata(
@@ -86,22 +98,17 @@ class IacProvider(Provider):
Returns:
CheckReportIAC: The processed check report
"""
# Get severity and ensure it's a valid string
severity = finding.get("severity", "low")
if severity is None:
severity = "low"
severity = str(severity).lower()
# Create a basic metadata structure for the check
metadata_dict = {
"Provider": "iac",
"CheckID": check.get("check_id", ""),
"CheckTitle": check.get("check_name", ""),
"CheckType": ["Infrastructure as Code"],
"ServiceName": "iac",
"ServiceName": finding["check_type"],
"SubServiceName": "",
"ResourceIdTemplate": "",
"Severity": severity,
"Severity": (
check.get("severity", "low").lower() if check.get("severity") else "low"
),
"ResourceType": "iac",
"Description": check.get("check_name", ""),
"Risk": "",
@@ -126,7 +133,6 @@ class IacProvider(Provider):
"DependsOn": [],
"RelatedTo": [],
"Notes": "",
"GCPProject": check.get("project_id", ""),
}
# Convert metadata dict to JSON string
@@ -134,6 +140,10 @@ class IacProvider(Provider):
report = CheckReportIAC(metadata=metadata, finding=check)
report.status = status
report.resource_tags = check.get("entity_tags", {})
report.status_extended = check.get("check_name", "")
if status == "MUTED":
report.muted = True
return report
def run(self) -> List[CheckReportIAC]:
@@ -161,7 +171,11 @@ class IacProvider(Provider):
reports = []
# Process all findings
# If only one framework has findings, the output is a dict, otherwise it's a list of dicts
if isinstance(output, dict):
output = [output]
# Process all frameworks findings
for finding in output:
results = finding.get("results", {})
@@ -177,6 +191,12 @@ class IacProvider(Provider):
report = self._process_check(finding, passed_check, "PASS")
reports.append(report)
# Process skipped checks (muted)
skipped_checks = results.get("skipped_checks", [])
for skipped_check in skipped_checks:
report = self._process_check(finding, skipped_check, "MUTED")
reports.append(report)
return reports
except Exception as error:
@@ -171,7 +171,7 @@ class Pod(BaseModel):
host_ip: Optional[str]
host_pid: Optional[str]
host_ipc: Optional[str]
host_network: Optional[str]
host_network: Optional[bool]
security_context: Optional[dict]
containers: Optional[dict]