mirror of
https://github.com/ghndrx/prowler.git
synced 2026-02-10 14:55:00 +00:00
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:
@@ -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(
|
||||||
|
|||||||
@@ -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]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|||||||
8
prowler
8
prowler
@@ -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(
|
||||||
|
|||||||
Reference in New Issue
Block a user