Skip to content

Commit

Permalink
Merge pull request #6 from cintek/csaf_searcher
Browse files Browse the repository at this point in the history
Add new binary, the searcher(, the main and docs) from https://github.com/cintek/csaf_advisory_example
  • Loading branch information
cintek authored Oct 18, 2023
2 parents c05a402 + d9e5792 commit 0b5c7a2
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 0 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ Can be used for automated forwarding of CSAF documents.
### [csaf_validator](docs/csaf_validator.md)
is a tool to validate local advisories files against the JSON Schema and an optional remote validator.

### [csaf_searcher](docs/csaf_searcher.md)
is a tool to search through local advisories. It finds PURLs based on the product ID of an advisory.

## Tools for advisory providers

### [csaf_provider](docs/csaf_provider.md)
Expand Down
126 changes: 126 additions & 0 deletions cmd/csaf_searcher/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// Package main implements a simple demo program to
// work with the csaf_distribution library.
package main

import (
"flag"
"fmt"
"log"
"os"
"slices"
"strings"

"github.com/csaf-poc/csaf_distribution/v2/csaf"
)

func main() {
flag.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(),
"Usage:\n %s [OPTIONS] files...\n\nOptions:\n", os.Args[0])
flag.PrintDefaults()
}
idsString := flag.String("p", "", "ID1,ID2,...")
flag.Parse()

files := flag.Args()
if len(files) == 0 {
log.Println("No files given.")
return
}
if err := run(files, *idsString); err != nil {
log.Fatalf("error: %v\n", err)
}
}

// run prints PURLs belonging to the given Product IDs.
func run(files []string, ids string) error {

uf := newURLFinder(strings.Split(ids, ","))

for _, file := range files {
adv, err := csaf.LoadAdvisory(file)
if err != nil {
return fmt.Errorf("loading %q failed: %w", file, err)
}
uf.findURLs(adv)
uf.dumpURLs()
uf.clear()
}

return nil
}

// urlFinder helps to find the URLs of a set of product ids in advisories.
type urlFinder struct {
ids []csaf.ProductID
urls [][]csaf.PURL
}

// newURLFinder creates a new urlFinder for given ids.
func newURLFinder(ids []string) *urlFinder {
uf := &urlFinder{
ids: make([]csaf.ProductID, len(ids)),
urls: make([][]csaf.PURL, len(ids)),
}
for i := range uf.ids {
uf.ids[i] = csaf.ProductID(ids[i])
}
return uf
}

// clear resets the url finder after a run on an advisory.
func (uf *urlFinder) clear() {
clear(uf.urls)
}

// dumpURLs dumps the found URLs to stdout.
func (uf *urlFinder) dumpURLs() {
for i, urls := range uf.urls {
if len(urls) == 0 {
continue
}
fmt.Printf("Found URLs for %s:\n", uf.ids[i])
for j, url := range urls {
fmt.Printf("%d. %s\n", j+1, url)
}
}
}

// findURLs find the URLs in an advisory.
func (uf *urlFinder) findURLs(adv *csaf.Advisory) {
tree := adv.ProductTree
if tree == nil {
return
}

// If we have found it and we have a valid URL add unique.
add := func(idx int, h *csaf.ProductIdentificationHelper) {
if idx != -1 && h != nil && h.PURL != nil &&
!slices.Contains(uf.urls[idx], *h.PURL) {
uf.urls[idx] = append(uf.urls[idx], *h.PURL)
}
}

// First iterate over full product names.
if names := tree.FullProductNames; names != nil {
for _, name := range *names {
if name != nil && name.ProductID != nil {
add(slices.Index(uf.ids, *name.ProductID), name.ProductIdentificationHelper)
}
}
}

// Second traverse the branches recursively.
var recBranch func(*csaf.Branch)
recBranch = func(b *csaf.Branch) {
if p := b.Product; p != nil && p.ProductID != nil {
add(slices.Index(uf.ids, *p.ProductID), p.ProductIdentificationHelper)
}
for _, c := range b.Branches {
recBranch(c)
}
}
for _, b := range tree.Branches {
recBranch(b)
}
}
16 changes: 16 additions & 0 deletions docs/csaf_searcher.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# csaf_advisory_example

This is a small searcher using the advisory model to search for PURLs belonging to a product ID in an advisory of the CSAF 2.0 standard.

Usage:
```
csaf_advisory_example OPTIONS [files...]
Application Options:
-p The Product ID
Help Options:
-h, --help Show a help message
```

0 comments on commit 0b5c7a2

Please sign in to comment.