Skip to content

Commit

Permalink
Parse CVE DB objects into domain objects (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
fwilhe authored May 8, 2024
1 parent e3b98ee commit b29d6a8
Show file tree
Hide file tree
Showing 14 changed files with 84 additions and 93 deletions.
5 changes: 3 additions & 2 deletions src/main/java/io/gardenlinux/glvd/GlvdController.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.gardenlinux.glvd;

import io.gardenlinux.glvd.dto.Cve;
import io.gardenlinux.glvd.exceptions.CantParseJSONException;
import io.gardenlinux.glvd.exceptions.NotFoundException;
import jakarta.annotation.Nonnull;
import org.springframework.http.MediaType;
Expand Down Expand Up @@ -29,8 +30,8 @@ ResponseEntity<Cve> getCveId(@PathVariable("cveId") final String cveId) throws N
}

@GetMapping("/{vendor}/{product}/{codename}")
ResponseEntity<List<String>> getCveDistro(@PathVariable final String vendor, @PathVariable final String product,
@PathVariable final String codename) {
ResponseEntity<List<Cve>> getCveDistro(@PathVariable final String vendor, @PathVariable final String product,
@PathVariable final String codename) throws CantParseJSONException {
return ResponseEntity.ok().body(glvdService.getCveForDistribution(vendor, product, codename));
}

Expand Down
25 changes: 20 additions & 5 deletions src/main/java/io/gardenlinux/glvd/GlvdService.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package io.gardenlinux.glvd;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.gardenlinux.glvd.db.CveEntity;
import io.gardenlinux.glvd.db.CveRepository;
import io.gardenlinux.glvd.db.HealthCheckRepository;
import io.gardenlinux.glvd.dto.Cve;
import io.gardenlinux.glvd.dto.Readiness;
import io.gardenlinux.glvd.exceptions.CantParseJSONException;
import io.gardenlinux.glvd.exceptions.DbNotConnectedException;
import io.gardenlinux.glvd.exceptions.NotFoundException;
import jakarta.annotation.Nonnull;
Expand All @@ -20,9 +24,12 @@ public class GlvdService {
@Nonnull
private final HealthCheckRepository healthCheckRepository;

private final ObjectMapper objectMapper;

public GlvdService(@Nonnull CveRepository cveRepository, @Nonnull HealthCheckRepository healthCheckRepository) {
this.cveRepository = cveRepository;
this.healthCheckRepository = healthCheckRepository;
this.objectMapper = new ObjectMapper();
}

public Readiness getReadiness() throws DbNotConnectedException {
Expand All @@ -34,15 +41,23 @@ public Readiness getReadiness() throws DbNotConnectedException {
}
}

public Cve getCve(String cveId) throws NotFoundException {
public Cve getCve(String cveId) throws NotFoundException, CantParseJSONException {
var cveEntity = cveRepository.findById(cveId).orElseThrow(NotFoundException::new);
// Todo: more specific transformation from db type 'cve' to response type 'cve'
return new Cve(cveEntity.getId(), cveEntity.getLastModified(), cveEntity.getData());

return cveEntityDataToDomainEntity(cveEntity);
}

public List<String> getCveForDistribution(String vendor, String product, String codename) {
return cveRepository.cvesForDistribution(vendor, product, codename);
public List<Cve> getCveForDistribution(String vendor, String product, String codename) throws CantParseJSONException {
var entities = cveRepository.cvesForDistribution(vendor, product, codename);

return entities.stream().map(this::cveEntityDataToDomainEntity).toList();
}

private Cve cveEntityDataToDomainEntity(CveEntity cveEntity) throws CantParseJSONException {
try {
return objectMapper.readValue(cveEntity.getData(), Cve.class);
} catch (JsonProcessingException e) {
throw new CantParseJSONException("Failed to parse JSON object into domain classes:\n====\n" + cveEntity.getData() + "\n====");
}
}
}
5 changes: 3 additions & 2 deletions src/main/java/io/gardenlinux/glvd/db/CveRepository.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.gardenlinux.glvd.db;

import io.gardenlinux.glvd.dto.Cve;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

Expand All @@ -9,7 +10,7 @@ public interface CveRepository extends JpaRepository<CveEntity, String> {

@Query(value = """
SELECT
all_cve.data AS cveEntity
all_cve.*
FROM
all_cve
INNER JOIN deb_cve USING (cve_id)
Expand All @@ -21,6 +22,6 @@ INNER JOIN dist_cpe ON (deb_cve.dist_id = dist_cpe.id)
ORDER BY
all_cve.cve_id
""", nativeQuery = true)
List<String> cvesForDistribution(String vendor, String product, String codename);
List<CveEntity> cvesForDistribution(String vendor, String product, String codename);

}
7 changes: 7 additions & 0 deletions src/main/java/io/gardenlinux/glvd/dto/Configuration.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.gardenlinux.glvd.dto;

import java.util.List;

public record Configuration(List<Node> nodes) {

}
6 changes: 6 additions & 0 deletions src/main/java/io/gardenlinux/glvd/dto/CpeMatch.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package io.gardenlinux.glvd.dto;

public record CpeMatch(String criteria, Deb deb, boolean vulnerable, String versionStartIncluding,
String versionEndExcluding, String matchCriteriaId) {

}
59 changes: 5 additions & 54 deletions src/main/java/io/gardenlinux/glvd/dto/Cve.java
Original file line number Diff line number Diff line change
@@ -1,59 +1,10 @@
package io.gardenlinux.glvd.dto;

import jakarta.annotation.Nonnull;
import java.util.List;

import java.util.Objects;

public class Cve {

private String id;

@Nonnull
private String lastModified;

@Nonnull
private String data;

public Cve() {
}

public Cve(String id, @Nonnull String lastModified, @Nonnull String data) {
this.id = id;
this.lastModified = lastModified;
this.data = data;
}

public String getId() {
return id;
}

@Nonnull
public String getLastModified() {
return lastModified;
}

@Nonnull
public String getData() {
return data;
}

@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;

Cve Cve = (Cve) o;
return Objects.equals(id, Cve.id) && lastModified.equals(Cve.lastModified) && data.equals(Cve.data);
}

@Override
public int hashCode() {
int result = Objects.hashCode(id);
result = 31 * result + lastModified.hashCode();
result = 31 * result + data.hashCode();
return result;
}
public record Cve(String id, String lastModified, String sourceIdentifier, String published, String vulnStatus,
List<Description> descriptions, Object metrics, List<Reference> references, List<Weakness> weaknesses,
List<Configuration> configurations) {

}

5 changes: 5 additions & 0 deletions src/main/java/io/gardenlinux/glvd/dto/Deb.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package io.gardenlinux.glvd.dto;

public record Deb(String versionLatest, String versionEndExcluding, String cvssSeverity) {

}
4 changes: 4 additions & 0 deletions src/main/java/io/gardenlinux/glvd/dto/Description.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package io.gardenlinux.glvd.dto;

public record Description(String lang, String value) {
}
7 changes: 7 additions & 0 deletions src/main/java/io/gardenlinux/glvd/dto/Node.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.gardenlinux.glvd.dto;

import java.util.List;

public record Node(List<CpeMatch> cpeMatch, boolean negate, String operator) {

}
30 changes: 1 addition & 29 deletions src/main/java/io/gardenlinux/glvd/dto/Readiness.java
Original file line number Diff line number Diff line change
@@ -1,33 +1,5 @@
package io.gardenlinux.glvd.dto;

import java.util.Objects;

public class Readiness {

private final String dbCheck;

public Readiness(String dbCheck) {
this.dbCheck = dbCheck;
}

public String getDbCheck() {
return dbCheck;
}

@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;

Readiness readiness = (Readiness) o;
return Objects.equals(dbCheck, readiness.dbCheck);
}

@Override
public int hashCode() {
return Objects.hashCode(dbCheck);
}
public record Readiness(String dbCheck) {

}
7 changes: 7 additions & 0 deletions src/main/java/io/gardenlinux/glvd/dto/Reference.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.gardenlinux.glvd.dto;

import java.util.List;

public record Reference(String url, String source, List<String> tags) {

}
7 changes: 7 additions & 0 deletions src/main/java/io/gardenlinux/glvd/dto/Weakness.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.gardenlinux.glvd.dto;

import java.util.List;

public record Weakness(String source, String type, List<Description> description) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.gardenlinux.glvd.exceptions;

public class CantParseJSONException extends RuntimeException{

public CantParseJSONException(String message) {
super(message);
}
}
2 changes: 1 addition & 1 deletion src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ spring.datasource.url=jdbc:postgresql://localhost:5432/glvd
spring.datasource.username=glvd
spring.datasource.password=glvd
spring.sql.init.mode=never
spring.jpa.properties.javax.persistence.query.timeout=5000
jakarta.persistence.query.timeout=5000

0 comments on commit b29d6a8

Please sign in to comment.