Skip to content

Commit

Permalink
Updating print report.
Browse files Browse the repository at this point in the history
  • Loading branch information
TreyE committed Sep 7, 2024
1 parent 6c3999b commit d60a216
Show file tree
Hide file tree
Showing 13 changed files with 412 additions and 165 deletions.
8 changes: 8 additions & 0 deletions assets/css/print_report.css
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
page-break-after: always;
}

.vulnerability-section {
page-break-inside: avoid;
}

html {
font-size: 11pt;
font-family: "Open Sans", sans-serif;
Expand All @@ -50,4 +54,8 @@ h2 {

h3 {
font-size: 1.17em;
}

.wrap {
white-space: pre-wrap;
}
5 changes: 4 additions & 1 deletion assets/frontend/pages/DeliverableVersions/ShowComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ export default function ShowComponent({ deliverable_version }) {
const deliverableSbomTags = deliverable_version.version_sboms.map((d) => {
return <tr key={d.id}>
<td><a href={d.version_sbom_url}>{d.name}</a></td>
<td><a href={d.analyzed_version_sbom_url}>Analyzed Version</a></td>
<td>
<a href={d.analyzed_version_sbom_url}>Analyzed Version</a>
<a href={d.vulnerability_report_download_url}>Mitigation Report</a>
</td>
</tr>
});

Expand Down
35 changes: 32 additions & 3 deletions lib/sectory/analysis/analysis_presenter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ defmodule Sectory.Analysis.AnalysisPresenter do
:analysis_timestamp,
:analyses,
:totals,
:all_issue_totals
:all_issue_totals,
:vulnerabilities,
:mitigations
]

def for_sbom_id(version_sbom_id) do
Expand All @@ -33,13 +35,20 @@ defmodule Sectory.Analysis.AnalysisPresenter do
|> Enum.group_by(fn {k, _v} -> elem(k, 0) end, fn {k, v} -> v end)
|> Enum.into(%{}, fn {k, v} -> {k, Enum.sum(v)} end)

mitigations = Enum.filter(vulns, fn(v) ->
v[:mitigation]
end)
|> Enum.map(fn(v) -> v.mitigation end)

%__MODULE__{
component_name: Sectory.Sbom.Component.main_component_name(analysis),
component_version: Sectory.Sbom.Component.main_component_version(analysis),
analysis_timestamp: analysis_timestamp(analysis),
analyses: analyses,
totals: totals,
all_issue_totals: all_issue_totals
all_issue_totals: all_issue_totals,
vulnerabilities: vulns,
mitigations: mitigations
}
end

Expand All @@ -52,13 +61,33 @@ defmodule Sectory.Analysis.AnalysisPresenter do
end

def format_vuln(v, component_map) do
components = lookup_components(v, component_map)
%{
id: v["id"],
description: Sectory.Sbom.Vulnerability.description(v),
detail: Sectory.Sbom.Vulnerability.detail(v),
components: components,
severity: Sectory.Sbom.Vulnerability.format_severity(v),
potential: Sectory.Sbom.Vulnerability.potential?(v)
potential: Sectory.Sbom.Vulnerability.potential?(v),
mitigation: extract_mitigation(v, components),
tools: Sectory.Sbom.Vulnerability.tools(v)
}
end

defp extract_mitigation(v, components) do
Sectory.Sbom.Vulnerability.extract_mitigation(v, components)
end

defp lookup_components(v, component_map) do
component_refs = Sectory.Sbom.Vulnerability.component_refs(v)
Enum.reduce(component_refs, [], fn(e, acc) ->
case Map.has_key?(component_map, e) do
false -> acc
_ -> [Map.fetch!(component_map, e)|acc]
end
end)
end

def component_lookup_map(sbom_data) do
Map.new(
sbom_data["components"],
Expand Down
20 changes: 10 additions & 10 deletions lib/sectory/analysis/analyzed_version_sbom.ex
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ defmodule Sectory.Analysis.AnalyzedVersionSbom do
false ->
Map.put(v, "properties", [
%{
name: "vuln-assign:analysis_severity",
value: analysis_record.vulnerability_analysis.adjusted_severity
"name" => "vuln-assign:analysis_severity",
"value" => analysis_record.vulnerability_analysis.adjusted_severity
}
])

Expand All @@ -107,8 +107,8 @@ defmodule Sectory.Analysis.AnalyzedVersionSbom do

[
%{
name: "vuln-assign:analysis_severity",
value: analysis_record.vulnerability_analysis.adjusted_severity
"name" => "vuln-assign:analysis_severity",
"value" => analysis_record.vulnerability_analysis.adjusted_severity
}
| clean_props
]
Expand All @@ -117,12 +117,12 @@ defmodule Sectory.Analysis.AnalyzedVersionSbom do

defp scope_to_sbom_analysis(vas) do
%{
state: vas.vulnerability_analysis.state,
justification: vas.vulnerability_analysis.justification,
response: vas.vulnerability_analysis.response,
detail: vas.vulnerability_analysis.detail,
firstIssued: vas.inserted_at,
lastUpdated: vas.updated_at
"state" => vas.vulnerability_analysis.state,
"justification" => vas.vulnerability_analysis.justification,
"response" => vas.vulnerability_analysis.response,
"detail" => vas.vulnerability_analysis.detail,
"firstIssued" => vas.inserted_at,
"lastUpdated" => vas.updated_at
}
end
end
157 changes: 156 additions & 1 deletion lib/sectory/sbom/vulnerability.ex
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,105 @@ defmodule Sectory.Sbom.Vulnerability do
end
end

def component_refs(v) do
vuln_component_ref_lens()
|> Lens.to_list(v)
end

def extract_mitigation(v, components) do
analysis = analysis_lens()
|> Lens.one!(v)
case analysis do
nil -> nil
_ ->
construct_mitigation_statement(v, analysis, components)
end
end

def tools(v) do
Lens.key?("tools")
|> Lens.key?("components")
|> Lens.all()
|> Lens.key?("name")
|> Lens.to_list(v)
end

def id(v) do
Lens.key?("id")
|> Lens.either(Lens.const(nil))
|> Lens.one!(v)
end

def detail(v) do
Lens.key?("detail")
|> Lens.either(
Lens.const(nil)
)
|> Lens.one!(v)
end

def description(v) do
case Map.has_key?(v, "description") do
false ->
case Map.has_key?(v, "detail") do
false -> "NO DESCRIPTION PROVIDED"
_ ->
Map.fetch!(v, "detail")
|> truncate(length: 80)
end
_ -> Map.fetch!(v, "description")
end
end

defp construct_mitigation_statement(v, analysis, components) do
original_severity = max_severity_from_ratings(v)
severity = format_severity(v)
vuln_properties = %{
id: id(v),
description: description(v),
severity: severity,
original_severity: original_severity,
components: components,
tools: tools(v)
}
Map.merge(
mitigation_properties_for(analysis),
vuln_properties
)
end

defp mitigation_properties_for(analysis) do
%{
state: analysis_state(analysis),
justification: analysis_justification(analysis),
detail: analysis_detail(analysis)
}
end

defp analysis_justification(analysis) do
Lens.key?("justification")
|> Lens.either(
Lens.const(nil)
)
|> Lens.one!(analysis)
end

defp analysis_detail(analysis) do
Lens.key?("detail")
|> Lens.either(
Lens.const(nil)
)
|> Lens.one!(analysis)
end

defp analysis_state(analysis) do
Lens.key?("state")
|> Lens.either(
Lens.const(nil)
)
|> Lens.one!(analysis)
end

defp has_non_triage_state(v) do
case Map.has_key?(v, "analysis") do
false -> false
Expand Down Expand Up @@ -86,7 +185,7 @@ defmodule Sectory.Sbom.Vulnerability do
Lens.key?("properties")
|> Lens.all()
|> Lens.filter(fn v when is_map(v) ->
v["name"] == "vuln-assign:analysis_severity"
(v["name"] == "vuln-assign:analysis_severity")
end)
|> Lens.key?("value")
end
Expand All @@ -99,4 +198,60 @@ defmodule Sectory.Sbom.Vulnerability do
end)
|> Lens.key?("severity")
end

Lens.Macros.deflensp vuln_component_ref_lens() do
Lens.key?("affects")
|> Lens.all()
|> Lens.key?("ref")
end

Lens.Macros.deflensp analysis_lens() do
Lens.key?("analysis")
|> Lens.either(Lens.const(nil))
end

def truncate(text, options \\ []) do
len = options[:length] || 30
omi = options[:omission] || "..."

cond do
!String.valid?(text) ->
text

String.length(text) < len ->
text

true ->
len_with_omi = len - String.length(omi)

stop =
if options[:separator] do
rindex(text, options[:separator], len_with_omi) || len_with_omi
else
len_with_omi
end

"#{String.slice(text, 0, stop)}#{omi}"
end
end

defp rindex(text, str, offset) do
text =
if offset do
String.slice(text, 0, offset)
else
text
end

revesed = text |> String.reverse()
matchword = String.reverse(str)

case :binary.match(revesed, matchword) do
{at, strlen} ->
String.length(text) - at - strlen

:nomatch ->
nil
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ defmodule SectoryWeb.DeliverableVersionController do
id: vs.id,
name: vs.name,
version_sbom_url: ~p"/version_sboms/#{vs.id}",
analyzed_version_sbom_url: ~p"/version_sboms/#{vs.id}/analyzed"
analyzed_version_sbom_url: ~p"/version_sboms/#{vs.id}/analyzed",
vulnerability_report_download_url: ~p"/sbom_vulnerability_reports/#{vs.id}"
}
end),
version_artifacts: Enum.map(record.version_artifacts, fn(va) ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ defmodule SectoryWeb.SbomVulnerabilityReportController do

result =
conn
|> put_resp_header("content-disposition", ~s(attachment; filename="report.pdf"))
|> put_resp_content_type("application/pdf")
|> put_resp_header("content-disposition", ~s(inline; filename="report.pdf"))
|> send_file(200, report_pdf_path)

Briefly.cleanup()
Expand Down Expand Up @@ -59,6 +60,8 @@ defmodule SectoryWeb.SbomVulnerabilityReportController do
"-s",
"A4",
"--disable-smart-shrinking",
"--footer-center",
"[page]",
"--allow",
Path.join(directory_path, "assets"),
"--allow",
Expand Down
12 changes: 12 additions & 0 deletions lib/sectory_web/controllers/sbom_vulnerability_report_html.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,16 @@ defmodule SectoryWeb.SbomVulnerabilityReportHTML do
use SectoryWeb, :html

embed_templates "sbom_vulnerability_report_html/*"

def critical_issues(analysis) do
Enum.filter(analysis.vulnerabilities, fn(v) ->
v.severity == "critical"
end)
end

def high_issues(analysis) do
Enum.filter(analysis.vulnerabilities, fn(v) ->
v.severity == "high"
end)
end
end
Loading

0 comments on commit d60a216

Please sign in to comment.