mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-01-25 02:08:11 +00:00
fix(dashboard): Add multiple dashboard fixes (#3714)
This commit is contained in:
2
dashboard/assets/styles/dist/output.css
vendored
2
dashboard/assets/styles/dist/output.css
vendored
@@ -591,7 +591,7 @@ video {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 700;
|
||||
font-weight: 400;
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(41 37 36 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
@@ -6,6 +6,24 @@ fail_emoji = "❌"
|
||||
info_emoji = "ℹ️"
|
||||
manual_emoji = "✋🏽"
|
||||
|
||||
# Main colors
|
||||
fail_color = "#e67272"
|
||||
pass_color = "#54d283"
|
||||
info_color = "#2684FF"
|
||||
manual_color = "#636c78"
|
||||
|
||||
# Muted colors
|
||||
muted_fail_color = "#fca903"
|
||||
muted_pass_color = "#03fccf"
|
||||
muted_manual_color = "#b33696"
|
||||
|
||||
# Severity colors
|
||||
critical_color = "#951649"
|
||||
high_color = "#e11d48"
|
||||
medium_color = "#ee6f15"
|
||||
low_color = "#f9f5e6"
|
||||
informational_color = "#3274d9"
|
||||
|
||||
# Folder output path
|
||||
folder_path_overview = os.getcwd() + "/output"
|
||||
folder_path_compliance = os.getcwd() + "/output/compliance"
|
||||
|
||||
@@ -193,3 +193,97 @@ def create_compliance_dropdown(compliance: list) -> html.Div:
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def create_severity_dropdown(severity: list) -> html.Div:
|
||||
"""
|
||||
Dropdown to select the severity.
|
||||
Args:
|
||||
severity (list): List of severity.
|
||||
Returns:
|
||||
html.Div: Dropdown to select the severity.
|
||||
"""
|
||||
return html.Div(
|
||||
[
|
||||
html.Label(
|
||||
"Severity:", className="text-prowler-stone-900 font-bold text-sm"
|
||||
),
|
||||
dcc.Dropdown(
|
||||
id="severity-filter",
|
||||
options=[{"label": i, "value": i} for i in severity],
|
||||
value=["All"],
|
||||
clearable=False,
|
||||
multi=True,
|
||||
style={"color": "#000000"},
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def create_service_dropdown(services: list) -> html.Div:
|
||||
"""
|
||||
Dropdown to select the service.
|
||||
Args:
|
||||
services (list): List of services.
|
||||
Returns:
|
||||
html.Div: Dropdown to select the service.
|
||||
"""
|
||||
return html.Div(
|
||||
[
|
||||
html.Label(
|
||||
"Service:", className="text-prowler-stone-900 font-bold text-sm"
|
||||
),
|
||||
dcc.Dropdown(
|
||||
id="service-filter",
|
||||
options=[{"label": i, "value": i} for i in services],
|
||||
value=["All"],
|
||||
clearable=False,
|
||||
multi=True,
|
||||
style={"color": "#000000"},
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def create_status_dropdown(status: list) -> html.Div:
|
||||
"""
|
||||
Dropdown to select the status.
|
||||
Args:
|
||||
status (list): List of status.
|
||||
Returns:
|
||||
html.Div: Dropdown to select the status.
|
||||
"""
|
||||
return html.Div(
|
||||
[
|
||||
html.Label("Status:", className="text-prowler-stone-900 font-bold text-sm"),
|
||||
dcc.Dropdown(
|
||||
id="status-filter",
|
||||
options=[{"label": i, "value": i} for i in status],
|
||||
value=["All"],
|
||||
clearable=False,
|
||||
multi=True,
|
||||
style={"color": "#000000"},
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def create_table_row_dropdown(table_rows: list) -> html.Div:
|
||||
"""
|
||||
Dropdown to select the number of rows in the table.
|
||||
Args:
|
||||
table_rows (list): List of number of rows.
|
||||
Returns:
|
||||
html.Div: Dropdown to select the number of rows in the table.
|
||||
"""
|
||||
return html.Div(
|
||||
[
|
||||
dcc.Dropdown(
|
||||
id="table-rows",
|
||||
options=[{"label": i, "value": i} for i in table_rows],
|
||||
value=table_rows[0],
|
||||
clearable=False,
|
||||
style={"color": "#000000", "margin-right": "10px"},
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
@@ -6,6 +6,10 @@ def create_layout_overview(
|
||||
date_dropdown: html.Div,
|
||||
region_dropdown: html.Div,
|
||||
download_button: html.Button,
|
||||
severity_dropdown: html.Div,
|
||||
service_dropdown: html.Div,
|
||||
table_row_dropdown: html.Div,
|
||||
status_dropdown: html.Div,
|
||||
) -> html.Div:
|
||||
"""
|
||||
Create the layout of the dashboard.
|
||||
@@ -39,15 +43,23 @@ def create_layout_overview(
|
||||
),
|
||||
html.Div(
|
||||
[
|
||||
html.Div(className="flex", id="aws_card"),
|
||||
html.Div(className="flex", id="azure_card"),
|
||||
html.Div(className="flex", id="gcp_card"),
|
||||
html.Div(className="flex", id="k8s_card"),
|
||||
html.Div([severity_dropdown], className=""),
|
||||
html.Div([service_dropdown], className=""),
|
||||
html.Div([status_dropdown], className=""),
|
||||
],
|
||||
className="grid gap-x-4 gap-y-4 sm:grid-cols-2 lg:grid-cols-3 lg:gap-y-0",
|
||||
),
|
||||
html.Div(
|
||||
[
|
||||
html.Div(className="flex", id="aws_card", n_clicks=0),
|
||||
html.Div(className="flex", id="azure_card", n_clicks=0),
|
||||
html.Div(className="flex", id="gcp_card", n_clicks=0),
|
||||
html.Div(className="flex", id="k8s_card", n_clicks=0),
|
||||
],
|
||||
className="grid gap-x-4 gap-y-4 sm:grid-cols-2 lg:grid-cols-4 lg:gap-y-0",
|
||||
),
|
||||
html.H4(
|
||||
"Count of Failed Findings by severity",
|
||||
"Count of Findings by severity",
|
||||
className="text-prowler-stone-900 text-lg font-bold",
|
||||
),
|
||||
html.Div(
|
||||
@@ -70,10 +82,23 @@ def create_layout_overview(
|
||||
html.Div(
|
||||
[
|
||||
html.H4(
|
||||
"Top 25 Failed Findings by Severity",
|
||||
"Top Findings by Severity",
|
||||
className="text-prowler-stone-900 text-lg font-bold",
|
||||
),
|
||||
download_button,
|
||||
html.Div(
|
||||
[
|
||||
(
|
||||
html.Label(
|
||||
"Table Rows:",
|
||||
className="text-prowler-stone-900 font-bold text-sm",
|
||||
style={"margin-right": "10px"},
|
||||
)
|
||||
),
|
||||
table_row_dropdown,
|
||||
download_button,
|
||||
],
|
||||
className="flex justify-between items-center",
|
||||
),
|
||||
dcc.Download(id="download-data"),
|
||||
],
|
||||
className="flex justify-between items-center",
|
||||
|
||||
@@ -14,7 +14,13 @@ from dash import callback, dcc, html
|
||||
from dash.dependencies import Input, Output
|
||||
|
||||
# Config import
|
||||
from dashboard.config import folder_path_compliance
|
||||
from dashboard.config import (
|
||||
fail_color,
|
||||
folder_path_compliance,
|
||||
info_color,
|
||||
manual_color,
|
||||
pass_color,
|
||||
)
|
||||
from dashboard.lib.dropdowns import (
|
||||
create_account_dropdown_compliance,
|
||||
create_compliance_dropdown,
|
||||
@@ -505,7 +511,7 @@ def get_bar_graph(df, column_name):
|
||||
x="counts",
|
||||
y=colums,
|
||||
color="STATUS",
|
||||
color_discrete_map={"FAIL": "#e67272"},
|
||||
color_discrete_map={"FAIL": fail_color},
|
||||
orientation="h",
|
||||
)
|
||||
|
||||
@@ -530,11 +536,11 @@ def get_bar_graph(df, column_name):
|
||||
def get_pie(df):
|
||||
# Define custom colors
|
||||
color_mapping = {
|
||||
"FAIL": "#e67272",
|
||||
"PASS": "#54d283",
|
||||
"INFO": "#2684FF",
|
||||
"FAIL": fail_color,
|
||||
"PASS": pass_color,
|
||||
"INFO": info_color,
|
||||
"WARN": "#260000",
|
||||
"MANUAL": "#636c78",
|
||||
"MANUAL": manual_color,
|
||||
}
|
||||
|
||||
# Use the color_discrete_map parameter to map categories to custom colors
|
||||
|
||||
@@ -16,12 +16,30 @@ from dash import callback, ctx, dcc, html
|
||||
from dash.dependencies import Input, Output
|
||||
|
||||
# Config import
|
||||
from dashboard.config import folder_path_overview
|
||||
from dashboard.config import (
|
||||
critical_color,
|
||||
fail_color,
|
||||
folder_path_overview,
|
||||
high_color,
|
||||
info_color,
|
||||
informational_color,
|
||||
low_color,
|
||||
manual_color,
|
||||
medium_color,
|
||||
muted_fail_color,
|
||||
muted_manual_color,
|
||||
muted_pass_color,
|
||||
pass_color,
|
||||
)
|
||||
from dashboard.lib.cards import create_provider_card
|
||||
from dashboard.lib.dropdowns import (
|
||||
create_account_dropdown,
|
||||
create_date_dropdown,
|
||||
create_region_dropdown,
|
||||
create_service_dropdown,
|
||||
create_severity_dropdown,
|
||||
create_status_dropdown,
|
||||
create_table_row_dropdown,
|
||||
)
|
||||
from dashboard.lib.layouts import create_layout_overview
|
||||
|
||||
@@ -221,6 +239,33 @@ else:
|
||||
regions = options
|
||||
region_dropdown = create_region_dropdown(regions)
|
||||
|
||||
# Severity Dropdown
|
||||
severity = ["All"] + list(data["SEVERITY"].unique())
|
||||
severity = [
|
||||
x for x in severity if str(x) != "nan" and x.__class__.__name__ == "str"
|
||||
]
|
||||
|
||||
severity_dropdown = create_severity_dropdown(severity)
|
||||
|
||||
# Service Dropdown
|
||||
services = []
|
||||
for service in data["SERVICE_NAME"].unique():
|
||||
if "aws" in list(data[data["SERVICE_NAME"] == service]["PROVIDER"]):
|
||||
services.append(service + " - AWS")
|
||||
if "kubernetes" in list(data[data["SERVICE_NAME"] == service]["PROVIDER"]):
|
||||
services.append(service + " - K8S")
|
||||
if "azure" in list(data[data["SERVICE_NAME"] == service]["PROVIDER"]):
|
||||
services.append(service + " - AZURE")
|
||||
if "gcp" in list(data[data["SERVICE_NAME"] == service]["PROVIDER"]):
|
||||
services.append(service + " - GCP")
|
||||
|
||||
services = ["All"] + services
|
||||
services = [
|
||||
x for x in services if str(x) != "nan" and x.__class__.__name__ == "str"
|
||||
]
|
||||
|
||||
service_dropdown = create_service_dropdown(services)
|
||||
|
||||
# Create the download button
|
||||
download_button = html.Button(
|
||||
"Download this table as CSV",
|
||||
@@ -229,12 +274,29 @@ else:
|
||||
className="border-solid border-2 border-prowler-stone-900/10 hover:border-solid hover:border-2 hover:border-prowler-stone-900/10 text-prowler-stone-900 inline-block px-4 py-2 text-xs font-bold uppercase transition-all rounded-lg text-gray-900 hover:bg-prowler-stone-900/10 flex justify-end w-fit",
|
||||
)
|
||||
|
||||
# Create the table row dropdown
|
||||
table_row_values = [-1]
|
||||
table_row_dropdown = create_table_row_dropdown(table_row_values)
|
||||
|
||||
# Create the status dropdown
|
||||
status = ["All"] + list(data["STATUS"].unique())
|
||||
status = [x for x in status if str(x) != "nan" and x.__class__.__name__ == "str"]
|
||||
|
||||
status_dropdown = create_status_dropdown(status)
|
||||
|
||||
# Initializing the Dash App
|
||||
dash.register_page(__name__, path="/")
|
||||
|
||||
# Create the layout
|
||||
layout = create_layout_overview(
|
||||
account_dropdown, date_dropdown, region_dropdown, download_button
|
||||
account_dropdown,
|
||||
date_dropdown,
|
||||
region_dropdown,
|
||||
download_button,
|
||||
severity_dropdown,
|
||||
service_dropdown,
|
||||
table_row_dropdown,
|
||||
status_dropdown,
|
||||
)
|
||||
|
||||
|
||||
@@ -257,19 +319,80 @@ else:
|
||||
Output("k8s_card", "children"),
|
||||
Output("subscribe_card", "children"),
|
||||
Output("info-file-over", "title"),
|
||||
Output("severity-filter", "value"),
|
||||
Output("severity-filter", "options"),
|
||||
Output("service-filter", "value"),
|
||||
Output("service-filter", "options"),
|
||||
Output("table-rows", "value"),
|
||||
Output("table-rows", "options"),
|
||||
Output("status-filter", "value"),
|
||||
Output("status-filter", "options"),
|
||||
Output("aws_card", "n_clicks"),
|
||||
Output("azure_card", "n_clicks"),
|
||||
Output("gcp_card", "n_clicks"),
|
||||
Output("k8s_card", "n_clicks"),
|
||||
],
|
||||
Input("cloud-account-filter", "value"),
|
||||
Input("region-filter", "value"),
|
||||
Input("report-date-filter", "value"),
|
||||
Input("download_link", "n_clicks"),
|
||||
Input("severity-filter", "value"),
|
||||
Input("service-filter", "value"),
|
||||
Input("table-rows", "value"),
|
||||
Input("status-filter", "value"),
|
||||
Input("aws_card", "n_clicks"),
|
||||
Input("azure_card", "n_clicks"),
|
||||
Input("gcp_card", "n_clicks"),
|
||||
Input("k8s_card", "n_clicks"),
|
||||
)
|
||||
def filter_data(
|
||||
cloud_account_values, region_account_values, assessment_value, n_clicks
|
||||
cloud_account_values,
|
||||
region_account_values,
|
||||
assessment_value,
|
||||
n_clicks,
|
||||
severity_values,
|
||||
service_values,
|
||||
table_row_values,
|
||||
status_values,
|
||||
aws_clicks,
|
||||
azure_clicks,
|
||||
gcp_clicks,
|
||||
k8s_clicks,
|
||||
):
|
||||
# Use n_clicks for vulture
|
||||
n_clicks = n_clicks
|
||||
# Filter the data
|
||||
filtered_data = data.copy()
|
||||
|
||||
if aws_clicks > 0:
|
||||
filtered_data = data.copy()
|
||||
if aws_clicks % 2 != 0 and "aws" in list(data["PROVIDER"]):
|
||||
filtered_data = filtered_data[filtered_data["PROVIDER"] == "aws"]
|
||||
azure_clicks = 0
|
||||
gcp_clicks = 0
|
||||
k8s_clicks = 0
|
||||
if azure_clicks > 0:
|
||||
filtered_data = data.copy()
|
||||
if azure_clicks % 2 != 0 and "azure" in list(data["PROVIDER"]):
|
||||
filtered_data = filtered_data[filtered_data["PROVIDER"] == "azure"]
|
||||
aws_clicks = 0
|
||||
gcp_clicks = 0
|
||||
k8s_clicks = 0
|
||||
if gcp_clicks > 0:
|
||||
filtered_data = data.copy()
|
||||
if gcp_clicks % 2 != 0 and "gcp" in list(data["PROVIDER"]):
|
||||
filtered_data = filtered_data[filtered_data["PROVIDER"] == "gcp"]
|
||||
aws_clicks = 0
|
||||
azure_clicks = 0
|
||||
k8s_clicks = 0
|
||||
if k8s_clicks > 0:
|
||||
filtered_data = data.copy()
|
||||
if k8s_clicks % 2 != 0 and "kubernetes" in list(data["PROVIDER"]):
|
||||
filtered_data = filtered_data[filtered_data["PROVIDER"] == "kubernetes"]
|
||||
aws_clicks = 0
|
||||
azure_clicks = 0
|
||||
gcp_clicks = 0
|
||||
|
||||
# For all the data, we will add to the status column the value 'MUTED (FAIL)' and 'MUTED (PASS)' depending on the value of the column 'STATUS' and 'MUTED'
|
||||
if "MUTED" in filtered_data.columns:
|
||||
filtered_data["STATUS"] = filtered_data.apply(
|
||||
@@ -422,7 +545,6 @@ def filter_data(
|
||||
elif "ACCOUNT_NAME" in filtered_data.columns:
|
||||
filtered_data = filtered_data[filtered_data["ACCOUNT_NAME"].isin(values_choice)]
|
||||
|
||||
copy_data = filtered_data.copy()
|
||||
# Filter REGION
|
||||
|
||||
# Check if filtered data contains an aws account
|
||||
@@ -446,7 +568,7 @@ def filter_data(
|
||||
filtered_data["REGION"].isin(updated_region_account_values)
|
||||
]
|
||||
|
||||
region_filter_options = ["All"] + list(copy_data["REGION"].unique())
|
||||
region_filter_options = ["All"] + list(filtered_data["REGION"].unique())
|
||||
# clean the region_filter_options from null values
|
||||
region_filter_options = [
|
||||
x
|
||||
@@ -463,10 +585,84 @@ def filter_data(
|
||||
|
||||
region_filter_options = options
|
||||
|
||||
# Select failed findings
|
||||
fails_findings_default = filtered_data[filtered_data["STATUS"] == "FAIL"]
|
||||
fails_findings_muted = filtered_data[filtered_data["STATUS"] == "MUTED (FAIL)"]
|
||||
fails_findings = pd.concat([fails_findings_default, fails_findings_muted])
|
||||
# Filter Severity
|
||||
if severity_values == ["All"]:
|
||||
updated_severity_values = filtered_data["SEVERITY"].unique()
|
||||
elif "All" in severity_values and len(severity_values) > 1:
|
||||
# Remove 'All' from the list
|
||||
severity_values.remove("All")
|
||||
updated_severity_values = severity_values
|
||||
elif len(severity_values) == 0:
|
||||
updated_severity_values = filtered_data["SEVERITY"].unique()
|
||||
severity_values = ["All"]
|
||||
else:
|
||||
updated_severity_values = severity_values
|
||||
|
||||
filtered_data = filtered_data[
|
||||
filtered_data["SEVERITY"].isin(updated_severity_values)
|
||||
]
|
||||
|
||||
severity_filter_options = ["All"] + list(filtered_data["SEVERITY"].unique())
|
||||
|
||||
service_filter_options = ["All"]
|
||||
|
||||
all_items = filtered_data["SERVICE_NAME"].unique()
|
||||
for item in all_items:
|
||||
if item not in service_filter_options and item.__class__.__name__ == "str":
|
||||
if "aws" in list(
|
||||
filtered_data[filtered_data["SERVICE_NAME"] == item]["PROVIDER"]
|
||||
):
|
||||
service_filter_options.append(item + " - AWS")
|
||||
if "kubernetes" in list(
|
||||
filtered_data[filtered_data["SERVICE_NAME"] == item]["PROVIDER"]
|
||||
):
|
||||
service_filter_options.append(item + " - K8S")
|
||||
if "azure" in list(
|
||||
filtered_data[filtered_data["SERVICE_NAME"] == item]["PROVIDER"]
|
||||
):
|
||||
service_filter_options.append(item + " - AZURE")
|
||||
if "gcp" in list(
|
||||
filtered_data[filtered_data["SERVICE_NAME"] == item]["PROVIDER"]
|
||||
):
|
||||
service_filter_options.append(item + " - GCP")
|
||||
|
||||
# Filter Service
|
||||
if service_values == ["All"]:
|
||||
updated_service_values = filtered_data["SERVICE_NAME"].unique()
|
||||
elif "All" in service_values and len(service_values) > 1:
|
||||
# Remove 'All' from the list
|
||||
updated_service_values = []
|
||||
service_values.remove("All")
|
||||
for item in service_values:
|
||||
updated_service_values.append(item.split(" - ")[0])
|
||||
elif len(service_values) == 0:
|
||||
updated_service_values = filtered_data["SERVICE_NAME"].unique()
|
||||
service_values = ["All"]
|
||||
else:
|
||||
updated_service_values = []
|
||||
for item in service_values:
|
||||
updated_service_values.append(item.split(" - ")[0])
|
||||
|
||||
filtered_data = filtered_data[
|
||||
filtered_data["SERVICE_NAME"].isin(updated_service_values)
|
||||
]
|
||||
|
||||
# Filter Status
|
||||
if status_values == ["All"]:
|
||||
updated_status_values = filtered_data["STATUS"].unique()
|
||||
elif "All" in status_values and len(status_values) > 1:
|
||||
# Remove 'All' from the list
|
||||
status_values.remove("All")
|
||||
updated_status_values = status_values
|
||||
elif len(status_values) == 0:
|
||||
updated_status_values = filtered_data["STATUS"].unique()
|
||||
status_values = ["All"]
|
||||
else:
|
||||
updated_status_values = status_values
|
||||
|
||||
filtered_data = filtered_data[filtered_data["STATUS"].isin(updated_status_values)]
|
||||
|
||||
status_filter_options = ["All"] + list(filtered_data["STATUS"].unique())
|
||||
|
||||
if len(filtered_data_sp) == 0:
|
||||
fig = px.pie()
|
||||
@@ -521,13 +717,13 @@ def filter_data(
|
||||
result_df["Status_count"].fillna(0, inplace=True)
|
||||
|
||||
color_mapping = {
|
||||
"FAIL": "#e67272",
|
||||
"PASS": "#54d283",
|
||||
"INFO": "#2684FF",
|
||||
"MANUAL": "#636c78",
|
||||
"MUTED (FAIL)": "#fca903",
|
||||
"MUTED (PASS)": "#03fccf",
|
||||
"MUTED (MANUAL)": "#b33696",
|
||||
"FAIL": fail_color,
|
||||
"PASS": pass_color,
|
||||
"INFO": info_color,
|
||||
"MANUAL": manual_color,
|
||||
"MUTED (FAIL)": muted_fail_color,
|
||||
"MUTED (PASS)": muted_pass_color,
|
||||
"MUTED (MANUAL)": muted_manual_color,
|
||||
}
|
||||
|
||||
# Create a single line plot for both 'FAIL' and 'PASS' statuses
|
||||
@@ -576,23 +772,23 @@ def filter_data(
|
||||
df1 = filtered_data[filtered_data["STATUS"] == "FAIL"]
|
||||
|
||||
color_mapping_pass_fail = {
|
||||
"FAIL": "#e67272",
|
||||
"PASS": "#54d283",
|
||||
"INFO": "#2684FF",
|
||||
"MANUAL": "#636c78",
|
||||
"WARNING": "#fca903",
|
||||
"MUTED (FAIL)": "#fca903",
|
||||
"MUTED (PASS)": "#03fccf",
|
||||
"FAIL": fail_color,
|
||||
"PASS": pass_color,
|
||||
"INFO": info_color,
|
||||
"MANUAL": manual_color,
|
||||
"WARNING": muted_fail_color,
|
||||
"MUTED (FAIL)": muted_fail_color,
|
||||
"MUTED (PASS)": muted_pass_color,
|
||||
"MUTED (MANUAL)": "#b33696",
|
||||
"MUTED (WARNING)": "#c7a45d",
|
||||
}
|
||||
# Define custom colors
|
||||
color_mapping = {
|
||||
"critical": "#951649",
|
||||
"high": "#e11d48",
|
||||
"medium": "#ee6f15",
|
||||
"low": "#f9f5e6",
|
||||
"informational": "#3274d9",
|
||||
"critical": critical_color,
|
||||
"high": high_color,
|
||||
"medium": medium_color,
|
||||
"low": low_color,
|
||||
"informational": informational_color,
|
||||
}
|
||||
|
||||
# Use the color_discrete_map parameter to map categories to custom colors
|
||||
@@ -661,12 +857,13 @@ def filter_data(
|
||||
"low": 1,
|
||||
"informational": 0,
|
||||
}
|
||||
fails_findings["SEVERITY"] = fails_findings["SEVERITY"].map(severity_dict)
|
||||
fails_findings = fails_findings.sort_values(by=["SEVERITY"], ascending=False)
|
||||
fails_findings["SEVERITY"] = fails_findings["SEVERITY"].replace(
|
||||
|
||||
filtered_data["SEVERITY"] = filtered_data["SEVERITY"].map(severity_dict)
|
||||
filtered_data = filtered_data.sort_values(by=["SEVERITY"], ascending=False)
|
||||
filtered_data["SEVERITY"] = filtered_data["SEVERITY"].replace(
|
||||
{4: "critical", 3: "high", 2: "medium", 1: "low", 0: "informational"}
|
||||
)
|
||||
table_data = fails_findings.copy()
|
||||
table_data = filtered_data.copy()
|
||||
|
||||
if "ACCOUNT_NAME" in table_data.columns:
|
||||
for subscription in table_data["ACCOUNT_NAME"].unique():
|
||||
@@ -704,15 +901,38 @@ def filter_data(
|
||||
}
|
||||
)
|
||||
|
||||
if len(table_data) > 25:
|
||||
table_row_options = []
|
||||
|
||||
# Take the values from the table_row_values
|
||||
if table_row_values == -1:
|
||||
if len(table_data) >= 25:
|
||||
table_row_values = 25
|
||||
else:
|
||||
table_row_values = "Full"
|
||||
|
||||
if len(table_data) < 25:
|
||||
table_row_values = "Full"
|
||||
|
||||
if len(table_data) >= 25:
|
||||
table_row_options.append(25)
|
||||
if len(table_data) >= 50:
|
||||
table_row_options.append(50)
|
||||
if len(table_data) >= 75:
|
||||
table_row_options.append(75)
|
||||
if len(table_data) >= 100:
|
||||
table_row_options.append(100)
|
||||
table_row_options.append("Full")
|
||||
|
||||
if table_row_values == "Full":
|
||||
table = dbc.Table.from_dataframe(
|
||||
table_data[:25],
|
||||
table_data,
|
||||
striped=True,
|
||||
bordered=False,
|
||||
hover=True,
|
||||
className="table-overview",
|
||||
)
|
||||
else:
|
||||
table_data = table_data[:table_row_values]
|
||||
table = dbc.Table.from_dataframe(
|
||||
table_data,
|
||||
striped=True,
|
||||
@@ -788,7 +1008,9 @@ def filter_data(
|
||||
)
|
||||
]
|
||||
if ctx.triggered_id == "download_link":
|
||||
csv_data = dcc.send_data_frame(table_data[:25].to_csv, "mydf.csv")
|
||||
csv_data = dcc.send_data_frame(
|
||||
table_data.to_csv, "prowler-dashboard-export.csv"
|
||||
)
|
||||
return (
|
||||
status_graph,
|
||||
two_pie_chart,
|
||||
@@ -806,6 +1028,18 @@ def filter_data(
|
||||
k8s_card,
|
||||
subscribe_card,
|
||||
list_files,
|
||||
severity_values,
|
||||
severity_filter_options,
|
||||
service_values,
|
||||
service_filter_options,
|
||||
table_row_values,
|
||||
table_row_options,
|
||||
status_values,
|
||||
status_filter_options,
|
||||
aws_clicks,
|
||||
azure_clicks,
|
||||
gcp_clicks,
|
||||
k8s_clicks,
|
||||
)
|
||||
else:
|
||||
return (
|
||||
@@ -825,4 +1059,16 @@ def filter_data(
|
||||
k8s_card,
|
||||
subscribe_card,
|
||||
list_files,
|
||||
severity_values,
|
||||
severity_filter_options,
|
||||
service_values,
|
||||
service_filter_options,
|
||||
table_row_values,
|
||||
table_row_options,
|
||||
status_values,
|
||||
status_filter_options,
|
||||
aws_clicks,
|
||||
azure_clicks,
|
||||
gcp_clicks,
|
||||
k8s_clicks,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user