Skip to content

Commit

Permalink
Allow for measuring the source up-to-dateness of Harbor JSON reports.
Browse files Browse the repository at this point in the history
Closes #10609.
  • Loading branch information
fniessink committed Jan 13, 2025
1 parent 88f6eb0 commit d70922d
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 58 deletions.
5 changes: 3 additions & 2 deletions components/collector/.vulture_ignore_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@
GitLabUnusedJobs # unused class (src/source_collectors/gitlab/unused_jobs.py:11)
scan_status # unused variable (src/source_collectors/harbor/security_warnings.py:58)
HarborSecurityWarnings # unused class (src/source_collectors/harbor/security_warnings.py:62)
HarborJSONSecurityWarnings # unused class (src/source_collectors/harbor_json/security_warnings.py:36)
generated_at # unused variable (src/source_collectors/harbor_json/base.py:23)
HarborJSONSecurityWarnings # unused class (src/source_collectors/harbor_json/security_warnings.py:12)
HarborJSONSourceUpToDateness # unused class (src/source_collectors/harbor_json/source_up_to_dateness.py:13)
JacocoSourceUpToDateness # unused class (src/source_collectors/jacoco/source_up_to_dateness.py:11)
JacocoUncoveredBranches # unused class (src/source_collectors/jacoco/uncovered_branches.py:6)
JacocoUncoveredLines # unused class (src/source_collectors/jacoco/uncovered_lines.py:6)
Expand Down Expand Up @@ -173,4 +175,3 @@
pageInfo # unused variable (tests/source_collectors/github/test_merge_requests.py:45)
totalCount # unused variable (tests/source_collectors/github/test_merge_requests.py:46)
pullRequests # unused variable (tests/source_collectors/github/test_merge_requests.py:53)
RobotFrameworkSourceVersion # unused class (tests/source_collectors/robot_framework/test_source_version.py:6)
1 change: 1 addition & 0 deletions components/collector/src/source_collectors/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
from .gitlab.unused_jobs import GitLabUnusedJobs
from .harbor.security_warnings import HarborSecurityWarnings
from .harbor_json.security_warnings import HarborJSONSecurityWarnings
from .harbor_json.source_up_to_dateness import HarborJSONSourceUpToDateness
from .jacoco.source_up_to_dateness import JacocoSourceUpToDateness
from .jacoco.uncovered_branches import JacocoUncoveredBranches
from .jacoco.uncovered_lines import JacocoUncoveredLines
Expand Down
30 changes: 30 additions & 0 deletions components/collector/src/source_collectors/harbor_json/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""Base classes for Harbor JSON collectors."""

from typing import Final, TypedDict

REPORT_MIME_TYPE: Final = "application/vnd.security.vulnerability.report; version=1.1"


class Vulnerability(TypedDict):
"""A Harbor JSON vulnerability."""

id: str
package: str
version: str
fix_version: str
severity: str
description: str
links: list[str]


class HarborJSONVulnerabilityReport(TypedDict):
"""A Harbor JSON vulnerability report."""

generated_at: str
vulnerabilities: list[Vulnerability]


HarborJSON = TypedDict(
"HarborJSON",
{"application/vnd.security.vulnerability.report; version=1.1": HarborJSONVulnerabilityReport},
)
Original file line number Diff line number Diff line change
@@ -1,36 +1,12 @@
"""Harbor JSON security warnings collector."""

from typing import Final, TypedDict, cast
from typing import cast

from base_collectors import JSONFileSourceCollector, SecurityWarningsSourceCollector
from collector_utilities.type import JSON
from model import Entities, Entity

REPORT_MIME_TYPE: Final = "application/vnd.security.vulnerability.report; version=1.1"


class Vulnerability(TypedDict):
"""A Harbor JSON vulnerability."""

id: str
package: str
version: str
fix_version: str
severity: str
description: str
links: list[str]


class HarborJSONVulnerabilityReport(TypedDict):
"""A Harbor JSON vulnerability report."""

vulnerabilities: list[Vulnerability]


HarborJSON = TypedDict(
"HarborJSON",
{"application/vnd.security.vulnerability.report; version=1.1": HarborJSONVulnerabilityReport},
)
from .base import REPORT_MIME_TYPE, HarborJSON


class HarborJSONSecurityWarnings(SecurityWarningsSourceCollector, JSONFileSourceCollector):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"""Harbor JSON source up-to-dateness collector."""

from datetime import datetime
from typing import Final

from base_collectors import JSONFileSourceCollector, TimePassedCollector
from collector_utilities.date_time import parse_datetime
from collector_utilities.type import Response

REPORT_MIME_TYPE: Final = "application/vnd.security.vulnerability.report; version=1.1"


class HarborJSONSourceUpToDateness(JSONFileSourceCollector, TimePassedCollector):
"""Harbor JSON collector for source up-to-dateness."""

async def _parse_source_response_date_time(self, response: Response) -> datetime:
"""Override to parse the date of the most recent analysis."""
return parse_datetime((await response.json())[REPORT_MIME_TYPE]["generated_at"])
38 changes: 38 additions & 0 deletions components/collector/tests/source_collectors/harbor_json/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""Base classes for Harbor JSON collector unit tests."""

from typing import ClassVar

from source_collectors.harbor_json.base import HarborJSON

from tests.source_collectors.source_collector_test_case import SourceCollectorTestCase


class HarborJSONCollectorTestCase(SourceCollectorTestCase):
"""Base class for Harbor JSON collector unit tests."""

SOURCE_TYPE = "harbor_json"
VULNERABILITIES_JSON: ClassVar[HarborJSON] = {
"application/vnd.security.vulnerability.report; version=1.1": {
"generated_at": "2023-08-26T16:32:21.923910328Z",
"vulnerabilities": [
{
"id": "CVE-2011-3374",
"package": "apt",
"version": "2.2.4",
"fix_version": "2.2.5",
"severity": "Low",
"description": "It was found that apt-key in apt, all versions, do not correctly validate ...",
"links": ["https://avd.aquasec.com/nvd/cve-2011-3374"],
},
{
"id": "CVE-2020-22218",
"package": "libssh2-1",
"version": "1.9.0-2",
"fix_version": "",
"severity": "High",
"description": "An issue was discovered in function _libssh2_packet_add in libssh2 1.10.0 ...",
"links": ["https://avd.aquasec.com/nvd/cve-2020-22218"],
},
],
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,13 @@

from typing import ClassVar

from source_collectors.harbor_json.security_warnings import HarborJSON
from .base import HarborJSONCollectorTestCase

from tests.source_collectors.source_collector_test_case import SourceCollectorTestCase


class HarborJSONSecurityWarningsTest(SourceCollectorTestCase):
class HarborJSONSecurityWarningsTest(HarborJSONCollectorTestCase):
"""Unit tests for the security warning metric."""

SOURCE_TYPE = "harbor_json"
METRIC_TYPE = "security_warnings"
VULNERABILITIES_JSON: ClassVar[HarborJSON] = {
"application/vnd.security.vulnerability.report; version=1.1": {
"vulnerabilities": [
{
"id": "CVE-2011-3374",
"package": "apt",
"version": "2.2.4",
"fix_version": "2.2.5",
"severity": "Low",
"description": "It was found that apt-key in apt, all versions, do not correctly validate ...",
"links": ["https://avd.aquasec.com/nvd/cve-2011-3374"],
},
{
"id": "CVE-2020-22218",
"package": "libssh2-1",
"version": "1.9.0-2",
"fix_version": "",
"severity": "High",
"description": "An issue was discovered in function _libssh2_packet_add in libssh2 1.10.0 ...",
"links": ["https://avd.aquasec.com/nvd/cve-2020-22218"],
},
],
},
}
EXPECTED_ENTITIES: ClassVar[list[dict[str, str]]] = [
{
"key": "CVE-2011-3374@apt@2_2_4",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"""Unit tests for the Harbor JSON source up-to-dateness collector."""

from collector_utilities.date_time import days_ago, parse_datetime

from .base import HarborJSONCollectorTestCase


class HarborJSONSourceUpToDatenessTest(HarborJSONCollectorTestCase):
"""Unit tests for the source up-to-dateness metric."""

METRIC_TYPE = "source_up_to_dateness"

async def test_souce_up_to_dateness(self):
"""Test the source up-to-dateness."""
response = await self.collect(get_request_json_return_value=self.VULNERABILITIES_JSON)
expected_value = str(days_ago(parse_datetime("2023-08-26T16:32:21.923910328Z")))
self.assert_measurement(response, value=expected_value)
1 change: 1 addition & 0 deletions components/shared_code/src/shared_data_model/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,7 @@
"dependency_track",
"gatling",
"gitlab",
"harbor_json",
"jacoco",
"jacoco_jenkins_plugin",
"jenkins",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@
},
)

ALL_HARBOR_JSON_METRICS = ["security_warnings", "source_up_to_dateness"]

HARBOR_JSON = Source(
name="Harbor JSON",
description=(
Expand All @@ -91,7 +93,11 @@
parameters={
"severities": Severities(values=["unknown", "low", "medium", "high", "critical"]),
"fix_availability": FixAvailability(),
**access_parameters(ALL_HARBOR_METRICS, source_type="Harbor vulnerability report", source_type_format="JSON"),
**access_parameters(
ALL_HARBOR_JSON_METRICS,
source_type="Harbor vulnerability report",
source_type_format="JSON",
),
},
entities={
"security_warnings": Entity(
Expand Down
1 change: 1 addition & 0 deletions docs/src/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ If your currently installed *Quality-time* version is not the latest version, pl
### Added

- When measuring missing metrics, make the subject type and the metric type of the missing metrics link to the reference documentation. Closes [#10528](https://github.com/ICTU/quality-time/issues/10528).
- Allow for measuring the source up-to-dateness of Harbor JSON reports. Closes [#10609](https://github.com/ICTU/quality-time/issues/10609).

## v5.21.0 - 2024-12-12

Expand Down

0 comments on commit d70922d

Please sign in to comment.