forked from aquasecurity/vuln-list-update
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-Authored-By: stefan <[email protected]>
- Loading branch information
Showing
13 changed files
with
458 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
package alt | ||
|
||
import ( | ||
"archive/zip" | ||
"bytes" | ||
"encoding/json" | ||
"encoding/xml" | ||
"fmt" | ||
"io" | ||
"log" | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
|
||
"github.com/cheggaaa/pb/v3" | ||
"github.com/spf13/afero" | ||
"golang.org/x/xerrors" | ||
|
||
"github.com/aquasecurity/vuln-list-update/utils" | ||
) | ||
|
||
const ( | ||
altDir = "oval" | ||
|
||
branchURL = "https://rdb.altlinux.org/api/errata/export/oval/%s" | ||
branchListURL = "https://rdb.altlinux.org/api/errata/export/oval/branches" | ||
|
||
retry = 5 | ||
) | ||
|
||
type Config struct { | ||
VulnListDir string | ||
BranchURL string | ||
BranchListURL string | ||
AppFs afero.Fs | ||
Retry int | ||
} | ||
|
||
func NewConfig() Config { | ||
return Config{ | ||
VulnListDir: utils.VulnListDir(), | ||
BranchURL: branchURL, | ||
BranchListURL: branchListURL, | ||
AppFs: afero.NewOsFs(), | ||
Retry: retry, | ||
} | ||
} | ||
|
||
type BranchList struct { | ||
Length int | ||
Branches []string | ||
} | ||
|
||
func (c Config) Update() error { | ||
dirPath := filepath.Join(c.VulnListDir, altDir) | ||
log.Printf("Remove ALT's OVAL directoty: %s", dirPath) | ||
if err := os.RemoveAll(dirPath); err != nil { | ||
return xerrors.Errorf("failed to remove ALT's OVAL directory: %w", err) | ||
} | ||
|
||
log.Println("Fetching ALT's OVAL branch list...") | ||
branchList, err := c.fetchBranchList() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
for _, branch := range branchList.Branches { | ||
log.Printf("Fetching ALT's OVAL branch: %s", branch) | ||
if err := c.updateOVAL(branch); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (c Config) fetchBranchList() (BranchList, error) { | ||
resp, err := utils.FetchURL(c.BranchListURL, "", c.Retry) | ||
if err != nil { | ||
return BranchList{}, xerrors.Errorf("failed to get ALT's OVAL branch list: %w", err) | ||
} | ||
|
||
var branchList BranchList | ||
if err := json.Unmarshal(resp, &branchList); err != nil { | ||
return BranchList{}, xerrors.Errorf("failed to unmarshal branch list JSON response: %w", err) | ||
} | ||
|
||
return branchList, nil | ||
} | ||
|
||
func (c Config) updateOVAL(branch string) error { | ||
ovalURL := fmt.Sprintf(c.BranchURL, branch) | ||
|
||
resp, err := utils.FetchURL(ovalURL, "", c.Retry) | ||
if err != nil { | ||
return xerrors.Errorf("failed to get ALT's OVAL branch archive: %w", err) | ||
} | ||
|
||
reader, err := zip.NewReader(bytes.NewReader(resp), int64(len(resp))) | ||
if err != nil { | ||
return xerrors.Errorf("failed to init zip reader: %w", err) | ||
} | ||
|
||
pbar := pb.StartNew(len(reader.File)) | ||
for _, file := range reader.File { | ||
var oval OVALDefinitions | ||
rc, err := file.Open() | ||
if err != nil { | ||
return xerrors.Errorf("failed to open file: %w", err) | ||
} | ||
content, err := io.ReadAll(rc) | ||
if err != nil { | ||
rc.Close() | ||
return xerrors.Errorf("failed to read file content: %w", err) | ||
} | ||
|
||
err = xml.Unmarshal(content, &oval) | ||
if err != nil { | ||
rc.Close() | ||
return xerrors.Errorf("failed to unmarshal ALT's OVAL xml: %w", err) | ||
} | ||
|
||
ovalName := strings.TrimSuffix(file.Name, ".xml") | ||
ovalPath := filepath.Join(c.VulnListDir, altDir, branch, ovalName) | ||
|
||
if err := utils.WriteJSON(c.AppFs, ovalPath, "tests.json", oval.Tests); err != nil { | ||
rc.Close() | ||
return xerrors.Errorf("failed to write tests.json: %w", err) | ||
} | ||
|
||
if err := utils.WriteJSON(c.AppFs, ovalPath, "objects.json", oval.Objects); err != nil { | ||
rc.Close() | ||
return xerrors.Errorf("failed to write objects.json: %w", err) | ||
} | ||
|
||
if err = utils.WriteJSON(c.AppFs, ovalPath, "states.json", oval.States); err != nil { | ||
rc.Close() | ||
return xerrors.Errorf("failed to write states: %w", err) | ||
} | ||
|
||
if err = utils.WriteJSON(c.AppFs, ovalPath, "definitions.json", oval.Definitions); err != nil { | ||
rc.Close() | ||
return xerrors.Errorf("failed to write definitions: %w", err) | ||
} | ||
|
||
pbar.Increment() | ||
rc.Close() | ||
} | ||
|
||
pbar.Finish() | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package alt | ||
|
||
import ( | ||
"net/http" | ||
"net/http/httptest" | ||
"testing" | ||
|
||
"github.com/spf13/afero" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestConfig_Update(t *testing.T) { | ||
testCases := []struct { | ||
name string | ||
dir string | ||
wantFiles int | ||
wantErr string | ||
}{ | ||
{ | ||
name: "happy path", | ||
dir: "testdata/happy", | ||
}, | ||
{ | ||
name: "404", | ||
dir: "testdata/missing-oval", | ||
wantErr: "failed to get ALT's OVAL branch archive: failed to fetch URL: HTTP error. status code: 404, url:", | ||
}, | ||
{ | ||
name: "broken XML", | ||
dir: "testdata/broken", | ||
wantErr: "failed to unmarshal ALT's OVAL xml: XML syntax error on line 4: element <cpe> closed by </cp>", | ||
}, | ||
} | ||
for _, tc := range testCases { | ||
t.Run(tc.name, func(t *testing.T) { | ||
ts := httptest.NewServer(http.FileServer(http.Dir(tc.dir))) | ||
defer ts.Close() | ||
|
||
tmpDir := "/tmp" // It is a virtual filesystem of afero. | ||
appFs := afero.NewMemMapFs() | ||
c := Config{ | ||
VulnListDir: tmpDir, | ||
BranchURL: ts.URL + "/%s/oval_definitions.zip", | ||
BranchListURL: ts.URL + "/branches.json", | ||
AppFs: appFs, | ||
Retry: 0, | ||
} | ||
|
||
err := c.Update() | ||
if tc.wantErr != "" { | ||
require.Error(t, err) | ||
assert.Contains(t, err.Error(), tc.wantErr) | ||
return | ||
} | ||
|
||
require.NoError(t, err, tc.name) | ||
assert.NoError(t, err, tc.name) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{"length": 3, "branches": ["p9", "p10", "c9f2"]} |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{"length": 3, "branches": ["p9", "p10", "c9f2"]} |
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{"length": 3, "branches": ["p9", "p10", "c9f2"]} |
Oops, something went wrong.