Skip to content

Commit

Permalink
feat: add known errors
Browse files Browse the repository at this point in the history
This introduces a set of known errors, and a command to print those
(show errors).

Those are to be used by the next commit.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
  • Loading branch information
kolyshkin committed Jul 11, 2023
1 parent 869bc3e commit 62daf28
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 12 deletions.
18 changes: 18 additions & 0 deletions errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package main

import "errors"

//go:generate go run gen_errors_map.go -out errors_map.go

// Well-known errors returned by scan.
var (
ErrGoInvalidTag = errors.New("go binary has invalid build tag(s) set")
ErrGoMissingSymbols = errors.New("go binary does not contain required symbol(s)")
ErrGoMissingTag = errors.New("go binary does not contain required tag(s)")
ErrMultipleLibcrypto = errors.New("openssl: found multiple different libcrypto versions")
ErrNoCgoInit = errors.New("x_cgo_init not found")
ErrNoLibcrypto = errors.New("openssl: did not find libcrypto library within binary")
ErrNoLibcryptoSO = errors.New("could not find dependent openssl version within container image")
ErrNotCgoEnabled = errors.New("go binary is not CGO_ENABLED")
ErrNotDynLinked = errors.New("executable is not dynamically linked")
)
65 changes: 65 additions & 0 deletions gen_errors_map.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//go:build ignore

package main

import (
"bufio"
"flag"
"log"
"os"
"strings"
"text/template"
)

var (
inFile = flag.String("in", "errors.go", "Input file name")
outFile = flag.String("out", "", "Output file name")

tmpl = template.Must(template.New("").Parse(`// Generated by go generate; DO NOT EDIT.
package main
var KnownErrors = map[string]error {
{{- range .Vars }}
{{ printf "\"%s\": %s," . . }}
{{- end }}
}
`))
)

func main() {
flag.Parse()

input, err := os.Open(*inFile)
if err != nil {
log.Fatal(err)
}
defer input.Close()

out := os.Stdout
if *outFile != "" {
out, err = os.Create(*outFile)
if err != nil {
log.Fatal(err)
}
defer out.Close()
}

vars := []string{}
s := bufio.NewScanner(input)
for s.Scan() {
line := s.Text()
if strings.HasPrefix(line, "\tErr") {
// Extract the variable name.
vars = append(vars, line[1:strings.IndexByte(line, ' ')])
}
}
if err := s.Err(); err != nil {
log.Fatal(err)
}
tmpl.Execute(out, struct {
Vars []string
}{
Vars: vars,
})
}
18 changes: 18 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,23 @@ func main() {
},
}

showCmd := &cobra.Command{
Use: "show",
Short: "Show various information",
}

showErrorsCmd := &cobra.Command{
Use: "errors",
Short: "Show known scan errors",
RunE: func(_ *cobra.Command, _ []string) error {
for k, v := range KnownErrors {
fmt.Printf("%-30s %s\n", k, v.Error())
}
return nil
},
}
showCmd.AddCommand(showErrorsCmd)

scanCmd := &cobra.Command{
Use: "scan",
Short: "Run a scan",
Expand Down Expand Up @@ -204,6 +221,7 @@ func main() {
scanCmd.AddCommand(scanImage)

rootCmd.AddCommand(versionCmd)
rootCmd.AddCommand(showCmd)
rootCmd.AddCommand(scanCmd)

// Add klog flags.
Expand Down
21 changes: 9 additions & 12 deletions validations.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ var (
validateGoVersionRegexp = regexp.MustCompile(`go(\d.\d\d)`)
validateGoTagsRegexp = regexp.MustCompile(`-tags=(.*)\n`)
validateStringsOpensslRegexp = regexp.MustCompile(`libcrypto.so(\.?\d+)*`)

ErrNotGolangExe = errors.New("not golang executable")
ErrNotExecutable = errors.New("not a regular executable")
)

type Baton struct {
Expand Down Expand Up @@ -95,7 +92,7 @@ func validateGoSymbols(_ context.Context, _ *v1.TagReference, path string, baton
}

if !ExpectedSyms(requiredGolangSymbols, symtable) {
return fmt.Errorf("go: expected symbols not found for %v", filepath.Base(path))
return ErrGoMissingSymbols
}
return nil
}
Expand Down Expand Up @@ -123,7 +120,7 @@ func validateGoCgo(_ context.Context, _ *v1.TagReference, _ string, baton *Baton
}

if !bytes.Contains(baton.GoVersionDetailed, []byte("CGO_ENABLED=1")) {
return fmt.Errorf("go: binary is not CGO_ENABLED")
return ErrNotCgoEnabled
}
return nil
}
Expand Down Expand Up @@ -157,12 +154,12 @@ func validateGoTags(_ context.Context, _ *v1.TagReference, _ string, baton *Bato
// check for invalid tags
binaryTags := mapset.NewSet(tags...)
if set := binaryTags.Intersect(invalidTagsSet); set.Cardinality() > 0 {
return fmt.Errorf("go: binary has invalid tag %v enabled", set.ToSlice())
return fmt.Errorf("%w: %v", ErrGoInvalidTag, set.ToSlice())
}

// check for required tags
if set := binaryTags.Intersect(expectedTagsSet); set.Cardinality() == 0 {
return fmt.Errorf("go: binary does not contain required tag(s) %v", expectedTagsSet.ToSlice())
return fmt.Errorf("%w: %v", ErrGoMissingTag, expectedTagsSet.ToSlice())
}

return nil
Expand Down Expand Up @@ -215,7 +212,7 @@ func validateGoCGOInit(_ context.Context, _ *v1.TagReference, path string, _ *Ba
}

if !cgoInitFound {
return fmt.Errorf("x_cgo_init: not found")
return ErrNoCgoInit
}

return nil
Expand Down Expand Up @@ -262,17 +259,17 @@ func validateStringsOpenssl(path string, baton *Baton) error {
}

if libcryptoVersion == "" {
return fmt.Errorf("openssl: did not find libcrypto library within binary")
return ErrNoLibcrypto
}

if haveMultipleLibcrypto {
return errors.New("openssl: found multiple different libcrypto versions")
return ErrMultipleLibcrypto
}

// check for openssl library within container image
opensslInnerPath := filepath.Join(baton.TopDir, "usr", "lib64", libcryptoVersion)
if _, err := os.Lstat(opensslInnerPath); err != nil {
return fmt.Errorf("could not find dependent openssl version %v within container image", libcryptoVersion)
return fmt.Errorf("%w: %v", ErrNoLibcryptoSO, libcryptoVersion)
}

return nil
Expand All @@ -290,7 +287,7 @@ func isDynamicallyLinked(ctx context.Context, path string) error {
return err
}
if !bytes.Contains(stdout.Bytes(), []byte("dynamically linked")) {
return fmt.Errorf("exe: executable is statically linked")
return ErrNotDynLinked
}
return nil
}
Expand Down

0 comments on commit 62daf28

Please sign in to comment.