Skip to content

Commit

Permalink
WIP - Arch Linux Tracker to collect vulnerabilities
Browse files Browse the repository at this point in the history
  • Loading branch information
santhosh1729 committed May 26, 2021
1 parent 668f12a commit 0c27dc5
Show file tree
Hide file tree
Showing 6 changed files with 225 additions and 0 deletions.
79 changes: 79 additions & 0 deletions arch-linux/archlinux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package arch_linux

import (
"encoding/json"
"fmt"
"log"
"os"
"path/filepath"

"github.com/aquasecurity/vuln-list-update/utils"
"golang.org/x/xerrors"
pb "gopkg.in/cheggaaa/pb.v1"
)

const (
archLinuxDir = "arch-linux"
securityTrackerURL = "https://security.archlinux.org/json"
retry = 3
)

type ArchLinuxConfig struct {
URL string
VulnListDir string
Retry int
}

func NewArchLinuxConfig() ArchLinuxConfig {
return NewArchLinuxWithConfig(securityTrackerURL, filepath.Join(utils.VulnListDir(), archLinuxDir), 5)
}

func NewArchLinuxWithConfig(url, path string, retryTimes int) ArchLinuxConfig {
return ArchLinuxConfig{
URL: url,
VulnListDir: path,
Retry: retryTimes,
}
}

func (alc ArchLinuxConfig) Update() error {
log.Println("Fetching Arch Linux data...")
vulns, err := alc.retrieveArchLinuxCveDetails()
if err != nil {
return xerrors.Errorf("failed to retrieve Arch Linux CVE details: %w", err)
}

log.Println("Removing old data...")
if err = os.RemoveAll(alc.VulnListDir); err != nil {
return xerrors.Errorf("failed to remove Arch Linux dir: %w", err)
}

// Save all JSON files
log.Println("Saving new data...")
bar := pb.StartNew(len(vulns))
for _, cves := range vulns {
dir := filepath.Join(alc.VulnListDir)
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
return xerrors.Errorf("failed to create the directory: %w", err)
}
filePath := filepath.Join(dir, fmt.Sprintf("%s.json", cves.Name))
if err = utils.Write(filePath, cves); err != nil {
return xerrors.Errorf("failed to write Debian CVE details: %w", err)
}
bar.Increment()
}
bar.Finish()
return nil
}

func (alc ArchLinuxConfig) retrieveArchLinuxCveDetails() (vulns ArchLinuxCVE, err error) {
cveJSON, err := utils.FetchURL(alc.URL, "", alc.Retry)
if err != nil {
return vulns, xerrors.Errorf("failed to fetch cve data from Arch Linux. err: %w", err)
}

if err = json.Unmarshal(cveJSON, &vulns); err != nil {
return vulns, xerrors.Errorf("error in unmarshal json: %w", err)
}
return vulns, nil
}
77 changes: 77 additions & 0 deletions arch-linux/archlinux_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package arch_linux

import (
"io"
"io/ioutil"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"testing"

"github.com/stretchr/testify/require"

"github.com/stretchr/testify/assert"
)

func TestUpdate(t *testing.T) {
testCases := []struct {
name string
inputJSONFile string
expectedOutputJSONFile string
expectedError string
ArchLinuxServerUrl string
}{
{
name: "happy path",
inputJSONFile: "testdata/archlinux.json",
expectedOutputJSONFile: "testdata/AVG-4.json",
},
{
name: "sad path, unreachable Arch Linux service",
expectedError: "failed to retrieve Arch Linux CVE details",
ArchLinuxServerUrl: "http://foo/bar/baz",
},
{
name: "sad path, invalid json",
inputJSONFile: "testdata/invalid.json",
expectedError: "failed to retrieve Arch Linux CVE details",
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
var ArchLinuxURL string
if tc.ArchLinuxServerUrl != "" {
ArchLinuxURL = tc.ArchLinuxServerUrl
} else {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
b, _ := ioutil.ReadFile(tc.inputJSONFile)
_, _ = io.WriteString(w, string(b))
}))
ArchLinuxURL = ts.URL
defer func() {
ts.Close()
}()
}

dir, _ := ioutil.TempDir("", "TestUpdate-*")
defer func() {
_ = os.RemoveAll(dir)
}()

c := NewArchLinuxWithConfig(ArchLinuxURL, filepath.Join(dir), 0)
err := c.Update()
switch {
case tc.expectedError != "":
require.Error(t, err, tc.name)
default:
gotJSON, err := ioutil.ReadFile(filepath.Join(dir, "AVG-4.json"))
require.NoError(t, err, tc.name)

wantJSON, _ := ioutil.ReadFile(tc.expectedOutputJSONFile)
assert.JSONEq(t, string(wantJSON), string(gotJSON), tc.name)
}
})
}
}
17 changes: 17 additions & 0 deletions arch-linux/testdata/AVG-4.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name":"AVG-4",
"packages":[
"bzip2"
],
"status":"Fixed",
"severity":"Low",
"type":"denial of service",
"affected":"1.0.6-5",
"fixed":"1.0.6-6",
"issues":[
"CVE-2016-3189"
],
"advisories":[
"ASA-201702-19"
]
}
38 changes: 38 additions & 0 deletions arch-linux/testdata/archlinux.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
[
{
"name":"AVG-20",
"packages":[
"curl"
],
"status":"Fixed",
"severity":"Low",
"type":"denial of service",
"affected":"7.50.2-1",
"fixed":"7.50.3-1",
"ticket":null,
"issues":[
"CVE-2016-7167"
],
"advisories":[
"ASA-201609-19"
]
},
{
"name":"AVG-4",
"packages":[
"bzip2"
],
"status":"Fixed",
"severity":"Low",
"type":"denial of service",
"affected":"1.0.6-5",
"fixed":"1.0.6-6",
"ticket":null,
"issues":[
"CVE-2016-3189"
],
"advisories":[
"ASA-201702-19"
]
}
]
1 change: 1 addition & 0 deletions arch-linux/testdata/invalid.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
invalid json
13 changes: 13 additions & 0 deletions arch-linux/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package arch_linux

type ArchLinuxCVE []struct {
Name string `json:"name"`
Packages []string `json:"packages"`
Status string `json:"status"`
Severity string `json:"severity"`
Type string `json:"type"`
Affected string `json:"affected"`
Fixed string `json:"fixed"`
Issues []string `json:"issues"`
Advisories []string `json:"advisories"`
}

0 comments on commit 0c27dc5

Please sign in to comment.