Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Retrieve open CVE for my system #1

Merged
merged 8 commits into from
Sep 20, 2024
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
18 changes: 18 additions & 0 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,21 @@ jobs:

- name: Test
run: go test -v ./...

- uses: actions/upload-artifact@v4
with:
name: glvd-client
path: glvd-client

run_in_gl:
runs-on: ubuntu-latest
container: ghcr.io/gardenlinux/gardenlinux:1592.1
needs:
- build
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
- run: cat /etc/os-release
- run: ls -lR
- run: chmod +x glvd-client/glvd-client
- run: ./glvd-client/glvd-client
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
*.so
*.dylib

glvd-client

# Test binary, built with `go test -c`
*.test

Expand Down
144 changes: 142 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,147 @@
package main

import "fmt"
import (
"bytes"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"os"
"slices"
"strings"
)

type sourcePackageCve struct {
CveId string `json:"cveId"`
BaseScore float32 `json:"baseScore"`
VectorString string `json:"vectorString"`
SourcePackageName string `json:"sourcePackageName"`
SourcePackageVersion string `json:"sourcePackageVersion"`
GardenlinuxVersion string `json:"gardenlinuxVersion"`
IsVulnerable bool `json:"isVulnerable"`
CvePublishedDate string `json:"cvePublishedDate"`
}

type dpkgPackage struct {
Package string
Status string
Source string
}

func buildDpkgStructure(dpkgStatusFileContents string) []dpkgPackage {
var packages []dpkgPackage

lines := strings.Split(dpkgStatusFileContents, "\n")

for _, line := range lines {
if strings.HasPrefix(line, "Package: ") {
pkg := strings.Replace(line, "Package: ", "", 1)
packages = append(packages, dpkgPackage{Package: pkg})
}

if strings.HasPrefix(line, "Status: ") {
packages[len(packages)-1].Status = strings.Replace(line, "Status: ", "", 1)
}

if strings.HasPrefix(line, "Source: ") {
sourcePackageNameWithPotentialVersion := strings.Replace(line, "Source: ", "", 1)
sourcePackageName := removePotentialVersionSuffix(sourcePackageNameWithPotentialVersion)
packages[len(packages)-1].Source = sourcePackageName
}
}

return packages
}

func removePotentialVersionSuffix(input string) string {
return strings.Split(input, " ")[0]
}

func getDpkgSourcePackages(dpkgStatusFilePath string) []string {
dat, err := os.ReadFile(dpkgStatusFilePath)
if err != nil {
log.Fatal(err)
}

packages := buildDpkgStructure(string(dat))

var pkgs []string

for _, pkg := range packages {
if pkg.Status == "install ok installed" {
if len(pkg.Source) > 0 {
pkgs = append(pkgs, pkg.Source)
} else {
pkgs = append(pkgs, pkg.Package)
}
}
}

// De-duplicate entries
slices.Sort(pkgs)
return slices.Compact(pkgs)
}

type payload struct {
PackageNames []string `json:"packageNames"`
}

func getCvesForPackageList(dpkgSourcePackages []string, gardenLinuxVersion string) []sourcePackageCve {
client := &http.Client{}
requestPayload, _ := json.Marshal(payload{PackageNames: dpkgSourcePackages})
req, err := http.NewRequest("PUT", "https://glvd.ingress.glvd.gardnlinux.shoot.canary.k8s-hana.ondemand.com/v1/cves/1592.0/packages?sortBy=cveId&sortOrder=ASC", bytes.NewBuffer(requestPayload))
if err != nil {
log.Fatal(err)
}
req.Header.Set("accept", "application/json")
req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
bodyText, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}

var results []sourcePackageCve
err = json.Unmarshal(bodyText, &results)
if err != nil {
panic(err)
}
return results
}

func readGardenLinuxVersion(osReleaseFilePath string) string {
dat, err := os.ReadFile(osReleaseFilePath)
if err != nil {
log.Fatal(err)
}

lines := strings.Split(string(dat), "\n")
for _, line := range lines {
if strings.HasPrefix("GARDENLINUX_VERSION=", line) {
return strings.Replace(line, "GARDENLINUX_VERSION=", "", 1)
}
}
panic("")
}

func main() {
fmt.Println("Hello World")

// fixme: have a proper setup for running with test data so it can be used on non-Garden Linux hosts for development and testing
dpkgSourcePackages := getDpkgSourcePackages("/var/lib/dpkg/status")
// dpkgSourcePackages := getDpkgSourcePackages("test-data/var-lib-dpkg-status.txt")

gardenLinuxVersion := readGardenLinuxVersion("/etc/os-release")
// gardenLinuxVersion := readGardenLinuxVersion("test-data/etc-os-release.txt")

cves := getCvesForPackageList(dpkgSourcePackages, gardenLinuxVersion)

for _, cve := range cves {
fmt.Printf("%-18s %4.1f %-46s %-20s %-20s\n", cve.CveId, cve.BaseScore, cve.VectorString, cve.SourcePackageName, cve.SourcePackageVersion)
}

}
11 changes: 11 additions & 0 deletions test-data/etc-os-release.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
ID=gardenlinux
NAME="Garden Linux"
PRETTY_NAME="Garden Linux 1592.1"
HOME_URL="https://gardenlinux.io"
SUPPORT_URL="https://github.com/gardenlinux/gardenlinux"
BUG_REPORT_URL="https://github.com/gardenlinux/gardenlinux/issues"
GARDENLINUX_CNAME=container-arm64-1592.1
GARDENLINUX_FEATURES=_slim,base,container
GARDENLINUX_VERSION=1592.1
GARDENLINUX_COMMIT_ID=f269ecdf
GARDENLINUX_COMMIT_ID_LONG=f269ecdf9e0bc0f48f6fde3aeed60786e13dded5
Loading
Loading