mirror of
https://github.com/project-zot/zot.git
synced 2024-12-16 21:56:37 -05:00
cli: add dummy cli for CVE search commands (WIP)
It supports commands for searching CVEs with various params. run "zot search -h" and "zot search cve -h" for commands Does not make any API calls yet.
This commit is contained in:
parent
36efa17915
commit
90a943790c
6 changed files with 227 additions and 1 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -19,4 +19,5 @@ test/data/
|
|||
.idea/
|
||||
coverage.html
|
||||
tags
|
||||
vendor/
|
||||
vendor/
|
||||
.vscode/
|
||||
|
|
|
@ -24,4 +24,5 @@ var (
|
|||
ErrCacheRootBucket = errors.New("cache: unable to create/update root bucket")
|
||||
ErrCacheNoBucket = errors.New("cache: unable to find bucket")
|
||||
ErrCacheMiss = errors.New("cache: miss")
|
||||
ErrInvalidArgs = errors.New("cli: Invalid Arguments")
|
||||
)
|
||||
|
|
79
pkg/cli/cveCmd.go
Normal file
79
pkg/cli/cveCmd.go
Normal file
|
@ -0,0 +1,79 @@
|
|||
package cli
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
zotErrors "github.com/anuvu/zot/errors"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var searchParams = make(map[string]*string)
|
||||
|
||||
func init() {
|
||||
searchCmd.AddCommand(cveCmd)
|
||||
searchCmd.AddCommand(imageCmd)
|
||||
setupFlags()
|
||||
|
||||
cveCmd.SetUsageTemplate(cveCmd.UsageTemplate() + allowedCombinations)
|
||||
}
|
||||
|
||||
var cveCmd = &cobra.Command{
|
||||
Use: "cve",
|
||||
Short: "Find CVEs",
|
||||
Long: `Find CVEs (Common Vulnerabilities and Exposures)`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if cmd.Flags().NFlag() == 0 {
|
||||
cmd.Usage()
|
||||
panic(zotErrors.ErrInvalidArgs) //TODO to panic or not to panic
|
||||
}
|
||||
err := searchCve(searchParams)
|
||||
if err != nil {
|
||||
cmd.PrintErrln(err.Error())
|
||||
cmd.PrintErrln()
|
||||
cmd.Usage()
|
||||
}
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
func setupFlags() {
|
||||
searchParams["imageName"] = cveCmd.Flags().StringP("image-name", "I", "", "Specify image name")
|
||||
searchParams["tag"] = cveCmd.Flags().StringP("tag", "t", "", "Specify tag")
|
||||
searchParams["packageName"] = cveCmd.Flags().StringP("package-name", "p", "", "Specify package name")
|
||||
searchParams["packageVersion"] = cveCmd.Flags().StringP("package-version", "V", "", "Specify package version")
|
||||
searchParams["packageVendor"] = cveCmd.Flags().StringP("package-vendor", "d", "", "Specify package vendor")
|
||||
searchParams["cveID"] = cveCmd.Flags().StringP("cve-id", "i", "", "Find by CVE-ID")
|
||||
searchParams["cveIDForImage"] = imageCmd.Flags().StringP("cve-id", "c", "", "Find by CVE-ID")
|
||||
}
|
||||
|
||||
func searchCve(params map[string]*string) error {
|
||||
foundResults := false
|
||||
for _, searcher := range getSearchers() {
|
||||
results, err := searcher.search(params)
|
||||
if err == nil {
|
||||
foundResults = true
|
||||
fmt.Println(results)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !foundResults {
|
||||
return errors.New("Invalid combination of arguments") // TODO error handling and printing updated help/usage
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var imageCmd = &cobra.Command{
|
||||
Use: "image",
|
||||
Short: "Find images",
|
||||
Long: `Find images`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if cmd.Flags().NFlag() == 0 {
|
||||
cmd.Usage()
|
||||
panic(zotErrors.ErrInvalidArgs)
|
||||
}
|
||||
searchCve(searchParams)
|
||||
},
|
||||
}
|
129
pkg/cli/cveSearchers.go
Normal file
129
pkg/cli/cveSearchers.go
Normal file
|
@ -0,0 +1,129 @@
|
|||
package cli
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func getSearchers() []searcher {
|
||||
searchers := []searcher{
|
||||
new(searchCveByID),
|
||||
new(searchByImageName),
|
||||
new(searchByImageNameAndTag),
|
||||
new(searchByPackageNameAndVersion),
|
||||
new(searchByPackageName),
|
||||
new(searchByPackageVendor),
|
||||
}
|
||||
|
||||
return searchers
|
||||
}
|
||||
|
||||
var allowedCombinations = `
|
||||
Only these combinations of flags(or their shorthands) are allowed:
|
||||
--cve-id
|
||||
--image-name
|
||||
--image-name --tag
|
||||
--package-vendor
|
||||
--package-name
|
||||
--package-name --package-version
|
||||
--package-version
|
||||
`
|
||||
|
||||
type searcher interface {
|
||||
search(params map[string]*string) (string, error)
|
||||
}
|
||||
|
||||
func canSearch(params map[string]*string, requiredParams *set) bool {
|
||||
for key, value := range params {
|
||||
if requiredParams.contains(key) && *value == "" {
|
||||
return false
|
||||
} else if !requiredParams.contains(key) && *value != "" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
type searchCveByID struct{}
|
||||
|
||||
func (search searchCveByID) search(params map[string]*string) (string, error) {
|
||||
if !canSearch(params, newSet("cveID")) {
|
||||
return "", errors.New("searchByCveId: cannot search with given params. Only CVE ID is required")
|
||||
}
|
||||
return fmt.Sprintf("Searching with CVE ID: %s", *params["cveID"]), nil
|
||||
}
|
||||
|
||||
type searchImageByCveID struct{}
|
||||
|
||||
func (search searchImageByCveID) search(params map[string]*string) (string, error) {
|
||||
if !canSearch(params, newSet("cveIDForImage")) {
|
||||
return "", errors.New("searchImageByCveID: cannot search image with given params. Only CVE ID is required")
|
||||
}
|
||||
return fmt.Sprintf("Searching image with CVE ID: %s", *params["cveID"]), nil
|
||||
}
|
||||
|
||||
type searchByImageNameAndTag struct{}
|
||||
|
||||
func (search searchByImageNameAndTag) search(params map[string]*string) (string, error) {
|
||||
|
||||
if !canSearch(params, newSet("imageName", "tag")) {
|
||||
return "", errors.New("searchByImageNameAndTag: cannot search with given params. Only image name and tag are required")
|
||||
}
|
||||
return fmt.Sprintf("Searching with image name and tag: %s and %s", *params["imageName"], *params["tag"]), nil
|
||||
}
|
||||
|
||||
type searchByImageName struct{}
|
||||
|
||||
func (search searchByImageName) search(params map[string]*string) (string, error) {
|
||||
if !canSearch(params, newSet("imageName")) {
|
||||
return "", errors.New("searchByImageName: cannot search with given params. Only image name is required")
|
||||
}
|
||||
return fmt.Sprintf("Searching with image name: %s", *params["imageName"]), nil
|
||||
}
|
||||
|
||||
type searchByPackageNameAndVersion struct{}
|
||||
|
||||
func (search searchByPackageNameAndVersion) search(params map[string]*string) (string, error) {
|
||||
if !canSearch(params, newSet("packageName", "packageVersion")) {
|
||||
return "", errors.New("searchByPackageNameAndVersion: cannot search with given params. Only package name and version are required")
|
||||
}
|
||||
return fmt.Sprintf("Searching with package name: %s and version %s", *params["packageName"], *params["packageVersion"]), nil
|
||||
}
|
||||
|
||||
type searchByPackageName struct{}
|
||||
|
||||
func (search searchByPackageName) search(params map[string]*string) (string, error) {
|
||||
if !canSearch(params, newSet("packageName")) {
|
||||
return "", errors.New("searchByPackageName: cannot search with given params. Only package name is required")
|
||||
}
|
||||
return fmt.Sprintf("Searching with package name: %s", *params["packageName"]), nil
|
||||
}
|
||||
|
||||
type searchByPackageVendor struct{}
|
||||
|
||||
func (search searchByPackageVendor) search(params map[string]*string) (string, error) {
|
||||
if !canSearch(params, newSet("packageVendor")) {
|
||||
return "", errors.New("searchByPackageVendor: cannot search with given params. Only package vendor is required")
|
||||
}
|
||||
return fmt.Sprintf("Searching with package vendor: %s", *params["packageVendor"]), nil
|
||||
}
|
||||
|
||||
var exists = struct{}{}
|
||||
|
||||
type set struct {
|
||||
m map[string]struct{}
|
||||
}
|
||||
|
||||
func newSet(initialValues ...string) *set {
|
||||
s := &set{}
|
||||
s.m = make(map[string]struct{})
|
||||
for _, val := range initialValues {
|
||||
s.m[val] = exists
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *set) contains(value string) bool {
|
||||
_, c := s.m[value]
|
||||
return c
|
||||
}
|
|
@ -96,6 +96,7 @@ func NewRootCmd() *cobra.Command {
|
|||
|
||||
rootCmd.AddCommand(serveCmd)
|
||||
rootCmd.AddCommand(gcCmd)
|
||||
initSearchCommand(rootCmd)
|
||||
rootCmd.Flags().BoolVarP(&showVersion, "version", "v", false, "show the version and exit")
|
||||
|
||||
return rootCmd
|
||||
|
|
15
pkg/cli/searchCmd.go
Normal file
15
pkg/cli/searchCmd.go
Normal file
|
@ -0,0 +1,15 @@
|
|||
package cli
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func initSearchCommand(rootCmd *cobra.Command) {
|
||||
rootCmd.AddCommand(searchCmd)
|
||||
}
|
||||
|
||||
var searchCmd = &cobra.Command{
|
||||
Use: "search",
|
||||
Short: "Search in zot",
|
||||
Long: `Search in zot`,
|
||||
}
|
Loading…
Reference in a new issue