Skip to content

Commit

Permalink
support for scanning license files in golang packages
Browse files Browse the repository at this point in the history
Signed-off-by: Avi Deitcher <avi@deitcher.net>
  • Loading branch information
deitch committed Mar 23, 2023
1 parent 9fd5322 commit 9509543
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 3 deletions.
17 changes: 17 additions & 0 deletions cmd/syft/cli/options/packages.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/anchore/syft/syft/formats"
"github.com/anchore/syft/syft/formats/table"
"github.com/anchore/syft/syft/pkg/cataloger"
"github.com/anchore/syft/syft/pkg/cataloger/golang"
"github.com/anchore/syft/syft/source"
)

Expand All @@ -22,6 +23,8 @@ type PackagesOptions struct {
Exclude []string
Catalogers []string
Name string
GoFetchPackages bool
GoProxy string
}

var _ Interface = (*PackagesOptions)(nil)
Expand Down Expand Up @@ -51,6 +54,12 @@ func (o *PackagesOptions) AddFlags(cmd *cobra.Command, v *viper.Viper) error {
cmd.Flags().StringVarP(&o.Name, "name", "", "",
"set the name of the target being analyzed")

cmd.Flags().BoolVarP(&o.GoFetchPackages, "go-fetch", "", false,
"enable fetching of Go packages from the internet for license analysis, otherwise will look only in local")

cmd.Flags().StringVarP(&o.GoProxy, "go-proxy", "", golang.DefaultGoProxy,
"proxy to use when fetching Go packages from the internet for license analysis; used only if --go-fetch is set")

return bindPackageConfigOptions(cmd.Flags(), v)
}

Expand Down Expand Up @@ -90,5 +99,13 @@ func bindPackageConfigOptions(flags *pflag.FlagSet, v *viper.Viper) error {
return err
}

if err := v.BindPFlag("go-fetch", flags.Lookup("go-fetch")); err != nil {
return err
}

if err := v.BindPFlag("go-proxy", flags.Lookup("go-proxy")); err != nil {
return err
}

return nil
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ require (
github.com/anchore/go-logger v0.0.0-20220728155337-03b66a5207d8
github.com/anchore/stereoscope v0.0.0-20230317134707-7928713c391e
github.com/docker/docker v23.0.1+incompatible
github.com/google/go-containerregistry v0.14.0
github.com/google/go-containerregistry v0.13.0
github.com/google/licensecheck v0.3.1
github.com/invopop/jsonschema v0.7.0
github.com/knqyf263/go-rpmdb v0.0.0-20221030135625-4082a22221ce
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -261,8 +261,8 @@ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-containerregistry v0.14.0 h1:z58vMqHxuwvAsVwvKEkmVBz2TlgBgH5k6koEXBtlYkw=
github.com/google/go-containerregistry v0.14.0/go.mod h1:aiJ2fp/SXvkWgmYHioXnbMdlgB8eXiiYOY55gfN91Wk=
github.com/google/go-containerregistry v0.13.0 h1:y1C7Z3e149OJbOPDBxLYR8ITPz8dTKqQwjErKVHJC8k=
github.com/google/go-containerregistry v0.13.0/go.mod h1:J9FQ+eSS4a1aC2GNZxvNpbWhgp0487v+cgiilB4FqDo=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/licensecheck v0.3.1 h1:QoxgoDkaeC4nFrtGN1jV7IPmDCHFNIVh54e5hSt6sPs=
github.com/google/licensecheck v0.3.1/go.mod h1:ORkR35t/JjW+emNKtfJDII0zlciG9JgbT7SmsohlHmY=
Expand Down
2 changes: 2 additions & 0 deletions internal/config/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ type Application struct {
Platform string `yaml:"platform" json:"platform" mapstructure:"platform"`
Name string `yaml:"name" json:"name" mapstructure:"name"`
Parallelism int `yaml:"parallelism" json:"parallelism" mapstructure:"parallelism"` // the number of catalog workers to run in parallel
GoFetch bool `yaml:"go-fetch" json:"go-fetch" mapstructure:"go-fetch"`
GoProxy string `yaml:"go-proxy]" json:"go-proxy" mapstructure:"go-proxy"`
}

func (cfg Application) ToCatalogerConfig() cataloger.Config {
Expand Down
47 changes: 47 additions & 0 deletions syft/pkg/cataloger/golang/package.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
package golang

import (
"archive/zip"
"bytes"
"fmt"
"io"
"io/fs"
"net/http"
"os"
"path/filepath"
"regexp"
"runtime/debug"
"strings"
Expand Down Expand Up @@ -74,3 +82,42 @@ func packageURL(moduleName, moduleVersion string) string {
subpath,
).ToString()
}

func getModule(module, version, proxy string) (fs.FS, error) {
// first see if we have it locally
goPath := os.Getenv("GOPATH")
if goPath != "" {
modPath := filepath.Join(goPath, "pkg", "mod", fmt.Sprintf("%s@%s", module, version))
if fi, err := os.Stat(modPath); err == nil && fi != nil && fi.IsDir() {
modFS := os.DirFS(modPath)
return modFS, nil
}
}

// we could not get it locally, so get it from the proxy, but only if network is enabled

// get the module zip
resp, err := http.Get(fmt.Sprintf("%s/%s/@v/%s.zip", proxy, module, version))
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
// try lowercasing it; some packages have mixed casing that really messes up the proxy
respLC, errLC := http.Get(fmt.Sprintf("%s/%s/@v/%s.zip", proxy, strings.ToLower(module), version))
if errLC != nil {
return nil, err
}
defer respLC.Body.Close()
if respLC.StatusCode != http.StatusOK {
return nil, fmt.Errorf("failed to get module zip: %s", resp.Status)
}
resp = respLC
}
// read the zip
b, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return zip.NewReader(bytes.NewReader(b), resp.ContentLength)
}
5 changes: 5 additions & 0 deletions syft/pkg/cataloger/golang/parse_go_binary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ func TestBuildGoPkgInfo(t *testing.T) {
Name: "github.com/adrg/xdg",
Version: "v0.2.1",
PURL: "pkg:golang/github.com/adrg/xdg@v0.2.1",
Licenses: []string{"MIT"},
Language: pkg.Go,
Type: pkg.GoModulePkg,
Locations: source.NewLocationSet(
Expand Down Expand Up @@ -372,6 +373,7 @@ func TestBuildGoPkgInfo(t *testing.T) {
Name: "github.com/adrg/xdg",
Version: "v0.2.1",
PURL: "pkg:golang/github.com/adrg/xdg@v0.2.1",
Licenses: []string{"MIT"},
Language: pkg.Go,
Type: pkg.GoModulePkg,
Locations: source.NewLocationSet(
Expand All @@ -394,6 +396,7 @@ func TestBuildGoPkgInfo(t *testing.T) {
Name: "github.com/anchore/client-go",
Version: "v0.0.0-20210222170800-9c70f9b80bcf",
PURL: "pkg:golang/github.com/anchore/client-go@v0.0.0-20210222170800-9c70f9b80bcf",
Licenses: []string{"Apache-2.0"},
Language: pkg.Go,
Type: pkg.GoModulePkg,
Locations: source.NewLocationSet(
Expand Down Expand Up @@ -449,6 +452,7 @@ func TestBuildGoPkgInfo(t *testing.T) {
Name: "golang.org/x/sys",
Version: "v0.0.0-20211006194710-c8a6f5223071",
PURL: "pkg:golang/golang.org/x/sys@v0.0.0-20211006194710-c8a6f5223071",
Licenses: []string{"BSD-3-Clause"},
Language: pkg.Go,
Type: pkg.GoModulePkg,
Locations: source.NewLocationSet(
Expand All @@ -470,6 +474,7 @@ func TestBuildGoPkgInfo(t *testing.T) {
Name: "golang.org/x/term",
Version: "v0.0.0-20210916214954-140adaaadfaf",
PURL: "pkg:golang/golang.org/x/term@v0.0.0-20210916214954-140adaaadfaf",
Licenses: []string{"BSD-3-Clause"},
Language: pkg.Go,
Type: pkg.GoModulePkg,
Locations: source.NewLocationSet(
Expand Down

0 comments on commit 9509543

Please sign in to comment.