Bug fix for 1095 - syft conversion option error (#1177)

Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
Christopher Angelo Phillips 2022-08-25 17:36:15 -04:00 committed by GitHub
parent 2c882f6239
commit 615f933d98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 106 additions and 20 deletions

View File

@ -11,6 +11,9 @@ ignore-packages:
# packageurl-go is released under the MIT license located in the root of the repo at /mit.LICENSE # packageurl-go is released under the MIT license located in the root of the repo at /mit.LICENSE
- github.com/anchore/packageurl-go - github.com/anchore/packageurl-go
# crypto/internal/boring is released under the openSSL license as a part of the Golang Standard Libary
- crypto/internal/boring
# from: https://github.com/spdx/tools-golang/blob/main/LICENSE.code # from: https://github.com/spdx/tools-golang/blob/main/LICENSE.code
# The tools-golang source code is provided and may be used, at your option, # The tools-golang source code is provided and may be used, at your option,
# under either: # under either:

View File

@ -49,7 +49,7 @@ func New() (*cobra.Command, error) {
// root options are also passed to the attestCmd so that a user provided config location can be discovered // root options are also passed to the attestCmd so that a user provided config location can be discovered
attestCmd := Attest(v, app, ro) attestCmd := Attest(v, app, ro)
poweruserCmd := PowerUser(v, app, ro) poweruserCmd := PowerUser(v, app, ro)
convertCmd := Convert(v, app, ro) convertCmd := Convert(v, app, ro, po)
// rootCmd is currently an alias for the packages command // rootCmd is currently an alias for the packages command
rootCmd := &cobra.Command{ rootCmd := &cobra.Command{

View File

@ -2,6 +2,7 @@ package cli
import ( import (
"fmt" "fmt"
"log"
"github.com/anchore/syft/cmd/syft/cli/convert" "github.com/anchore/syft/cmd/syft/cli/convert"
"github.com/anchore/syft/cmd/syft/cli/options" "github.com/anchore/syft/cmd/syft/cli/options"
@ -17,7 +18,8 @@ const (
` `
) )
func Convert(v *viper.Viper, app *config.Application, ro *options.RootOptions) *cobra.Command { //nolint:dupl
func Convert(v *viper.Viper, app *config.Application, ro *options.RootOptions, po *options.PackagesOptions) *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "convert [SOURCE-SBOM] -o [FORMAT]", Use: "convert [SOURCE-SBOM] -o [FORMAT]",
Short: "Convert between SBOM formats", Short: "Convert between SBOM formats",
@ -43,5 +45,11 @@ func Convert(v *viper.Viper, app *config.Application, ro *options.RootOptions) *
return convert.Run(cmd.Context(), app, args) return convert.Run(cmd.Context(), app, args)
}, },
} }
err := po.AddFlags(cmd, v)
if err != nil {
log.Fatal(err)
}
return cmd return cmd
} }

View File

@ -5,6 +5,7 @@ import (
"log" "log"
"github.com/anchore/syft/cmd/syft/cli/options" "github.com/anchore/syft/cmd/syft/cli/options"
"github.com/anchore/syft/cmd/syft/cli/packages" "github.com/anchore/syft/cmd/syft/cli/packages"
"github.com/anchore/syft/internal" "github.com/anchore/syft/internal"
"github.com/anchore/syft/internal/config" "github.com/anchore/syft/internal/config"
@ -44,6 +45,7 @@ const (
packagesHelp = packagesExample + packagesSchemeHelp packagesHelp = packagesExample + packagesSchemeHelp
) )
//nolint:dupl
func Packages(v *viper.Viper, app *config.Application, ro *options.RootOptions, po *options.PackagesOptions) *cobra.Command { func Packages(v *viper.Viper, app *config.Application, ro *options.RootOptions, po *options.PackagesOptions) *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "packages [SOURCE]", Use: "packages [SOURCE]",

View File

@ -2,7 +2,7 @@ package file
import ( import (
"fmt" "fmt"
"io/ioutil" "os"
"path/filepath" "path/filepath"
"github.com/bmatcuk/doublestar/v4" "github.com/bmatcuk/doublestar/v4"
@ -33,7 +33,7 @@ func ExtractGlobsFromTarToUniqueTempFile(archivePath, dir string, globs ...strin
// we have a file we want to extract.... // we have a file we want to extract....
tempfilePrefix := filepath.Base(filepath.Clean(file.Name())) + "-" tempfilePrefix := filepath.Base(filepath.Clean(file.Name())) + "-"
tempFile, err := ioutil.TempFile(dir, tempfilePrefix) tempFile, err := os.CreateTemp(dir, tempfilePrefix)
if err != nil { if err != nil {
return fmt.Errorf("unable to create temp file: %w", err) return fmt.Errorf("unable to create temp file: %w", err)
} }

View File

@ -4,7 +4,6 @@ import (
"archive/zip" "archive/zip"
"bytes" "bytes"
"fmt" "fmt"
"io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
@ -82,7 +81,7 @@ func ExtractFromZipToUniqueTempFile(archivePath, dir string, paths ...string) (m
visitor := func(file *zip.File) error { visitor := func(file *zip.File) error {
tempfilePrefix := filepath.Base(filepath.Clean(file.Name)) + "-" tempfilePrefix := filepath.Base(filepath.Clean(file.Name)) + "-"
tempFile, err := ioutil.TempFile(dir, tempfilePrefix) tempFile, err := os.CreateTemp(dir, tempfilePrefix)
if err != nil { if err != nil {
return fmt.Errorf("unable to create temp file: %w", err) return fmt.Errorf("unable to create temp file: %w", err)
} }

View File

@ -4,7 +4,6 @@ import (
"fmt" "fmt"
"io" "io"
"io/fs" "io/fs"
"io/ioutil"
"os" "os"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
@ -55,7 +54,7 @@ func NewLogrusLogger(cfg LogrusConfig) *LogrusLogger {
} }
output = logFile output = logFile
default: default:
output = ioutil.Discard output = io.Discard
} }
appLogger.SetOutput(output) appLogger.SetOutput(output)

View File

@ -2,7 +2,7 @@ package version
import ( import (
"fmt" "fmt"
"io/ioutil" "io"
"net/http" "net/http"
"strings" "strings"
@ -59,7 +59,7 @@ func fetchLatestApplicationVersion() (*hashiVersion.Version, error) {
return nil, fmt.Errorf("HTTP %d on fetching latest version: %s", resp.StatusCode, resp.Status) return nil, fmt.Errorf("HTTP %d on fetching latest version: %s", resp.StatusCode, resp.Status)
} }
versionBytes, err := ioutil.ReadAll(resp.Body) versionBytes, err := io.ReadAll(resp.Body)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to read latest version: %w", err) return nil, fmt.Errorf("failed to read latest version: %w", err)
} }

View File

@ -4,7 +4,7 @@ import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil" "io"
"os" "os"
"reflect" "reflect"
"sort" "sort"
@ -118,7 +118,7 @@ func write(schema []byte) {
panic(err) panic(err)
} }
existingSchemaBytes, err := ioutil.ReadAll(existingFh) existingSchemaBytes, err := io.ReadAll(existingFh)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@ -2,7 +2,7 @@ package linux
import ( import (
"fmt" "fmt"
"io/ioutil" "io"
"regexp" "regexp"
"strings" "strings"
@ -68,7 +68,7 @@ func IdentifyRelease(resolver source.FileResolver) *Release {
continue continue
} }
content, err := ioutil.ReadAll(contentReader) content, err := io.ReadAll(contentReader)
internal.CloseAndLogError(contentReader, location.VirtualPath) internal.CloseAndLogError(contentReader, location.VirtualPath)
if err != nil { if err != nil {
log.Warnf("unable to read %q: %+v", location.RealPath, err) log.Warnf("unable to read %q: %+v", location.RealPath, err)

View File

@ -3,7 +3,6 @@ package golang
import ( import (
"fmt" "fmt"
"io" "io"
"io/ioutil"
"sort" "sort"
"github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/artifact"
@ -15,7 +14,7 @@ import (
func parseGoMod(path string, reader io.Reader) ([]*pkg.Package, []artifact.Relationship, error) { func parseGoMod(path string, reader io.Reader) ([]*pkg.Package, []artifact.Relationship, error) {
packages := make(map[string]*pkg.Package) packages := make(map[string]*pkg.Package)
contents, err := ioutil.ReadAll(reader) contents, err := io.ReadAll(reader)
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("failed to read go module: %w", err) return nil, nil, fmt.Errorf("failed to read go module: %w", err)
} }

View File

@ -4,7 +4,6 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"io" "io"
"io/ioutil"
macho "github.com/anchore/go-macholibre" macho "github.com/anchore/go-macholibre"
"github.com/anchore/syft/internal/log" "github.com/anchore/syft/internal/log"
@ -45,7 +44,7 @@ func GetUnionReader(readerCloser io.ReadCloser) (UnionReader, error) {
return reader, nil return reader, nil
} }
b, err := ioutil.ReadAll(readerCloser) b, err := io.ReadAll(readerCloser)
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to read contents from binary: %w", err) return nil, fmt.Errorf("unable to read contents from binary: %w", err)
} }

View File

@ -8,7 +8,6 @@ package source
import ( import (
"context" "context"
"fmt" "fmt"
"io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
@ -345,7 +344,7 @@ func (s *Source) FileResolver(scope Scope) (FileResolver, error) {
} }
func unarchiveToTmp(path string, unarchiver archiver.Unarchiver) (string, func(), error) { func unarchiveToTmp(path string, unarchiver archiver.Unarchiver) (string, func(), error) {
tempDir, err := ioutil.TempDir("", "syft-archive-contents-") tempDir, err := os.MkdirTemp("", "syft-archive-contents-")
if err != nil { if err != nil {
return "", func() {}, fmt.Errorf("unable to create tempdir for archive processing: %w", err) return "", func() {}, fmt.Errorf("unable to create tempdir for archive processing: %w", err)
} }

View File

@ -0,0 +1,78 @@
package cli
import (
"os"
"path/filepath"
"strings"
"testing"
"github.com/stretchr/testify/require"
)
type conversion struct {
To string
From string
}
func TestConvertCmdFlags(t *testing.T) {
commonAssertions := []traitAssertion{
func(tb testing.TB, stdout, _ string, _ int) {
tb.Helper()
if len(stdout) < 1000 {
tb.Errorf("there may not be any report output (len=%d)", len(stdout))
}
},
assertSuccessfulReturnCode,
}
tests := []struct {
name string
conversions []conversion
env map[string]string
assertions []traitAssertion
}{
{
name: "syft-format convertable to spdx-json",
conversions: []conversion{
{To: "syft-json", From: "spdx-json"},
{To: "syft-json", From: "cyclonedx-json"},
{To: "spdx-json", From: "syft-json"},
{To: "spdx-json", From: "cyclonedx-json"},
{To: "cyclonedx-json", From: "syft-json"},
{To: "cyclonedx-json", From: "spdx-json"},
},
assertions: commonAssertions,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
for _, c := range test.conversions {
sbomArgs := []string{"dir:./test-fixtures/image-pkg-coverage", "-o", c.From}
cmd, stdout, stderr := runSyft(t, test.env, sbomArgs...)
if cmd.ProcessState.ExitCode() != 0 {
t.Fatalf("failure executing syft creating an sbom")
t.Log("STDOUT:\n", stdout)
t.Log("STDERR:\n", stderr)
t.Log("COMMAND:", strings.Join(cmd.Args, " "))
return
}
tempDir := t.TempDir()
sbomFile := filepath.Join(tempDir, "sbom.json")
require.NoError(t, os.WriteFile(sbomFile, []byte(stdout), 0666))
convertArgs := []string{"convert", sbomFile, "-o", c.To}
cmd, stdout, stderr = runSyft(t, test.env, convertArgs...)
for _, traitFn := range test.assertions {
traitFn(t, stdout, stderr, cmd.ProcessState.ExitCode())
}
if t.Failed() {
t.Log("STDOUT:\n", stdout)
t.Log("STDERR:\n", stderr)
t.Log("COMMAND:", strings.Join(cmd.Args, " "))
}
}
})
}
}