From b6749e6f7838ab8723c74d0624fe9c9ff8981cfc Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Wed, 22 Feb 2023 08:28:23 -0500 Subject: [PATCH] fix: ensure we can serialize/deserialize the ghsa model (#35) * fix: ensure we can serialize/deserialize the ghsa model * chore: bump version --- CHANGELOG.md | 6 ++ .../vuln.tools.java-common-conventions.gradle | 2 +- gh-advisory-lib/README.md | 4 +- .../java/io/github/jeremylong/ghsa/CWE.java | 32 +++++++ .../ghsa/{CWEPage.java => CWEs.java} | 11 +-- .../ghsa/GitHubSecurityAdvisoryClient.java | 24 ++--- .../io/github/jeremylong/ghsa/Identifier.java | 4 +- .../io/github/jeremylong/ghsa/Package.java | 4 +- ...iesResult.java => SecurityAdvisories.java} | 40 +++++++-- .../jeremylong/ghsa/SecurityAdvisory.java | 15 ++-- ...ult.java => SecurityAdvisoryResponse.java} | 10 ++- ...rabilityPage.java => Vulnerabilities.java} | 11 +-- .../github/jeremylong/ghsa/Vulnerability.java | 87 +++++++++++++++++++ .../jeremylong/ghsa/SerializationTest.java | 18 ++-- nvd-lib/README.md | 4 +- 15 files changed, 214 insertions(+), 58 deletions(-) rename gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/{CWEPage.java => CWEs.java} (85%) rename gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/{SecurityAdvisoriesResult.java => SecurityAdvisories.java} (77%) rename gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/{SecurityAdvisoryResult.java => SecurityAdvisoryResponse.java} (91%) rename gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/{VulnerabilityPage.java => Vulnerabilities.java} (84%) diff --git a/CHANGELOG.md b/CHANGELOG.md index a821904c..c0ee91e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## 2.0.2 - 2023-02-22 + +### Fixed + +- Ensure GHSA model can be serialized and deserialized ([#35](https://github.com/jeremylong/vuln-tools/pull/35)). + ## 2.0.1 - 2023-02-21 ### Fixed diff --git a/buildSrc/src/main/groovy/vuln.tools.java-common-conventions.gradle b/buildSrc/src/main/groovy/vuln.tools.java-common-conventions.gradle index 86f34493..f83ab3fe 100644 --- a/buildSrc/src/main/groovy/vuln.tools.java-common-conventions.gradle +++ b/buildSrc/src/main/groovy/vuln.tools.java-common-conventions.gradle @@ -12,7 +12,7 @@ plugins { } group 'io.github.jeremylong' -version = '2.0.1' +version = '2.0.2' repositories { mavenCentral() diff --git a/gh-advisory-lib/README.md b/gh-advisory-lib/README.md index 75086c92..173e9250 100644 --- a/gh-advisory-lib/README.md +++ b/gh-advisory-lib/README.md @@ -12,14 +12,14 @@ The client requires a GitHub Personal Access Token to access the API. io.github.jeremylong gh-advisory-lib - 2.0.1 + 2.0.2 ``` ### gradle ```groovy -implementation 'io.github.jeremylong:gh-advisory-lib:2.0.1' +implementation 'io.github.jeremylong:gh-advisory-lib:2.0.2' ``` ### building from source diff --git a/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/CWE.java b/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/CWE.java index 44793a3c..1c1a0145 100644 --- a/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/CWE.java +++ b/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/CWE.java @@ -17,6 +17,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; import java.util.Objects; @@ -24,6 +25,7 @@ * Common weakness enumeration. */ @JsonIgnoreProperties(ignoreUnknown = true) +@JsonPropertyOrder({"cweId", "name", "description"}) public class CWE { @JsonProperty(value = "node", access = JsonProperty.Access.WRITE_ONLY) @@ -35,27 +37,57 @@ public class CWE { * @return the id of the CWE */ public String getCweId() { + if (node == null) { + return null; + } return node.cweId; } + void setCweId(String cweId) { + if (node == null) { + this.node = new CWERecord(); + } + node.cweId = cweId; + } + /** * Returns a detailed description of this CWE. * * @return a detailed description of this CWE. */ public String getDescription() { + if (node == null) { + return null; + } return node.description; } + void setDescription(String description) { + if (node == null) { + node = new CWERecord(); + } + node.description = description; + } + /** * The name of this CWE. * * @return the name of this CWE. */ public String getName() { + if (node == null) { + return null; + } return node.name; } + void setName(String name) { + if (node == null) { + node = new CWERecord(); + } + node.name = name; + } + @Override public String toString() { if (node == null) { diff --git a/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/CWEPage.java b/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/CWEs.java similarity index 85% rename from gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/CWEPage.java rename to gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/CWEs.java index 98ad2709..ef89188a 100644 --- a/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/CWEPage.java +++ b/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/CWEs.java @@ -22,7 +22,7 @@ import java.util.List; import java.util.Objects; -public class CWEPage extends AbstractPageable { +public class CWEs extends AbstractPageable { @JsonProperty("edges") private List cwes; @@ -30,13 +30,13 @@ public class CWEPage extends AbstractPageable { @SuppressFBWarnings(value = {"EI_EXPOSE_REP", "EI_EXPOSE_REP2"}, justification = "I prefer to suppress these FindBugs warnings") @JsonIgnore - public List getPage() { + public List getEdges() { return cwes; } @Override public String toString() { - return "CWEPage{" + "cwes=" + cwes + ", totalCount=" + getTotalCount() + "}"; + return "CWEs{" + "cwes=" + cwes + ", totalCount=" + getTotalCount() + "}"; } @Override @@ -45,7 +45,7 @@ public boolean equals(Object o) { return true; if (o == null || getClass() != o.getClass()) return false; - CWEPage cwePage = (CWEPage) o; + CWEs cwePage = (CWEs) o; return Objects.equals(cwes, cwePage.cwes); } @@ -54,7 +54,8 @@ public int hashCode() { return Objects.hash(cwes); } - public boolean addCwes(List c) { + boolean addCwes(List c) { return this.cwes.addAll(c); } + } diff --git a/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/GitHubSecurityAdvisoryClient.java b/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/GitHubSecurityAdvisoryClient.java index 593ee087..e9a349d4 100644 --- a/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/GitHubSecurityAdvisoryClient.java +++ b/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/GitHubSecurityAdvisoryClient.java @@ -271,7 +271,7 @@ public List next() { if (body == null) { body = new String(response.getBodyBytes(), StandardCharsets.UTF_8); } - SecurityAdvisoriesResult results = objectMapper.readValue(body, SecurityAdvisoriesResult.class); + SecurityAdvisories results = objectMapper.readValue(body, SecurityAdvisories.class); List list = results.getSecurityAdvisories(); totalCount += list.size(); if (results.getPageInfo().isHasNextPage() || totalCount < results.getTotalCount()) { @@ -343,12 +343,12 @@ private void ensureSubPages(List list) throws ExecutionExcepti int max = sa.getCwes().getTotalCount(); String after = sa.getCwes().getPageInfo().getEndCursor(); while (count < max) { - SecurityAdvisoryResult results = fetch(cwesTemplate, sa.getGhsaId(), after); - CWEPage cwes = results.getSecurityAdvisory().getCwes(); - count += cwes.getPage().size(); + SecurityAdvisoryResponse results = fetch(cwesTemplate, sa.getGhsaId(), after); + CWEs cwes = results.getSecurityAdvisory().getCwes(); + count += cwes.getEdges().size(); max = cwes.getTotalCount(); after = cwes.getPageInfo().getEndCursor(); - sa.getCwes().addCwes(cwes.getPage()); + sa.getCwes().addCwes(cwes.getEdges()); } } if (sa.getVulnerabilities().getPageInfo().isHasNextPage() @@ -358,12 +358,12 @@ private void ensureSubPages(List list) throws ExecutionExcepti int max = sa.getVulnerabilities().getTotalCount(); String after = sa.getVulnerabilities().getPageInfo().getEndCursor(); while (count < max) { - SecurityAdvisoryResult results = fetch(vulnerabilitiesTemplate, sa.getGhsaId(), after); - VulnerabilityPage vulnerability = results.getSecurityAdvisory().getVulnerabilities(); - count += vulnerability.getPage().size(); + SecurityAdvisoryResponse results = fetch(vulnerabilitiesTemplate, sa.getGhsaId(), after); + Vulnerabilities vulnerability = results.getSecurityAdvisory().getVulnerabilities(); + count += vulnerability.getEdges().size(); max = vulnerability.getTotalCount(); after = vulnerability.getPageInfo().getEndCursor(); - sa.getVulnerabilities().addVulnerabilties(vulnerability.getPage()); + sa.getVulnerabilities().addVulnerabilties(vulnerability.getEdges()); } } } @@ -379,9 +379,9 @@ private void ensureSubPages(List list) throws ExecutionExcepti * @throws ExecutionException thrown if there is a problem. * @throws InterruptedException thrown if interrupted. */ - private SecurityAdvisoryResult fetch(Template template, String ghsaId, String after) + private SecurityAdvisoryResponse fetch(Template template, String ghsaId, String after) throws InterruptedException, ExecutionException { - SecurityAdvisoryResult results = null; + SecurityAdvisoryResponse results = null; try { Map data = new HashMap(); data.put("ghsaId", ghsaId); @@ -392,7 +392,7 @@ private SecurityAdvisoryResult fetch(Template template, String ghsaId, String af if (body == null) { body = new String(response.getBodyBytes(), StandardCharsets.UTF_8); } - results = objectMapper.readValue(body, SecurityAdvisoryResult.class); + results = objectMapper.readValue(body, SecurityAdvisoryResponse.class); } catch (JsonProcessingException e) { LOG.debug("Deserialization Error", e); throw new GitHubSecurityAdvisoryException(e); diff --git a/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/Identifier.java b/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/Identifier.java index 87cea2bf..53a654e8 100644 --- a/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/Identifier.java +++ b/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/Identifier.java @@ -17,17 +17,19 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; import java.util.Objects; /** * A GitHub Security Advisory Identifier. - * + * *
  * type SecurityAdvisoryIdentifier
  * 
*/ @JsonIgnoreProperties(ignoreUnknown = true) +@JsonPropertyOrder({"type", "value"}) public class Identifier { @JsonProperty("type") diff --git a/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/Package.java b/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/Package.java index d68bb44a..1c22badc 100644 --- a/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/Package.java +++ b/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/Package.java @@ -17,6 +17,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; import java.util.Objects; @@ -28,7 +29,8 @@ * */ @JsonIgnoreProperties(ignoreUnknown = true) -class Package { +@JsonPropertyOrder({"ecosystem", "name"}) +public class Package { @JsonProperty("ecosystem") private String ecosystem; diff --git a/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/SecurityAdvisoriesResult.java b/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/SecurityAdvisories.java similarity index 77% rename from gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/SecurityAdvisoriesResult.java rename to gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/SecurityAdvisories.java index 1086aaa2..b8b1e246 100644 --- a/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/SecurityAdvisoriesResult.java +++ b/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/SecurityAdvisories.java @@ -15,6 +15,7 @@ */ package io.github.jeremylong.ghsa; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; @@ -22,9 +23,9 @@ import java.util.Objects; @JsonIgnoreProperties(ignoreUnknown = true) -public class SecurityAdvisoriesResult { +public class SecurityAdvisories { - @JsonProperty("data") + @JsonProperty(value = "data", access = JsonProperty.Access.WRITE_ONLY) private Data data; /** @@ -32,7 +33,11 @@ public class SecurityAdvisoriesResult { * * @return the rate limit. */ - public RateLimit getRateLimit() { + @JsonIgnore + RateLimit getRateLimit() { + if (data == null) { + return null; + } return data.rateLimit; } @@ -42,15 +47,30 @@ public RateLimit getRateLimit() { * @return the security advisories. */ public List getSecurityAdvisories() { + if (data == null || data.securityAdvisories == null) { + return null; + } return data.securityAdvisories.nodes; } + void setSecurityAdvisories(List advisories) { + if (data == null) { + data = new Data(); + data.securityAdvisories = new Advisories(); + } + data.securityAdvisories.nodes = advisories; + } + /** * Returns the current page info. * * @return the page info. */ - public PageInfo getPageInfo() { + @JsonIgnore + PageInfo getPageInfo() { + if (data == null || data.securityAdvisories == null) { + return null; + } return data.securityAdvisories.getPageInfo(); } @@ -59,7 +79,11 @@ public PageInfo getPageInfo() { * * @return the total count. */ + @JsonIgnore public int getTotalCount() { + if (data == null || data.securityAdvisories == null) { + return 0; + } return data.securityAdvisories.getTotalCount(); } @@ -77,7 +101,7 @@ public boolean equals(Object o) { return true; if (o == null || getClass() != o.getClass()) return false; - SecurityAdvisoriesResult that = (SecurityAdvisoriesResult) o; + SecurityAdvisories that = (SecurityAdvisories) o; return Objects.equals(data, that.data); } @@ -94,7 +118,7 @@ static class Data { @JsonProperty("rateLimit") private RateLimit rateLimit; @JsonProperty("securityAdvisories") - private SecurityAdvisories securityAdvisories; + private Advisories securityAdvisories; @Override public String toString() { @@ -122,7 +146,7 @@ public int hashCode() { * internal security advisories. */ @JsonIgnoreProperties(ignoreUnknown = true) - static class SecurityAdvisories extends AbstractPageable { + static class Advisories extends AbstractPageable { @JsonProperty("nodes") private List nodes; @@ -138,7 +162,7 @@ public boolean equals(Object o) { return true; if (o == null || getClass() != o.getClass()) return false; - SecurityAdvisories that = (SecurityAdvisories) o; + Advisories that = (Advisories) o; return Objects.equals(nodes, that.nodes); } diff --git a/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/SecurityAdvisory.java b/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/SecurityAdvisory.java index be20295f..19db8073 100644 --- a/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/SecurityAdvisory.java +++ b/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/SecurityAdvisory.java @@ -16,9 +16,9 @@ package io.github.jeremylong.ghsa; import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.time.ZonedDateTime; @@ -26,6 +26,9 @@ import java.util.Objects; @JsonIgnoreProperties(ignoreUnknown = true) +@JsonPropertyOrder({"databaseId", "description", "ghsaId", "id", "identifiers", "notificationsPermalink", "origin", + "permalink", "publishedAt", "references", "severity", "summary", "updatedAt", "vulnerabilities", "cvss", "cwes", + "withdrawnAt"}) public class SecurityAdvisory { @JsonProperty("databaseId") @@ -77,10 +80,10 @@ public class SecurityAdvisory { private CVSS cvss; @JsonProperty(value = "cwes") - private CWEPage cwes; + private CWEs cwes; @JsonProperty(value = "vulnerabilities") - private VulnerabilityPage vulnerabilities; + private Vulnerabilities vulnerabilities; /** * Identifies the primary key from the database. @@ -222,13 +225,13 @@ public CVSS getCvss() { } /** - * Returns CWEs associated with this Advisory. + * Returns CWE Page associated with this Advisory. * * @return CWEs associated with this Advisory. */ @SuppressFBWarnings(value = {"EI_EXPOSE_REP", "EI_EXPOSE_REP2"}, justification = "I prefer to suppress these FindBugs warnings") - public CWEPage getCwes() { + public CWEs getCwes() { return cwes; } @@ -239,7 +242,7 @@ public CWEPage getCwes() { */ @SuppressFBWarnings(value = {"EI_EXPOSE_REP", "EI_EXPOSE_REP2"}, justification = "I prefer to suppress these FindBugs warnings") - public VulnerabilityPage getVulnerabilities() { + public Vulnerabilities getVulnerabilities() { return vulnerabilities; } diff --git a/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/SecurityAdvisoryResult.java b/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/SecurityAdvisoryResponse.java similarity index 91% rename from gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/SecurityAdvisoryResult.java rename to gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/SecurityAdvisoryResponse.java index c6b7a7db..d5ded315 100644 --- a/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/SecurityAdvisoryResult.java +++ b/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/SecurityAdvisoryResponse.java @@ -21,8 +21,11 @@ import java.util.List; import java.util.Objects; +/** + * Internal class used to gather additional vulnerabilities if a security advisory has more than 100 entries. + */ @JsonIgnoreProperties(ignoreUnknown = true) -public class SecurityAdvisoryResult { +class SecurityAdvisoryResponse { @JsonProperty("data") private Data data; @@ -59,7 +62,7 @@ public boolean equals(Object o) { return true; if (o == null || getClass() != o.getClass()) return false; - SecurityAdvisoryResult that = (SecurityAdvisoryResult) o; + SecurityAdvisoryResponse that = (SecurityAdvisoryResponse) o; return Objects.equals(data, that.data); } @@ -116,8 +119,7 @@ static class SecurityAdvisories { @Override public String toString() { - return "SecurityAdvisories{" + "nodes=" + nodes + ", totalCount=" + totalCount + ", pageInfo=" + pageInfo - + '}'; + return "Advisories{" + "nodes=" + nodes + ", totalCount=" + totalCount + ", pageInfo=" + pageInfo + '}'; } @Override diff --git a/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/VulnerabilityPage.java b/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/Vulnerabilities.java similarity index 84% rename from gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/VulnerabilityPage.java rename to gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/Vulnerabilities.java index 920d2802..47810395 100644 --- a/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/VulnerabilityPage.java +++ b/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/Vulnerabilities.java @@ -24,7 +24,7 @@ import java.util.Objects; @JsonIgnoreProperties(ignoreUnknown = true) -public class VulnerabilityPage extends AbstractPageable { +public class Vulnerabilities extends AbstractPageable { @JsonProperty("edges") private List vulnerabilities; @@ -32,17 +32,17 @@ public class VulnerabilityPage extends AbstractPageable { @SuppressFBWarnings(value = {"EI_EXPOSE_REP", "EI_EXPOSE_REP2"}, justification = "I prefer to suppress these FindBugs warnings") @JsonIgnore - public List getPage() { + public List getEdges() { return vulnerabilities; } - public boolean addVulnerabilties(List v) { + boolean addVulnerabilties(List v) { return vulnerabilities.addAll(v); } @Override public String toString() { - return "VulnerabilityPage{" + "vulnerabilities=" + vulnerabilities + '}'; + return "Vulnerabilities{" + "vulnerabilities=" + vulnerabilities + '}'; } @Override @@ -51,7 +51,7 @@ public boolean equals(Object o) { return true; if (o == null || getClass() != o.getClass()) return false; - VulnerabilityPage that = (VulnerabilityPage) o; + Vulnerabilities that = (Vulnerabilities) o; return Objects.equals(vulnerabilities, that.vulnerabilities); } @@ -59,4 +59,5 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(vulnerabilities); } + } diff --git a/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/Vulnerability.java b/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/Vulnerability.java index 324510dd..e6be4b5f 100644 --- a/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/Vulnerability.java +++ b/gh-advisory-lib/src/main/java/io/github/jeremylong/ghsa/Vulnerability.java @@ -17,6 +17,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; import java.time.ZonedDateTime; import java.util.Objects; @@ -29,6 +30,7 @@ * */ @JsonIgnoreProperties(ignoreUnknown = true) +@JsonPropertyOrder({"severity", "updatedAt", "firstPatchedVersion", "vulnerableVersionRange", "package"}) public class Vulnerability { @JsonProperty(value = "node", access = JsonProperty.Access.WRITE_ONLY) @@ -39,37 +41,105 @@ public class Vulnerability { * * @return the first version containing a fix for the vulnerability. */ + @JsonProperty(value = "firstPatchedVersion") public PackageVersion getFirstPatchedVersion() { + if (node == null) { + return null; + } return node.firstPatchedVersion; } + /** + * Internal setter for deserialization. + * + * @param packageVersion the version. + */ + @JsonProperty(value = "firstPatchedVersion") + void setFirstPatchedVersion(PackageVersion packageVersion) { + if (node == null) { + node = new VulnerabilityRecord(); + } + node.firstPatchedVersion = packageVersion; + } + /** * A description of the vulnerable package. * * @return a description of the vulnerable package. */ + @JsonProperty(value = "package") public Package getPackage() { + if (node == null) { + return null; + } return node.pkg; } + /** + * Internal setter for deserialization. + * + * @param pkg the package + */ + @JsonProperty(value = "package") + void setPackage(Package pkg) { + if (node == null) { + node = new VulnerabilityRecord(); + } + node.pkg = pkg; + } + /** * The severity of the vulnerability within this package. * * @return the severity of the vulnerability within this package. */ + @JsonProperty(value = "severity") public Severity getSeverity() { + if (node == null) { + return null; + } return node.severity; } + /** + * Internal setter for deserialization. + * + * @param severity severity + */ + @JsonProperty(value = "severity") + void setSeverity(Severity severity) { + if (node == null) { + node = new VulnerabilityRecord(); + } + node.severity = severity; + } + /** * When the vulnerability was last updated. * * @return when the vulnerability was last updated. */ + @JsonProperty(value = "updatedAt") public ZonedDateTime getUpdatedAt() { + if (node == null) { + return null; + } return node.updatedAt; } + /** + * Internal setter for deserialization. + * + * @param updatedAt updated date time + */ + @JsonProperty(value = "updatedAt") + void setUpdatedAt(ZonedDateTime updatedAt) { + if (node == null) { + node = new VulnerabilityRecord(); + } + node.updatedAt = updatedAt; + } + /** * A string that describes the vulnerable package versions. This string follows a basic syntax with a few forms. * @@ -83,10 +153,27 @@ public ZonedDateTime getUpdatedAt() { * * @return the range. */ + @JsonProperty(value = "vulnerableVersionRange") public String getVulnerableVersionRange() { + if (node == null) { + return null; + } return node.vulnerableVersionRange; } + /** + * Internal setter for deserialization. + * + * @param range the range + */ + @JsonProperty(value = "vulnerableVersionRange") + void setVulnerableVersionRange(String range) { + if (node == null) { + node = new VulnerabilityRecord(); + } + node.vulnerableVersionRange = range; + } + @Override public String toString() { return "Vulnerability[" + node + ']'; diff --git a/gh-advisory-lib/src/test/java/io/github/jeremylong/ghsa/SerializationTest.java b/gh-advisory-lib/src/test/java/io/github/jeremylong/ghsa/SerializationTest.java index 93e82505..82371113 100644 --- a/gh-advisory-lib/src/test/java/io/github/jeremylong/ghsa/SerializationTest.java +++ b/gh-advisory-lib/src/test/java/io/github/jeremylong/ghsa/SerializationTest.java @@ -15,44 +15,40 @@ */ package io.github.jeremylong.ghsa; -import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import io.github.jeremylong.ghsa.SecurityAdvisoriesResult; import org.junit.jupiter.api.Test; import java.io.BufferedReader; -import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; -import java.util.TimeZone; import java.util.stream.Collectors; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; public class SerializationTest { @Test - void parse() throws IOException { + void thereAndBackAgain() throws IOException { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.registerModule(new JavaTimeModule()); objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); - objectMapper.enable(SerializationFeature.WRITE_DATES_WITH_ZONE_ID); - objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); - objectMapper.setTimeZone(TimeZone.getTimeZone("UTC")); String json; try (BufferedReader r = new BufferedReader(new InputStreamReader( this.getClass().getClassLoader().getResourceAsStream("advisories.json"), StandardCharsets.UTF_8))) { json = r.lines().collect(Collectors.joining("\n")); } - SecurityAdvisoriesResult current = objectMapper.readValue(json, SecurityAdvisoriesResult.class); + SecurityAdvisories current = objectMapper.readValue(json, SecurityAdvisories.class); assertEquals(5000, current.getRateLimit().getLimit()); - // File f = File.createTempFile("ghsa","json"); - // objectMapper. + String serialized = objectMapper.writeValueAsString(current); + SecurityAdvisories hydrated = objectMapper.readValue(serialized, SecurityAdvisories.class); + String reserialized = objectMapper.writeValueAsString(hydrated); + assertTrue(serialized.equals(reserialized)); } } diff --git a/nvd-lib/README.md b/nvd-lib/README.md index a083ea5c..e008defd 100644 --- a/nvd-lib/README.md +++ b/nvd-lib/README.md @@ -14,14 +14,14 @@ Vulnerability Catalog can be downloaded in ~90 seconds. io.github.jeremylong nvd-lib - 2.0.1 + 2.0.2 ``` ### gradle ```groovy -implementation 'io.github.jeremylong:nvd-lib:2.0.1' +implementation 'io.github.jeremylong:nvd-lib:2.0.2' ``` ### building from source