Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ae 829/streamline report #183

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
54d7d9a
Minor adjustments.
jfuegen-metaeffekt Nov 22, 2024
85b948a
Merge branch 'master' of github.com:org-metaeffekt/metaeffekt-core in…
jfuegen-metaeffekt Nov 22, 2024
b5bccb5
Implemented english language properties.
jfuegen-metaeffekt Dec 14, 2024
5383ba7
Merge branch 'master' of github.com:org-metaeffekt/metaeffekt-core in…
jfuegen-metaeffekt Dec 14, 2024
4ec06f0
Implemented german language support.
jfuegen-metaeffekt Dec 17, 2024
f553c3b
Further translations.
jfuegen-metaeffekt Dec 19, 2024
126ba2c
Further translations.
jfuegen-metaeffekt Dec 20, 2024
b61dfdf
Further translations.
jfuegen-metaeffekt Dec 20, 2024
3d2a58e
Further translations.
jfuegen-metaeffekt Jan 2, 2025
52b744b
Further translations.
jfuegen-metaeffekt Jan 3, 2025
2805cc4
Set test to ignore
jfuegen-metaeffekt Jan 3, 2025
38d9ae2
Fixed language properties.
jfuegen-metaeffekt Jan 3, 2025
0aeb206
feature: revised command execution with ExecUtils
karsten-klein Jan 5, 2025
de063b1
Merge remote-tracking branch 'origin/AE-829/Streamline-Report' into A…
karsten-klein Jan 5, 2025
3fe623c
Added AbstractModelBase attributes.
jfuegen-metaeffekt Jan 7, 2025
85cf04c
Merge remote-tracking branch 'origin/AE-829/Streamline-Report' into A…
jfuegen-metaeffekt Jan 7, 2025
185c223
Added AbstractModelBase attributes.
jfuegen-metaeffekt Jan 7, 2025
d621473
Merge remote-tracking branch 'origin/master' into AE-829/Streamline-R…
karsten-klein Jan 8, 2025
0ff96f3
chore: cleanup
karsten-klein Jan 8, 2025
fc1047a
chore: adding CLA and DCO
karsten-klein Jan 8, 2025
59c0379
Added AbstractModelBase attributes.
jfuegen-metaeffekt Jan 8, 2025
520b0b8
Merge remote-tracking branch 'origin/AE-829/Streamline-Report' into A…
jfuegen-metaeffekt Jan 8, 2025
3d20a0a
Merge branch 'master' of github.com:org-metaeffekt/metaeffekt-core in…
jfuegen-metaeffekt Jan 10, 2025
00bc351
chore: fixing ci build; diverting test setup
karsten-klein Jan 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -392,4 +392,31 @@ public static Set<Artifact> getArtifactsForAsset(Inventory inventory, AssetMetaD
return setOfArtifacts;
}

public static Map<AssetMetaData, Set<Artifact>> buildAssetToArtifactMap(Inventory filteredInventory) {
final Map<AssetMetaData, Set<Artifact>> assetMetaDataToArtifactsMap = new HashMap<>();

// the report only operates on the specified assets (these may be filtered for the use case)
for (AssetMetaData assetMetaData : filteredInventory.getAssetMetaData()) {

final String assetId = assetMetaData.get(AssetMetaData.Attribute.ASSET_ID);

if (!StringUtils.isNotBlank(assetId)) continue;

// derive licenses from artifacts
for (Artifact artifact : filteredInventory.getArtifacts()) {
// skip all artifacts that do not belong to an asset
if (StringUtils.isNotBlank(artifact.get(assetId))) {
assetMetaDataToArtifactsMap.computeIfAbsent(assetMetaData, c -> new HashSet<>()).add(artifact);
} else {
// check via asset id; if artifact id matches asset id; add
final String artifactAssetId = InventoryUtils.deriveAssetIdFromArtifact(artifact);
if (assetId.equals(artifactAssetId)) {
assetMetaDataToArtifactsMap.computeIfAbsent(assetMetaData, c -> new HashSet<>()).add(artifact);
}
}
}
}
return assetMetaDataToArtifactsMap;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public enum Attribute implements AbstractModelBase.Attribute {

// url of the project pages
URL("URL"),
SOURCE_CODE_URL("Source Code URL"),

// indicates whether the artifact is security relevant and needs to be upgraded asap
SECURITY_RELEVANT("Security Relevance"),
Expand All @@ -76,16 +77,22 @@ public enum Attribute implements AbstractModelBase.Attribute {
VERIFIED("Verified"),
ERRORS("Errors"),
HASH_SHA256("Hash (SHA-256)"),
HASH_SHA1("Hash (SHA1)"),
HASH_SHA512("Hash (SHA-512)"),
PATH_IN_ASSET("Path in Asset"),
VIRTUAL_ROOT_PATH("Virtual Root Path"),
PURL("PURL"),
COMPONENT_SOURCE_TYPE("Component Source Type"),

// FIXME: consolidate
SOURCE("Source"),
ORGANIZATION("Organization"),
SUPPLIER("Supplier"),

ARCHIVE("Archive"),
STRUCTURED("Structured"),
EXECUTABLE("Executable");


// FIXME: consolidate
ORGANIZATION("Organization");

private String key;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,15 @@ public enum Attribute implements AbstractModelBase.Attribute {
VERSION("Version"),
ASSESSMENT_ID("Assessment Id"),
ROLE("Role"),
ASSESSMENT("Assessment");
ASSESSMENT("Assessment"),
CHECKSUM("Checksum"),
HASH_SHA256("Hash (SHA-256)"),
HASH_SHA1("Hash (SHA1)"),
HASH_SHA512("Hash (SHA-512)"),
URL("URL"),
SOURCE_CODE_URL("Source Code URL"),
SUPPLIER("Supplier"),
TYPE("Type");

private String key;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,7 @@ protected boolean createReport(Inventory globalInventory, Inventory localInvento
// write reports
if (inventoryBomReportEnabled) {
writeReports(projectInventory, filteredInventory, inventoryReportAdapters,
deriveTemplateBaseDir(), TEMPLATE_GROUP_INVENTORY_REPORT_BOM, reportContext);
TEMPLATES_BASE_DIR, TEMPLATE_GROUP_INVENTORY_REPORT_BOM, reportContext);
}

if (inventoryDiffReportEnabled) {
Expand All @@ -593,23 +593,23 @@ protected boolean createReport(Inventory globalInventory, Inventory localInvento

if (inventoryVulnerabilityReportEnabled) {
writeReports(projectInventory, filteredInventory, inventoryReportAdapters,
deriveTemplateBaseDir(), TEMPLATE_GROUP_INVENTORY_REPORT_VULNERABILITY, reportContext);
TEMPLATES_BASE_DIR, TEMPLATE_GROUP_INVENTORY_REPORT_VULNERABILITY, reportContext);
}

if (inventoryVulnerabilityReportSummaryEnabled) {
writeReports(projectInventory, filteredInventory, inventoryReportAdapters,
deriveTemplateBaseDir(), TEMPLATE_GROUP_INVENTORY_REPORT_VULNERABILITY_SUMMARY, reportContext);
TEMPLATES_BASE_DIR, TEMPLATE_GROUP_INVENTORY_REPORT_VULNERABILITY_SUMMARY, reportContext);
}

if (inventoryVulnerabilityStatisticsReportEnabled) {
writeReports(projectInventory, filteredInventory, inventoryReportAdapters,
deriveTemplateBaseDir(), TEMPLATE_GROUP_INVENTORY_STATISTICS_VULNERABILITY, reportContext);
TEMPLATES_BASE_DIR, TEMPLATE_GROUP_INVENTORY_STATISTICS_VULNERABILITY, reportContext);
}

// all vulnerability-related templates require to generate labels
if (inventoryVulnerabilityReportEnabled || inventoryVulnerabilityStatisticsReportEnabled) {
writeReports(projectInventory, filteredInventory, inventoryReportAdapters,
deriveTemplateBaseDir(), TEMPLATE_GROUP_LABELS_VULNERABILITY_ASSESSMENT, reportContext);
TEMPLATES_BASE_DIR, TEMPLATE_GROUP_LABELS_VULNERABILITY_ASSESSMENT, reportContext);
}

if (inventoryPomEnabled) {
Expand All @@ -619,12 +619,12 @@ protected boolean createReport(Inventory globalInventory, Inventory localInvento

if (assetBomReportEnabled) {
writeReports(projectInventory, filteredInventory, inventoryReportAdapters,
deriveTemplateBaseDir(), TEMPLATE_GROUP_ASSET_REPORT_BOM, reportContext);
TEMPLATES_BASE_DIR, TEMPLATE_GROUP_ASSET_REPORT_BOM, reportContext);
}

if (assessmentReportEnabled) {
writeReports(projectInventory, filteredInventory, inventoryReportAdapters,
deriveTemplateBaseDir(), TEMPLATE_GROUP_ASSESSMENT_REPORT, reportContext);
TEMPLATES_BASE_DIR, TEMPLATE_GROUP_ASSESSMENT_REPORT, reportContext);
}

// evaluate licenses only for managed artifacts
Expand Down Expand Up @@ -707,10 +707,6 @@ private InventoryReportAdapters(AssetReportAdapter assetReportAdapter, Vulnerabi
}
}

private String deriveTemplateBaseDir() {
return TEMPLATES_BASE_DIR + SEPARATOR_SLASH + getTemplateLanguageSelector();
}

protected void writeReports(Inventory projectInventory, Inventory filteredInventory, InventoryReportAdapters report,
String templateBaseDir, String templateGroup, ReportContext reportContext) throws IOException {

Expand Down Expand Up @@ -749,6 +745,9 @@ private void produceDita(Inventory projectInventory, Inventory filteredInventory
final Template template = velocityEngine.getTemplate(templateResourcePath);
final StringWriter sw = new StringWriter();
final VelocityContext context = new VelocityContext();
final ReportUtils reportUtils = new ReportUtils();
reportUtils.setLang(templateLanguageSelector);
reportUtils.setContext(context);

// regarding the report we only use the filtered inventory for the time being
context.put("inventory", filteredInventory);
Expand All @@ -759,7 +758,7 @@ private void produceDita(Inventory projectInventory, Inventory filteredInventory
context.put("report", this);
context.put("StringEscapeUtils", org.apache.commons.lang.StringEscapeUtils.class);
context.put("RegExUtils", RegExUtils.class);
context.put("utils", new ReportUtils());
context.put("utils", reportUtils);

context.put("Double", Double.class);
context.put("Float", Float.class);
Expand Down Expand Up @@ -993,7 +992,7 @@ protected void writeDiffReport(Inventory referenceInventory, Inventory projectIn
new AssessmentReportAdapter(baseFilteredInventory, securityPolicy),
new InventoryReportAdapter(baseFilteredInventory));

writeReports(baseFilteredInventory, filteredInventory, inventoryReportAdapters, deriveTemplateBaseDir(), TEMPLATE_GROUP_INVENTORY_REPORT_DIFF, reportContext);
writeReports(baseFilteredInventory, filteredInventory, inventoryReportAdapters, TEMPLATES_BASE_DIR, TEMPLATE_GROUP_INVENTORY_REPORT_DIFF, reportContext);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,50 @@
*/
package org.metaeffekt.core.inventory.processor.report;

import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.xmlbeans.impl.schema.PathResourceLoader;
import org.metaeffekt.core.inventory.InventoryUtils;
import org.metaeffekt.core.inventory.processor.model.Artifact;
import org.metaeffekt.core.inventory.processor.model.AssetMetaData;
import org.metaeffekt.core.inventory.processor.model.Inventory;

import java.io.*;
import java.util.*;
import java.util.stream.Collectors;

public class ReportUtils {

@Setter
private VelocityContext context;

private Properties languageProperties;

/**
* It is recommended to use Locale.getLanguage().toString() as those abbreviations are used in the
* getLanguagePropertyFile() method and as the property file names.
*/
private String lang;

public void setLang(String lang) {
this.lang = lang;
Properties props = new Properties();
InputStream inputStream = this.getClass()
.getClassLoader()
.getResourceAsStream("META-INF/templates/lang/" + lang + ".properties");

try {
if (inputStream != null) {
props.load(inputStream);
languageProperties = props;
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}

public boolean isEmpty(String value) {
return !StringUtils.isNotBlank(value);
}
Expand Down Expand Up @@ -70,8 +103,26 @@ public Set<AssetMetaData> getAssetsForArtifacts(List<Artifact> artifacts, Invent
}
}

// return empty set

return Collections.emptySet();
}

public String getText(String key) {
String value = languageProperties.get(key).toString();
if (StringUtils.isNotBlank(value)) {
return evaluate(value);
}
return "";
}

// TODO: Manually evaluate how expensive this operation is compared to previous report iterations.
public String evaluate(String template) {
StringWriter writer = new StringWriter();
try {
Velocity.evaluate(context, writer, "TemplateEval", new StringReader(template));
} catch ( Exception e ) {
throw new RuntimeException(e);
}
return writer.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public class AssetData {
public static AssetData fromInventory(Inventory filteredInventory) {
AssetData assetData = new AssetData();

final Map<AssetMetaData, Set<Artifact>> assetMetaDataToArtifactsMap = assetData.buildAssetToArtifactMap(filteredInventory);
final Map<AssetMetaData, Set<Artifact>> assetMetaDataToArtifactsMap = InventoryUtils.buildAssetToArtifactMap(filteredInventory);

assetData.insertData(filteredInventory, assetMetaDataToArtifactsMap);

Expand Down Expand Up @@ -148,34 +148,6 @@ private String evaluateRepresentedAs(String associatedLicense, LicenseData licen
return representedAs;
}

private Map<AssetMetaData, Set<Artifact>> buildAssetToArtifactMap(Inventory filteredInventory) {
final Map<AssetMetaData, Set<Artifact>> assetMetaDataToArtifactsMap = new HashMap<>();

// the report only operates on the specified assets (these may be filtered for the use case)
for (AssetMetaData assetMetaData : filteredInventory.getAssetMetaData()) {

final String assetId = assetMetaData.get(AssetMetaData.Attribute.ASSET_ID);

if (!StringUtils.isNotBlank(assetId)) continue;

// derive licenses from artifacts
for (Artifact artifact : filteredInventory.getArtifacts()) {
// skip all artifacts that do not belong to an asset
final boolean containedInAsset = StringUtils.isNotBlank(artifact.get(assetId));
if (containedInAsset) {
assetMetaDataToArtifactsMap.computeIfAbsent(assetMetaData, c -> new HashSet<>()).add(artifact);
} else {
// check via asset id; if artifact id matches asset id; add
final String artifactAssetId = InventoryUtils.deriveAssetIdFromArtifact(artifact);
if (assetId.equals(artifactAssetId)) {
assetMetaDataToArtifactsMap.computeIfAbsent(assetMetaData, c -> new HashSet<>()).add(artifact);
}
}
}
}
return assetMetaDataToArtifactsMap;
}

private AssetLicenseData createAssetLicenseData(AssetMetaData assetMetaData, Set<String> assetAssociatedLicenses) {
final String assetId = assetMetaData.get(AssetMetaData.Attribute.ASSET_ID);
final String assetName = assetMetaData.getAlternatives("Name", "Machine Tag", "Repository", "Repo");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#set ($assetGroupDisplayName = $group.assetGroupDisplayName)
#set ($assetGroupAsXmlId = $group.assetGroupAsXmlId)
<table id="${id}-${assetGroupAsXmlId}">
<title>Asset Group <i>$assetGroupDisplayName</i></title>
<title>$utils.getText("general.short.asset-group") <i>$assetGroupDisplayName</i></title>
<tgroup cols="8">
<colspec colname="COLSPEC0" colnum="1" colwidth="27*"/>
<colspec colname="COLSPEC1" colnum="2" colwidth="11*"/>
Expand All @@ -26,14 +26,14 @@
<colspec colname="COLSPEC7" colnum="8" colwidth="9*"/>
<thead>
<row>
<entry colname="COLSPEC0" valign="middle"><p>Asset Name</p></entry>
<entry colname="COLSPEC0" valign="middle"><p>$utils.getText("general.short.asset-name")</p></entry>
<entry colname="COLSPEC1" valign="middle">#labelRef("Critical")</entry>
<entry colname="COLSPEC2" valign="middle">#labelRef("High")</entry>
<entry colname="COLSPEC3" valign="middle">#labelRef("Medium")</entry>
<entry colname="COLSPEC4" valign="middle">#labelRef("Low")</entry>
<entry colname="COLSPEC5" valign="middle">#labelRef("None")</entry>
<entry colname="COLSPEC6" valign="middle"><p>Total</p></entry>
<entry colname="COLSPEC7" valign="middle"><p>Assessed</p></entry>
<entry colname="COLSPEC6" valign="middle"><p>$utils.getText("general.short.total")</p></entry>
<entry colname="COLSPEC7" valign="middle"><p>$utils.getText("general.short.assessed")</p></entry>
</row>
</thead>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
## load macros from other files
#parse("META-INF/templates/labels-vulnerability-assessment/macros/labels.vm")
#parse("META-INF/templates/assessment-report/macros/assessment-report.vm")
##
## main template content
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE topic PUBLIC "-//OASIS//DTD DITA Topic//EN" "http://docs.oasis-open.org/dita/v1.1/OS/dtd/topic.dtd">
<topic id="tpc_asset-assessment-overview-modified-$reportContext.id">
<title>$reportContext.combinedTitle($utils.getText("assessment-report.short.effective-vuln-by-asset"), true)</title>
##
#set($assets = $assessmentReportAdapter.getAssets())

##

<body>
#if ($assets.isEmpty)
$utils.getText("general.assets-empty")
#else
<p>$utils.getText("assessment-report.vuln-table-descr")</p>
<p>$utils.getText("assessment-report.vuln-table-descr-modified")</p>
#assetAssessmentSummary("asset-assessment-summary-effective", $assets, true)
#end
</body>
</topic>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
## load macros from other files
#parse("META-INF/templates/labels-vulnerability-assessment/macros/labels.vm")
#parse("META-INF/templates/assessment-report/macros/assessment-report.vm")
##
## main template content
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE topic PUBLIC "-//OASIS//DTD DITA Topic//EN" "http://docs.oasis-open.org/dita/v1.1/OS/dtd/topic.dtd">
<topic id="tpc_asset-assessment-overview-$reportContext.id">
<title>$reportContext.combinedTitle($utils.getText("assessment-report.short.associated-vuln-by-asset"), true)</title>
##
#set($assets = $assessmentReportAdapter.getAssets())


##
<body>
#if ($assets.isEmpty)
$utils.getText("general.assets-empty")
#else
<p>$utils.getText("assessment-report.vuln-table-descr")</p>
<p>$utils.getText("assessment-report.vuln-table-descr-unmodified")</p>
#assetAssessmentSummary("asset-assessment-summary-associated", $assets, false)
#end
</body>
</topic>
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@
#macro(containedComponentsTable $artifacts)
#if ($artifacts.size() > 0)

<p>
Listed below are all components containing vulnerabilities which are associated with this asset.
</p>
<p>$utils.getText("asset-report-bom.contained-components-table")</p>

<table>
<tgroup cols="3">
Expand Down Expand Up @@ -45,6 +43,6 @@
</tgroup>
</table>
#else
There are no components contained in this asset.
$utils.getText("general.no-affected-components")
#end
#end
Loading
Loading