Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,6 @@ out/

### Unbase OCI ###
*.oci
glvd.sql

# DB Dump for DevDb container image
/glvd.sql
3 changes: 3 additions & 0 deletions DevDb.Containerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM ghcr.io/gardenlinux/glvd-postgres:latest

COPY glvd.sql /docker-entrypoint-initdb.d/glvd.sql
14 changes: 10 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,26 +32,32 @@ To build the app, ensure the test database is running:

## Running the Application Locally

1. Start the application database:
1. Get a dump of the Database (this needs the GitHub `gh` cli and `jq`)

```bash
./download-db-dump.sh
```

2. Start the application database:

```bash
./start-db-for-app.sh
```

2. Build and run the Spring Boot app:
3. Build and run the Spring Boot app:

```bash
./gradlew bootRun
```

3. After startup, check readiness:
4. After startup, check readiness:

```
curl http://localhost:8080/readiness
# Should return status code 200
```

4. Open http://localhost:8080 in your web browser to use the UI
5. Open http://localhost:8080 in your web browser to use the UI

## Example Requests

Expand Down
4 changes: 4 additions & 0 deletions download-db-dump.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash

LATEST_RUN_ID=$(gh run list --repo gardenlinux/glvd-data-ingestion --branch main --workflow 02-ingest-dump-snapshot.yaml --json databaseId --limit 1 | jq -r '.[0].databaseId')
gh run download $LATEST_RUN_ID -n glvd.sql --repo gardenlinux/glvd-data-ingestion
19 changes: 19 additions & 0 deletions src/docs/asciidoc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,25 @@ Example response:

include::{snippets}/getCveForDistro/http-response.adoc[]

=== List CVEs by Image

Retrieve all CVEs for a given Garden Linux image and version.
This applies a filter for the packages in the specified image.

Supported images are currently:

- `ali-gardener_prod`
- `aws-gardener_prod`
- `azure-gardener_prod`
- `gcp-gardener_prod`
- `openstack-gardener_prod`

include::{snippets}/getCveForImage/curl-request.adoc[]

Example response:

include::{snippets}/getCveForImage/http-response.adoc[]

=== List CVEs for Packages by Distribution

Retrieve all CVEs for a list of packages in a specified distribution.
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/io/gardenlinux/glvd/GlvdController.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,20 @@ gardenlinuxVersion, new SortAndPageOptions(sortBy, sortOrder, pageNumber, pageSi
);
}

@GetMapping("/cves/{gardenlinuxVersion}/image/{gardenlinuxImage}")
ResponseEntity<List<ImageSourcePackageCve>> getCveImage(
@PathVariable final String gardenlinuxVersion,
@PathVariable final String gardenlinuxImage,
@RequestParam(defaultValue = "cveId") final String sortBy,
@RequestParam(defaultValue = "ASC") final String sortOrder,
@RequestParam(required = false) final String pageNumber,
@RequestParam(required = false) final String pageSize
) {
return ResponseEntity.ok().body(glvdService.getCveForImage(
gardenlinuxImage, gardenlinuxVersion, new SortAndPageOptions(sortBy, sortOrder, pageNumber, pageSize))
);
}

@GetMapping("/cves/{gardenlinuxVersion}/packages/{packageList}")
ResponseEntity<List<SourcePackageCve>> getCvePackages(
@PathVariable final String gardenlinuxVersion,
Expand Down
27 changes: 26 additions & 1 deletion src/main/java/io/gardenlinux/glvd/GlvdService.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ public class GlvdService {
@Nonnull
private final SourcePackageRepository sourcePackageRepository;

@Nonnull
private final ImageSourcePackageCveRepository imageSourcePackageCveRepository;

@Nonnull
private final CveDetailsRepository cveDetailsRepository;

Expand Down Expand Up @@ -62,9 +65,10 @@ public class GlvdService {

Logger logger = LoggerFactory.getLogger(GlvdService.class);

public GlvdService(@Nonnull SourcePackageCveRepository sourcePackageCveRepository, @Nonnull SourcePackageRepository sourcePackageRepository, @Nonnull CveDetailsRepository cveDetailsRepository, @Nonnull CveContextRepository cveContextRepository, @Nonnull DistCpeRepository distCpeRepository, @Nonnull NvdExclusiveCveRepository nvdExclusiveCveRepository, @Nonnull DebSrcRepository debSrcRepository, @Nonnull KernelCveRepository kernelCveRepository, @Nonnull KernelCveDetailsRepository kernelCveDetailsRepository, @Nonnull NvdCveRepository nvdCveRepository, @Nonnull TriageRepository triageRepository) {
public GlvdService(@Nonnull SourcePackageCveRepository sourcePackageCveRepository, @Nonnull SourcePackageRepository sourcePackageRepository, @Nonnull ImageSourcePackageCveRepository imageSourcePackageCveRepository, @Nonnull CveDetailsRepository cveDetailsRepository, @Nonnull CveContextRepository cveContextRepository, @Nonnull DistCpeRepository distCpeRepository, @Nonnull NvdExclusiveCveRepository nvdExclusiveCveRepository, @Nonnull DebSrcRepository debSrcRepository, @Nonnull KernelCveRepository kernelCveRepository, @Nonnull KernelCveDetailsRepository kernelCveDetailsRepository, @Nonnull NvdCveRepository nvdCveRepository, @Nonnull TriageRepository triageRepository) {
this.sourcePackageCveRepository = sourcePackageCveRepository;
this.sourcePackageRepository = sourcePackageRepository;
this.imageSourcePackageCveRepository = imageSourcePackageCveRepository;
this.cveDetailsRepository = cveDetailsRepository;
this.cveContextRepository = cveContextRepository;
this.distCpeRepository = distCpeRepository;
Expand Down Expand Up @@ -108,6 +112,22 @@ private Pageable determinePageAndSortFeatures2(SortAndPageOptions sortAndPageOpt
return Pageable.unpaged();
}

public List<ImageSourcePackageCve> getCveForImage(String image, String gardenlinuxVersion, SortAndPageOptions sortAndPageOptions) {
var cvesExcludingKernel = imageSourcePackageCveRepository.findByGardenlinuxVersionAndGardenlinuxImageName(
gardenlinuxVersion, image, determinePageAndSortFeatures(sortAndPageOptions))
.stream()
.filter(CvesByStatusRejectedxx())
.toList();

var kernelCves = kernelCveRepository.findByGardenlinuxVersion(gardenlinuxVersion)
.stream()
.map(kernelCve -> new ImageSourcePackageCve(kernelCve.getCveId(), kernelCve.getSourcePackageName(), kernelCve.getSourcePackageVersion(), kernelCve.getGardenlinuxVersion(), "", "", "", kernelCve.isVulnerable(), kernelCve.getCvePublishedDate(), kernelCve.getCveLastModifiedDate(), kernelCve.getCveLastIngestedDate(), kernelCve.getVulnStatus(), kernelCve.getBaseScore(), kernelCve.getVectorString(), kernelCve.getBaseScoreV40(), kernelCve.getBaseScoreV31(), kernelCve.getBaseScoreV30(), kernelCve.getBaseScoreV2(), kernelCve.getVectorStringV40(), kernelCve.getVectorStringV31(), kernelCve.getVectorStringV30(), kernelCve.getVectorStringV2()))
.filter(CvesByStatusRejectedxx())
.toList();

return Stream.concat(cvesExcludingKernel.stream(), kernelCves.stream()).toList();
}

public List<SourcePackageCve> getCveForDistribution(String gardenlinuxVersion, SortAndPageOptions sortAndPageOptions) {
var cvesExcludingKernel = sourcePackageCveRepository.findByGardenlinuxVersion(
gardenlinuxVersion, determinePageAndSortFeatures(sortAndPageOptions))
Expand All @@ -128,6 +148,11 @@ private static Predicate<SourcePackageCve> CvesByStatusRejected() {
return cve -> !cve.getVulnStatus().equalsIgnoreCase("Rejected");
}

// fixme
private static Predicate<ImageSourcePackageCve> CvesByStatusRejectedxx() {
return cve -> !cve.getVulnStatus().equalsIgnoreCase("Rejected");
}

public List<KernelCve> kernelCvesForGardenLinuxVersion(String gardenlinuxVersion) {
return kernelCveRepository.findByGardenlinuxVersion(gardenlinuxVersion);
}
Expand Down
28 changes: 28 additions & 0 deletions src/main/java/io/gardenlinux/glvd/UiController.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.gardenlinux.glvd;

import io.gardenlinux.glvd.db.ImageSourcePackageCve;
import io.gardenlinux.glvd.db.SourcePackageCve;
import io.gardenlinux.glvd.exceptions.CveNotKnownException;
import jakarta.annotation.Nonnull;
Expand Down Expand Up @@ -39,6 +40,33 @@ gardenlinuxVersion, new SortAndPageOptions(sortBy, sortOrder, pageNumber, pageSi
return "getPackagesForDistro";
}

@GetMapping("/getCveForImage")
public String getCveForImage(
@RequestParam(name = "gardenlinuxVersion", required = true) String gardenlinuxVersion,
@RequestParam(name = "imageName", required = true) String imageName,
@RequestParam(defaultValue = "baseScore") final String sortBy,
@RequestParam(defaultValue = "DESC") final String sortOrder,
@RequestParam(required = false) final String pageNumber,
@RequestParam(required = false) final String pageSize,
@RequestParam(required = false, defaultValue = "true") final boolean onlyVulnerable,
Model model
) {
var sourcePackageCves = glvdService.getCveForImage(
imageName, gardenlinuxVersion, new SortAndPageOptions(sortBy, sortOrder, pageNumber, pageSize)
)
.stream()
.filter(ImageSourcePackageCve::isVulnerable)
.filter(sourcePackageCve -> !sourcePackageCve.getVulnStatus().equalsIgnoreCase("Rejected"))
.toList();
var contexts = glvdService.getCveContextsForDist(glvdService.distVersionToId(gardenlinuxVersion));
model.addAttribute("sourcePackageCves", sourcePackageCves);
model.addAttribute("gardenlinuxVersion", gardenlinuxVersion);
model.addAttribute("imageName", imageName);
model.addAttribute("onlyVulnerable", onlyVulnerable);
model.addAttribute("cveContexts", contexts);
return "getCveForImage";
}

@GetMapping("/getCveForDistribution")
public String getCveForDistribution(
@RequestParam(name = "gardenlinuxVersion", required = true) String gardenlinuxVersion,
Expand Down
194 changes: 194 additions & 0 deletions src/main/java/io/gardenlinux/glvd/db/ImageSourcePackageCve.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
package io.gardenlinux.glvd.db;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;

@Entity
@Table(name = "imagesourcepackagecve")
public class ImageSourcePackageCve {

@Id
@Column(name = "cve_id", nullable = false)
private String cveId;

@Column(name = "source_package_name", nullable = false)
private String sourcePackageName;

@Column(name = "source_package_version", nullable = false)
private String sourcePackageVersion;

@Column(name = "gardenlinux_version", nullable = false)
private String gardenlinuxVersion;

@Column(name = "gardenlinux_image_name", nullable = false)
private String gardenlinuxImageName;

@Column(name = "gardenlinux_image_version", nullable = false)
private String gardenlinuxImageVersion;

@Column(name = "gardenlinux_image_commit_id", nullable = false)
private String gardenlinuxImageCommitId;

@Column(name = "is_vulnerable", nullable = false)
private boolean isVulnerable;

@Column(name = "cve_published_date", nullable = false)
private String cvePublishedDate;

@Column(name = "cve_last_modified_date", nullable = false)
private String cveLastModifiedDate;

@Column(name = "cve_last_ingested_date", nullable = false)
private String cveLastIngestedDate;

@Column(name = "vuln_status", nullable = false)
private String vulnStatus;

@Column(name = "base_score", nullable = true)
private Float baseScore;

@Column(name = "vector_string", nullable = true)
private String vectorString;

@Column(name = "base_score_v40", nullable = true)
private Float baseScoreV40;

@Column(name = "base_score_v31", nullable = true)
private Float baseScoreV31;

@Column(name = "base_score_v30", nullable = true)
private Float baseScoreV30;

@Column(name = "base_score_v2", nullable = true)
private Float baseScoreV2;

@Column(name = "vector_string_v40", nullable = true)
private String vectorStringV40;

@Column(name = "vector_string_v31", nullable = true)
private String vectorStringV31;

@Column(name = "vector_string_v30", nullable = true)
private String vectorStringV30;

@Column(name = "vector_string_v2", nullable = true)
private String vectorStringV2;

public ImageSourcePackageCve() {
}

public ImageSourcePackageCve(String cveId, String sourcePackageName, String sourcePackageVersion, String gardenlinuxVersion, String gardenlinuxImageName, String gardenlinuxImageVersion, String gardenlinuxImageCommitId, boolean isVulnerable, String cvePublishedDate, String cveLastModifiedDate, String cveLastIngestedDate, String vulnStatus, Float baseScore, String vectorString, Float baseScoreV40, Float baseScoreV31, Float baseScoreV30, Float baseScoreV2, String vectorStringV40, String vectorStringV31, String vectorStringV30, String vectorStringV2) {
this.cveId = cveId;
this.sourcePackageName = sourcePackageName;
this.sourcePackageVersion = sourcePackageVersion;
this.gardenlinuxVersion = gardenlinuxVersion;
this.gardenlinuxImageName = gardenlinuxImageName;
this.gardenlinuxImageVersion = gardenlinuxImageVersion;
this.gardenlinuxImageCommitId = gardenlinuxImageCommitId;
this.isVulnerable = isVulnerable;
this.cvePublishedDate = cvePublishedDate;
this.cveLastModifiedDate = cveLastModifiedDate;
this.cveLastIngestedDate = cveLastIngestedDate;
this.vulnStatus = vulnStatus;
this.baseScore = baseScore;
this.vectorString = vectorString;
this.baseScoreV40 = baseScoreV40;
this.baseScoreV31 = baseScoreV31;
this.baseScoreV30 = baseScoreV30;
this.baseScoreV2 = baseScoreV2;
this.vectorStringV40 = vectorStringV40;
this.vectorStringV31 = vectorStringV31;
this.vectorStringV30 = vectorStringV30;
this.vectorStringV2 = vectorStringV2;
}

public String getCveId() {
return cveId;
}

public String getSourcePackageName() {
return sourcePackageName;
}

public String getSourcePackageVersion() {
return sourcePackageVersion;
}

public String getGardenlinuxVersion() {
return gardenlinuxVersion;
}

public String getGardenlinuxImageName() {
return gardenlinuxImageName;
}

public String getGardenlinuxImageVersion() {
return gardenlinuxImageVersion;
}

public String getGardenlinuxImageCommitId() {
return gardenlinuxImageCommitId;
}

public boolean isVulnerable() {
return isVulnerable;
}

public String getCvePublishedDate() {
return cvePublishedDate;
}

public String getCveLastModifiedDate() {
return cveLastModifiedDate;
}

public String getCveLastIngestedDate() {
return cveLastIngestedDate;
}

public String getVulnStatus() {
return vulnStatus;
}

public Float getBaseScore() {
return baseScore;
}

public String getVectorString() {
return vectorString;
}

public Float getBaseScoreV40() {
return baseScoreV40;
}

public Float getBaseScoreV31() {
return baseScoreV31;
}

public Float getBaseScoreV30() {
return baseScoreV30;
}

public Float getBaseScoreV2() {
return baseScoreV2;
}

public String getVectorStringV40() {
return vectorStringV40;
}

public String getVectorStringV31() {
return vectorStringV31;
}

public String getVectorStringV30() {
return vectorStringV30;
}

public String getVectorStringV2() {
return vectorStringV2;
}
}
Loading