Skip to content
Snippets Groups Projects
Commit 33156f7b authored by Alberto Pianon's avatar Alberto Pianon
Browse files

support for custom columns and anomalies


Signed-off-by: default avatarAlberto Pianon <alberto@pianon.eu>
parent e5e33154
No related branches found
No related tags found
1 merge request!84update a4f for compatibility with Donnie/Oniro4OpenHarmony
Pipeline #65902 failed
......@@ -26,7 +26,8 @@ from aliens4friends.models.harvest import (AuditFindings, BinaryPackage,
SessionState, SourcePackage,
Statistics, StatisticsLicenses,
Tool, aggregate_tags,
RecipeCveStatus, RecipeMaxCveScores)
RecipeCveStatus, RecipeMaxCveScores,
HAnomaly, Column, Header)
from aliens4friends.models.session import SessionPackageModel
from aliens4friends.models.tinfoilhat import PackageWithTags, TinfoilHatModel
......@@ -225,8 +226,27 @@ class Harvester:
self._warn_missing_input(source_package, cur_package_inputs)
self._set_aggregation_flag(cur_package_stats)
def _create_columns(self) -> List[Column]:
tag_names = Settings.A4F_TAG_SCHEMA.split("/")
columns = [
Column(
text=tag_name.capitalize(),
value=f"tags.{tag_name}",
type="implode_tag",
tooltip=tag_name.capitalize(),
override=str(i+5)
)
for i, tag_name in enumerate(tag_names)
]
if Settings.A4F_NO_CVES_IN_DASHBOARD:
columns.append(
Column("", False, "", "", "0")
)
return columns
def readfile(self):
self.result = HarvestModel(Tool(__name__, Settings.VERSION))
header = Header(self._create_columns())
self.result = HarvestModel(Tool(__name__, Settings.VERSION), header)
self._create_groups()
self._parse_groups()
if self.snapshot_release:
......@@ -459,7 +479,7 @@ class Harvester:
cur = cur._container
for _, container in cur.items():
if container.recipe.layer:
if container.recipe.layer and container.recipe.layer["layer_path"].startswith("/"):
l = os.path.realpath(container.recipe.layer["layer_path"])
container.recipe.layer["layer_path"] = "/".join(l.split("/")[4:]) # FIXME rule of thumb to get layer's relpath, this should be done in TinfoilHat instead
source_package.name = container.recipe.metadata.name
......@@ -467,6 +487,9 @@ class Harvester:
source_package.revision = container.recipe.metadata.revision
source_package.variant = container.recipe.metadata.variant
source_package.tags = aggregate_tags(container.tags)
source_package.anomalies = [
HAnomaly.from_Anomaly(anomaly)
for anomaly in container.anomalies.values()]
source_package.binary_packages = self._parse_tinfoilhat_packages(container.packages)
source_package.metadata = container.recipe.metadata
source_package.cve_metadata = container.recipe.cve_metadata
......
......@@ -112,6 +112,15 @@ class Settings:
# 'all' to import license findings and conclusions and copyright findings
# 'copyright' to import only copyright findings
try:
A4F_TAG_SCHEMA = DOTENV["A4F_TAG_SCHEMA"]
except KeyError:
A4F_TAG_SCHEMA = DOTENV["A4F_TAG_SCHEMA"] = "project/release/distro/machine/image"
try:
A4F_NO_CVES_IN_DASHBOARD = DOTENV["A4F_NO_CVES_IN_DASHBOARD"]
except KeyError:
A4F_NO_CVES_IN_DASHBOARD = DOTENV["A4F_NO_CVES_IN_DASHBOARD"] = False
# TODO write the session_id into the .env file, or use a current-link
# to the actual created or chosen session_id.json
......
......@@ -3,8 +3,9 @@
# SPDX-License-Identifier: Apache-2.0
from .base import BaseModel
from .tinfoilhat import RecipeCveMetaData, RecipeMetaData, BBLayer
from .tinfoilhat import RecipeCveMetaData, RecipeMetaData, BBLayer, Anomaly
from .common import License, Tool, SourceFile
from aliens4friends.commons.settings import Settings
from typing import Dict, List, Optional, Set, Union
class DebianMatchBasic(BaseModel):
......@@ -105,7 +106,7 @@ def aggregate_tags(tags: List[str]) -> Dict[str, Union[List[str], Set[str]]]:
if not tags:
return {}
keys = ['project', 'release', 'distro', 'machine', 'image']
keys = Settings.A4F_TAG_SCHEMA.split("/")
res = {key: set() for key in keys}
for i, key in enumerate(keys):
for elem in tags:
......@@ -115,13 +116,14 @@ def aggregate_tags(tags: List[str]) -> Dict[str, Union[List[str], Set[str]]]:
pass
for key in keys:
res[key] = sorted(res[key])
for key in [ 'distro', 'image' ]:
new = set()
for tag in res[key]:
for project in res['project']:
tag = tag.replace(f'{project}-', '')
new.add(tag)
res[key] = sorted(new)
if Settings.A4F_TAG_SCHEMA == "project/release/distro/machine/image":
for key in [ 'distro', 'image' ]:
new = set()
for tag in res[key]:
for project in res['project']:
tag = tag.replace(f'{project}-', '')
new.add(tag)
res[key] = sorted(new)
return res
......@@ -160,6 +162,37 @@ class RecipeMaxCveScores(BaseModel):
self.v2 = float(v2)
self.v3 = float(v3)
class HAnomaly(BaseModel):
def __init__(
self,
id: str,
severity: str,
type: str,
type_description: str,
comment: str,
source_package_id: str,
tags: List[str]
):
self.id = id
self.severity = severity
self.type = type
self.type_description = type_description
self.comment = comment
self.source_package_id = source_package_id
self.tags = aggregate_tags(tags)
@classmethod
def from_Anomaly(cls, anomaly: Anomaly) -> 'HAnomaly':
return cls(
anomaly.id,
anomaly.severity,
anomaly.type,
anomaly.type_description,
anomaly.comment,
anomaly.source_package_id,
anomaly.tags
)
class SourcePackage(BaseModel):
def __init__(
self,
......@@ -178,6 +211,7 @@ class SourcePackage(BaseModel):
isCve: Optional[bool] = False,
isUnpatched: Optional[bool] = False,
cveScoreSum: Optional[float] = None,
anomalies: Optional[List[HAnomaly]] = None,
statistics: Optional[Statistics] = None,
binary_packages: Optional[List[BinaryPackage]] = None,
tags: Optional[List[str]] = None,
......@@ -200,17 +234,42 @@ class SourcePackage(BaseModel):
self.isCve = isCve
self.isUnpatched = isUnpatched
self.cveScoreSum = cveScoreSum
self.anomalies = anomalies
self.binary_packages = BinaryPackage.drilldown(binary_packages)
self.tags = aggregate_tags(tags)
self.layer = layer
self.is_main_variant = is_main_variant
class Column(BaseModel):
def __init__(
self,
text: str,
value: str,
type: str,
tooltip: str,
override: str
):
self.text = text
self.value = value
self.type = type
self.tooltip = tooltip
self.override = override
class Header(BaseModel):
def __init__(
self,
columns: List[Column]
):
self.columns = columns
class HarvestModel(BaseModel):
def __init__(
self,
tool: Optional[Tool] = None,
tool: Optional[Tool],
header: Optional[Header] = None,
source_packages: Optional[List[SourcePackage]] = None
) -> None:
self.tool = Tool.decode(tool)
self.header = header
self.source_packages = SourcePackage.drilldown(source_packages)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment