fix(html): fix error html generator (#1530)

Co-authored-by: sergargar <sergio@verica.io>
Co-authored-by: Toni de la Fuente <toni@blyx.com>
This commit is contained in:
Sergio Garcia
2022-12-07 13:04:38 +01:00
committed by GitHub
parent df4b89366c
commit 7bffe6b2d5
3 changed files with 82 additions and 76 deletions

View File

@@ -140,25 +140,26 @@ def print_compliance_frameworks(
def print_compliance_requirements( def print_compliance_requirements(
bulk_compliance_frameworks: dict, compliance_framework: str bulk_compliance_frameworks: dict, compliance_frameworks: list
): ):
for compliance in bulk_compliance_frameworks.values(): for compliance_framework in compliance_frameworks:
# Workaround until we have more Compliance Frameworks for compliance in bulk_compliance_frameworks.values():
split_compliance = compliance_framework.split("_") # Workaround until we have more Compliance Frameworks
framework = split_compliance[0].upper() split_compliance = compliance_framework.split("_")
version = split_compliance[1].upper() framework = split_compliance[0].upper()
provider = split_compliance[2].upper() version = split_compliance[1].upper()
if compliance.Framework == framework and compliance.Version == version: provider = split_compliance[2].upper()
print( if framework in compliance.Framework and compliance.Version == version:
f"Listing {framework} {version} {provider} Compliance Requirements:\n"
)
for requirement in compliance.Requirements:
checks = ""
for check in requirement.Checks:
checks += f" {Fore.YELLOW}\t\t{check}\n{Style.RESET_ALL}"
print( print(
f"Requirement Id: {Fore.MAGENTA}{requirement.Id}{Style.RESET_ALL}\n\t- Description: {requirement.Description}\n\t- Checks:\n{checks}" f"Listing {framework} {version} {provider} Compliance Requirements:\n"
) )
for requirement in compliance.Requirements:
checks = ""
for check in requirement.Checks:
checks += f" {Fore.YELLOW}\t\t{check}\n{Style.RESET_ALL}"
print(
f"Requirement Id: {Fore.MAGENTA}{requirement.Id}{Style.RESET_ALL}\n\t- Description: {requirement.Description}\n\t- Checks:\n{checks}"
)
def print_checks( def print_checks(

View File

@@ -16,7 +16,6 @@ from config.config import (
json_asff_file_suffix, json_asff_file_suffix,
json_file_suffix, json_file_suffix,
orange_color, orange_color,
output_file_timestamp,
prowler_version, prowler_version,
timestamp, timestamp,
timestamp_iso, timestamp_iso,
@@ -304,7 +303,6 @@ def initialize_file_descriptor(
if output_mode in ("json", "json-asff"): if output_mode in ("json", "json-asff"):
file_descriptor.write("[") file_descriptor.write("[")
if "html" in output_mode: if "html" in output_mode:
add_html_header(file_descriptor, audit_info) add_html_header(file_descriptor, audit_info)
except Exception as error: except Exception as error:
@@ -463,34 +461,6 @@ def fill_json_asff(finding_output, audit_info, finding):
return finding_output return finding_output
def fill_html(file_descriptor, audit_info, finding):
row_class = "p-3 mb-2 bg-success-custom"
if finding.status == "INFO":
row_class = "table-info"
elif finding.status == "FAIL":
row_class = "table-danger"
elif finding.status == "WARNING":
row_class = "table-warning"
file_descriptor.write(
f"""
<tr class="{row_class}">
<td>{finding.status}</td>
<td>{finding.check_metadata.Severity}</td>
<td>{audit_info.audited_account}</td>
<td>{finding.region}</td>
<td>{finding.check_metadata.ServiceName}</td>
<td>{finding.check_metadata.CheckID}</td>
<td>{finding.check_metadata.CheckTitle}</td>
<td>{finding.status_extended}</td>
<td><p class="show-read-more">{finding.check_metadata.Risk}</p></td>
<td><p class="show-read-more">{finding.check_metadata.Remediation.Recommendation.Text}</p></td>
<td><a class="read-more" href="{finding.check_metadata.Remediation.Recommendation.Url}"><i class="fas fa-external-link-alt"></i></a></td>
<td>{finding.resource_id}</td>
</tr>
"""
)
def close_json(output_filename, output_directory, mode): def close_json(output_filename, output_directory, mode):
try: try:
suffix = json_file_suffix suffix = json_file_suffix
@@ -638,8 +608,10 @@ def display_summary_table(
print(f" - HTML: {output_directory}/{output_filename}.html") print(f" - HTML: {output_directory}/{output_filename}.html")
if "json-asff" in output_options.output_modes: if "json-asff" in output_options.output_modes:
print(f" - JSON-ASFF: {output_directory}/{output_filename}.asff.json") print(f" - JSON-ASFF: {output_directory}/{output_filename}.asff.json")
print(f" - CSV: {output_directory}/{output_filename}.csv") if "csv" in output_options.output_modes:
print(f" - JSON: {output_directory}/{output_filename}.json") print(f" - CSV: {output_directory}/{output_filename}.csv")
if "json" in output_options.output_modes:
print(f" - JSON: {output_directory}/{output_filename}.json")
else: else:
print( print(
@@ -887,8 +859,12 @@ def display_compliance_table(
def add_html_header(file_descriptor, audit_info): def add_html_header(file_descriptor, audit_info):
try: try:
if not audit_info.profile:
audit_info.profile = "ENV"
if isinstance(audit_info.audited_regions, list): if isinstance(audit_info.audited_regions, list):
audited_regions = " ".join(audit_info.audited_regions) audited_regions = " ".join(audit_info.audited_regions)
elif not audit_info.audited_regions:
audited_regions = "All Regions"
else: else:
audited_regions = audit_info.audited_regions audited_regions = audit_info.audited_regions
file_descriptor.write( file_descriptor.write(
@@ -901,7 +877,8 @@ def add_html_header(file_descriptor, audit_info):
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<style> <style>
.read-more {color:#00f;} .read-more {color:#00f;}
.bg-success-custom {background-color: #70dc88 !important;} .bg-success-custom {background-color: #98dea7 !important;}
.bg-danger {background-color: #f28484 !important;}
</style> </style>
<!-- Bootstrap CSS --> <!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous"> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
@@ -913,12 +890,9 @@ def add_html_header(file_descriptor, audit_info):
display: none; display: none;
} }
</style> </style>
<title>Prowler - AWS Security Assessments</title> <title>Prowler - The Handy Cloud Security Tool</title>
</head> </head>
<body> <body>
<nav class="navbar navbar-expand-xl sticky-top navbar-dark bg-dark">
<a class="navbar-brand" href="#">Prowler - Security Assessments in AWS</a>
</nav>
<div class="container-fluid"> <div class="container-fluid">
<div class="row mt-3"> <div class="row mt-3">
<div class="col-md-4"> <div class="col-md-4">
@@ -927,6 +901,14 @@ def add_html_header(file_descriptor, audit_info):
Report Information: Report Information:
</div> </div>
<ul class="list-group list-group-flush"> <ul class="list-group list-group-flush">
<li class="list-group-item text-center">
<a href="""
+ html_logo_url
+ """><img src="""
+ html_logo_img
+ """
alt="prowler-logo"></a>
</li>
<li class="list-group-item"> <li class="list-group-item">
<div class="row"> <div class="row">
<div class="col-md-auto"> <div class="col-md-auto">
@@ -943,17 +925,9 @@ def add_html_header(file_descriptor, audit_info):
</li> </li>
<li class="list-group-item"> <li class="list-group-item">
<b>Date:</b> """ <b>Date:</b> """
+ output_file_timestamp + timestamp.isoformat()
+ """ + """
</li> </li>
<li class="list-group-item text-center">
<a href="""
+ html_logo_url
+ """><img src="""
+ html_logo_img
+ """
alt="prowler-logo"></a>
</li>
</ul> </ul>
</div> </div>
</div> </div>
@@ -998,16 +972,16 @@ def add_html_header(file_descriptor, audit_info):
<tr> <tr>
<th scope="col">Status</th> <th scope="col">Status</th>
<th scope="col">Severity</th> <th scope="col">Severity</th>
<th scope="col">Account ID</th> <th scope="col">Service Name</th>
<th scope="col">Region</th> <th scope="col">Region</th>
<th scope="col">Service</th>
<th scope="col">Check ID</th>
<th style="width:20%" scope="col">Check Title</th> <th style="width:20%" scope="col">Check Title</th>
<th style="width:20%" scope="col">Check Output</th>
<th scope="col">Risk</th>
<th scope="col">Remediation</th>
<th scope="col">Related URL</th>
<th scope="col">Resource ID</th> <th scope="col">Resource ID</th>
<th scope="col">Check Description</th>
<th scope="col">Check ID</th>
<th scope="col">Status Extended</th>
<th scope="col">Risk</th>
<th scope="col">Recomendation</th>
<th style="5% width" scope="col">Recomendation URL</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@@ -1019,6 +993,34 @@ def add_html_header(file_descriptor, audit_info):
) )
def fill_html(file_descriptor, audit_info, finding):
row_class = "p-3 mb-2 bg-success-custom"
if finding.status == "INFO":
row_class = "table-info"
elif finding.status == "FAIL":
row_class = "table-danger"
elif finding.status == "WARNING":
row_class = "table-warning"
file_descriptor.write(
f"""
<tr class="{row_class}">
<td>{finding.status}</td>
<td>{finding.check_metadata.Severity}</td>
<td>{finding.check_metadata.ServiceName}</td>
<td>{finding.region}</td>
<td>{finding.check_metadata.CheckTitle}</td>
<td>{finding.resource_id}</td>
<td>{finding.check_metadata.Description}</td>
<td>{finding.check_metadata.CheckID}</td>
<td>{finding.status_extended}</td>
<td><p class="show-read-more">{finding.check_metadata.Risk}</p></td>
<td><p class="show-read-more">{finding.check_metadata.Remediation.Recommendation.Text}</p></td>
<td><a class="read-more" href="{finding.check_metadata.Remediation.Recommendation.Url}"><i class="fas fa-external-link-alt"></i></a></td>
</tr>
"""
)
def add_html_footer(output_filename, output_directory): def add_html_footer(output_filename, output_directory):
try: try:
filename = f"{output_directory}/{output_filename}{html_file_suffix}" filename = f"{output_directory}/{output_filename}{html_file_suffix}"
@@ -1045,6 +1047,8 @@ def add_html_footer(output_filename, output_directory):
$(document).ready(function(){ $(document).ready(function(){
// Initialise the table with 50 rows, and some search/filtering panes // Initialise the table with 50 rows, and some search/filtering panes
$('#findingsTable').DataTable( { $('#findingsTable').DataTable( {
lengthChange: true,
buttons: [ 'copy', 'excel', 'pdf' ],
lengthMenu: [ [50, 100, -1], [50, 100, "All"] ], lengthMenu: [ [50, 100, -1], [50, 100, "All"] ],
searchPanes: { searchPanes: {
cascadePanes: true, cascadePanes: true,
@@ -1054,10 +1058,11 @@ def add_html_footer(output_filename, output_directory):
columnDefs: [ columnDefs: [
{ {
searchPanes: { searchPanes: {
show: false show: true,
pagingType: 'numbers',
searching: true
}, },
// Hide Compliance, Check ID (in favour of Check Title), CAF Epic, Risk, Remediation, Link targets: [0, 1, 2, 3, 4]
targets: [4, 6, 9, 10, 11, 12]
} }
] ]
}); });

View File

@@ -102,9 +102,9 @@ if __name__ == "__main__":
) )
list_group.add_argument( list_group.add_argument(
"--list-compliance-requirements", "--list-compliance-requirements",
nargs="?", nargs="+",
help="List compliance requirements for a given requirement", help="List compliance requirements for a given requirement",
choices=["ens_rd2022_aws"], choices=["ens_rd2022_aws", "cis_1.4_aws", "cis_1.5_aws"],
) )
list_group.add_argument( list_group.add_argument(
"--list-categories", "--list-categories",
@@ -174,8 +174,8 @@ if __name__ == "__main__":
"-M", "-M",
"--output-modes", "--output-modes",
nargs="+", nargs="+",
help="Output mode, by default csv and json", help="Output modes, by default csv, html and json",
default=["csv", "json"], default=["csv", "json", "html"],
choices=["csv", "json", "json-asff", "html"], choices=["csv", "json", "json-asff", "html"],
) )
parser.add_argument( parser.add_argument(