Skip to content

Commit

Permalink
Merge branch 'main' into add_linter_readme
Browse files Browse the repository at this point in the history
Signed-off-by: Andrew Pollock <[email protected]>
  • Loading branch information
andrewpollock committed Nov 5, 2024
2 parents 46abd6b + 29f64c7 commit f32d28f
Show file tree
Hide file tree
Showing 11 changed files with 11,661 additions and 66 deletions.
16 changes: 16 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org

root = true

[*]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
indent_style = space
indent_size = 2

[*.go]
indent_style = tab
22 changes: 21 additions & 1 deletion .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,30 @@ concurrency:
permissions: {}

jobs:
tests_osv-go:
permissions:
contents: read # to fetch code (actions/checkout)
name: Run `bindings/go` unit tests
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./bindings/go
steps:
- name: Check out code
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
with:
persist-credentials: false
- name: Set up Go
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
with:
go-version: stable
check-latest: true

- run: go test ./...
tests_osv-linter:
permissions:
contents: read # to fetch code (actions/checkout)
name: Run unit tests
name: Run `osv-linter` unit tests
runs-on: ubuntu-latest
defaults:
run:
Expand Down
3 changes: 3 additions & 0 deletions bindings/go/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/ossf/osv-schema/bindings/go

go 1.22.7
78 changes: 78 additions & 0 deletions bindings/go/osvschema/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package osvschema

type Ecosystem string

const (
EcosystemAlmaLinux Ecosystem = "AlmaLinux"
EcosystemAlpine Ecosystem = "Alpine"
EcosystemAndroid Ecosystem = "Android"
EcosystemBioconductor Ecosystem = "Bioconductor"
EcosystemBitnami Ecosystem = "Bitnami"
EcosystemConanCenter Ecosystem = "ConanCenter"
EcosystemCRAN Ecosystem = "CRAN"
EcosystemCratesIO Ecosystem = "crates.io"
EcosystemDebian Ecosystem = "Debian"
EcosystemGitHubActions Ecosystem = "GitHub Actions"
EcosystemGo Ecosystem = "Go"
EcosystemHex Ecosystem = "Hex"
EcosystemLinux Ecosystem = "Linux"
EcosystemMaven Ecosystem = "Maven"
EcosystemNPM Ecosystem = "npm"
EcosystemNuGet Ecosystem = "NuGet"
EcosystemOSSFuzz Ecosystem = "OSS-Fuzz"
EcosystemPackagist Ecosystem = "Packagist"
EcosystemPhotonOS Ecosystem = "Photon OS"
EcosystemPub Ecosystem = "Pub"
EcosystemPyPI Ecosystem = "PyPI"
EcosystemRedHat Ecosystem = "Red Hat"
EcosystemRockyLinux Ecosystem = "Rocky Linux"
EcosystemRubyGems Ecosystem = "RubyGems"
EcosystemSwiftURL Ecosystem = "SwiftURL"
EcosystemUbuntu Ecosystem = "Ubuntu"
)

type SeverityType string

const (
SeverityCVSSV2 SeverityType = "CVSS_V2"
SeverityCVSSV3 SeverityType = "CVSS_V3"
SeverityCVSSV4 SeverityType = "CVSS_V4"
)

type RangeType string

const (
RangeSemVer RangeType = "SEMVER"
RangeEcosystem RangeType = "ECOSYSTEM"
RangeGit RangeType = "GIT"
)

type ReferenceType string

const (
ReferenceAdvisory ReferenceType = "ADVISORY"
ReferenceArticle ReferenceType = "ARTICLE"
ReferenceDetection ReferenceType = "DETECTION"
ReferenceDiscussion ReferenceType = "DISCUSSION"
ReferenceReport ReferenceType = "REPORT"
ReferenceFix ReferenceType = "FIX"
ReferenceIntroduced ReferenceType = "INTRODUCED"
ReferencePackage ReferenceType = "PACKAGE"
ReferenceEvidence ReferenceType = "EVIDENCE"
ReferenceWeb ReferenceType = "WEB"
)

type CreditType string

const (
CreditFinder CreditType = "FINDER"
CreditReporter CreditType = "REPORTER"
CreditAnalyst CreditType = "ANALYST"
CreditCoordinator CreditType = "COORDINATOR"
CreditRemediationDeveloper CreditType = "REMEDIATION_DEVELOPER" //nolint:gosec
CreditRemediationReviewer CreditType = "REMEDIATION_REVIEWER" //nolint:gosec
CreditRemediationVerifier CreditType = "REMEDIATION_VERIFIER" //nolint:gosec
CreditTool CreditType = "TOOL"
CreditSponsor CreditType = "SPONSOR"
CreditOther CreditType = "OTHER"
)
5 changes: 4 additions & 1 deletion docs/schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,8 @@ within its ecosystem. The two fields must both be present, because the

The `purl` field is a string following the
[Package URL specification](https://github.com/package-url/purl-spec) that
identifies the package. This field is optional but recommended.
identifies the package, without the `@version` component.
This field is optional but recommended.

Different ecosystems can define the same names; they identify different
packages. For example, these denote different libraries with different sets of
Expand All @@ -681,6 +682,8 @@ versions and different potential vulnerabilities:
{"ecosystem": "PyPI", "name": "zlib"}
```

#### Defined ecosystems

<!-- Please keep this list alphabetically sorted -->
The defined ecosystems are:

Expand Down
40 changes: 22 additions & 18 deletions tools/redhat/redhat_osv/convert_redhat_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,29 @@
class TestRedHatConverter(unittest.TestCase):
"""Test end-to-end convertion from RedHAt CSAF to OSV format"""

test_advisories = ["2024_4546", "2024_6220"]

def test_convert_redhat(self):
""" Test a single demo CSAF file """
modified_time = datetime.strptime("2024-09-02T14:30:00",
"%Y-%m-%dT%H:%M:%S")
csaf_file = "testdata/rhsa-2024_4546.json"
expected_file = "testdata/RHSA-2024_4546.json"

with open(csaf_file, "r", encoding="utf-8") as fp:
csaf_data = fp.read()
converter = RedHatConverter()
osv_data = converter.convert(csaf_data,
modified_time.strftime(DATE_FORMAT))

assert osv_data[0] == "RHSA-2024:4546"
result_data = json.loads(osv_data[1])

with open(expected_file, "r", encoding="utf-8") as fp:
expected_data = json.load(fp)
assert expected_data == result_data
for test_advisory in self.test_advisories:
""" Test a single demo CSAF file """
modified_time = datetime.strptime("2024-09-02T14:30:00",
"%Y-%m-%dT%H:%M:%S")
csaf_file = f"testdata/rhsa-{test_advisory}.json"
expected_file = f"testdata/RHSA-{test_advisory}.json"

with open(csaf_file, "r", encoding="utf-8") as fp:
csaf_data = fp.read()
converter = RedHatConverter()
osv_data = converter.convert(csaf_data,
modified_time.strftime(DATE_FORMAT))

advisory_id = test_advisory.replace("_", ":")
assert osv_data[0] == f"RHSA-{advisory_id}"
result_data = json.loads(osv_data[1])

with open(expected_file, "r", encoding="utf-8") as fp:
expected_data = json.load(fp)
assert expected_data == result_data


if __name__ == '__main__':
Expand Down
11 changes: 9 additions & 2 deletions tools/redhat/redhat_osv/csaf.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from dataclasses import dataclass, InitVar, field
from typing import Any, Iterable

class RemediationParseError(ValueError):
pass

@dataclass
class Remediation:
Expand Down Expand Up @@ -32,7 +34,7 @@ def __post_init__(self, csaf_product_id: str, cpes: dict[str, str],
# We split the name from the rest of the 'version' data (EVRA). We store name as component.
split_component_version = self.product_version.rsplit("-", maxsplit=2)
if len(split_component_version) < 3:
raise ValueError(
raise RemediationParseError(
f"Could not convert component into NEVRA: {self.product_version}"
)
# RHEL Modules have 4 colons in the name part of the NEVRA. If we detect a modular RPM
Expand Down Expand Up @@ -96,7 +98,12 @@ def __post_init__(self, csaf_vuln: dict[str, Any], cpes: dict[str, str],
self.references = csaf_vuln["references"]
self.remediations = []
for product_id in csaf_vuln["product_status"]["fixed"]:
self.remediations.append(Remediation(product_id, cpes, purls))
try:
self.remediations.append(Remediation(product_id, cpes, purls))
except RemediationParseError:
continue
if not self.remediations:
raise ValueError(f"Did not find any remediations for {self.cve_id}")


def gen_dict_extract(key, var: Iterable):
Expand Down
23 changes: 13 additions & 10 deletions tools/redhat/redhat_osv/osv.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,12 @@ def __init__(self, csaf_data: CSAF, modified: str, published: str = ""):
}]

self.affected: list[Affected] = []

# Deduplicate arch specific remediations
unique_packages: dict[str: tuple[str: str]] = {}

for vulnerability in csaf_data.vulnerabilities:
self.related.append(vulnerability.cve_id)
# Deduplicate arch specific remediations
unique_packages: dict[str: tuple[str: str]] = {}
for remediation in vulnerability.remediations:
# Safety check for when we start processing non-rpm content
if not remediation.purl.startswith("pkg:rpm/"):
Expand All @@ -173,14 +175,15 @@ def __init__(self, csaf_data: CSAF, modified: str, published: str = ""):
unique_packages[remediation.cpe + "&" + remediation.component] = (
version_arch_split[0], remediation.purl,
)
# Add all the RPM packages without arch suffixes
for package_key, version_purl in unique_packages.items():
package_key_parts = package_key.split("&", 1)
cpe = package_key_parts[0]
component = package_key_parts[1]
package = Package(component, cpe, version_purl[1])
ranges = [Range(version_purl[0])]
self.affected.append(Affected(package, ranges))

# Add all the RPM packages without arch suffixes
for package_key, version_purl in unique_packages.items():
package_key_parts = package_key.split("&", 1)
cpe = package_key_parts[0]
component = package_key_parts[1]
package = Package(component, cpe, version_purl[1])
ranges = [Range(version_purl[0])]
self.affected.append(Affected(package, ranges))

self.references = self._convert_references(csaf_data)

Expand Down
Loading

0 comments on commit f32d28f

Please sign in to comment.