Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cmd/attest.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,11 @@ func attestExec(ctx context.Context, _ *cobra.Command, args []string) error {
return fmt.Errorf("attest command can only be used with image sources fetch directly from the registry, but discovered an image source of %q when given %q", si.ImageSource, userInput)
}

if len(appConfig.Output) > 1 {
if len(appConfig.Outputs) > 1 {
return fmt.Errorf("unable to generate attestation for more than one output")
}

format := syft.FormatByName(appConfig.Output[0])
format := syft.FormatByName(appConfig.Outputs[0])
predicateType := formatPredicateType(format)
if predicateType == "" {
return fmt.Errorf("could not produce attestation predicate for given format: %q. Available formats: %+v", formatAliases(format.ID()), formatAliases(attestFormats...))
Expand Down
5 changes: 1 addition & 4 deletions cmd/output_writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,7 @@ func parseOptions(outputs []string, defaultFile string) (out []sbom.WriterOption
continue
}

out = append(out, sbom.WriterOption{
Format: format,
Path: file,
})
out = append(out, sbom.NewWriterOption(format, file))
}
return out, errs
}
2 changes: 1 addition & 1 deletion cmd/packages.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ func validateInputArgs(cmd *cobra.Command, args []string) error {
}

func packagesExec(_ *cobra.Command, args []string) error {
writer, err := makeWriter(appConfig.Output, appConfig.File)
writer, err := makeWriter(appConfig.Outputs, appConfig.File)
if err != nil {
return err
}
Expand Down
10 changes: 6 additions & 4 deletions cmd/power_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,12 @@ func powerUserExec(_ *cobra.Command, args []string) error {
// could be an image or a directory, with or without a scheme
userInput := args[0]

writer, err := sbom.NewWriter(sbom.WriterOption{
Format: syftjson.Format(),
Path: appConfig.File,
})
writer, err := sbom.NewWriter(
sbom.NewWriterOption(
syftjson.Format(),
appConfig.File,
),
)
if err != nil {
return err
}
Expand Down
14 changes: 13 additions & 1 deletion internal/config/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ type parser interface {
// Application is the main syft application configuration.
type Application struct {
ConfigPath string `yaml:",omitempty" json:"configPath"` // the location where the application config was read from (either from -c or discovered while loading)
Output []string `yaml:"output" json:"output" mapstructure:"output"` // -o, the format to use for output
Outputs []string `yaml:"output" json:"output" mapstructure:"output"` // -o, the format to use for output
File string `yaml:"file" json:"file" mapstructure:"file"` // --file, the file to write report output to
Quiet bool `yaml:"quiet" json:"quiet" mapstructure:"quiet"` // -q, indicates to not show any status output to stderr (ETUI or logging UI)
CheckForAppUpdate bool `yaml:"check-for-app-update" json:"check-for-app-update" mapstructure:"check-for-app-update"` // whether to check for an application update on start up or not
Expand Down Expand Up @@ -104,6 +104,7 @@ func (cfg *Application) parseConfigValues() error {
for _, optionFn := range []func() error{
cfg.parseUploadOptions,
cfg.parseLogLevelOption,
cfg.parseFile,
} {
if err := optionFn(); err != nil {
return err
Expand All @@ -126,6 +127,17 @@ func (cfg *Application) parseConfigValues() error {
return nil
}

func (cfg *Application) parseFile() error {
if cfg.File != "" {
expandedPath, err := homedir.Expand(cfg.File)
if err != nil {
return fmt.Errorf("unable to expand file path=%q: %w", cfg.File, err)
}
cfg.File = expandedPath
}
return nil
}

func (cfg *Application) parseUploadOptions() error {
if cfg.Anchore.Host == "" && cfg.Anchore.Dockerfile != "" {
return fmt.Errorf("cannot provide dockerfile option without enabling upload")
Expand Down
52 changes: 52 additions & 0 deletions internal/config/application_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package config

import (
"github.com/docker/docker/pkg/homedir"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"path/filepath"
"testing"
)

func TestApplication_parseFile(t *testing.T) {
tests := []struct {
name string
config Application
expected string
wantErr require.ErrorAssertionFunc
}{
{
name: "expand home dir",
config: Application{
File: "~/place.txt",
},
expected: filepath.Join(homedir.Get(), "place.txt"),
},
{
name: "passthrough other paths",
config: Application{
File: "/other/place.txt",
},
expected: "/other/place.txt",
},
{
name: "no path",
config: Application{
File: "",
},
expected: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cfg := tt.config

if tt.wantErr == nil {
tt.wantErr = require.NoError
}

tt.wantErr(t, cfg.parseFile())
assert.Equal(t, tt.expected, cfg.File)
})
}
}
15 changes: 12 additions & 3 deletions internal/config/attest.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
package config

import (
"fmt"
"os"

"github.com/mitchellh/go-homedir"
"github.com/spf13/viper"
)

type attest struct {
Key string `yaml:"key" json:"key" mapstructure:"key"`
Key string `yaml:"key" json:"key" mapstructure:"key"` // same as --key, file path to the private key
// IMPORTANT: do not show the password in any YAML/JSON output (sensitive information)
Password string `yaml:"-" json:"-" mapstructure:"password"`
Password string `yaml:"-" json:"-" mapstructure:"password"` // password for the private key
}

//nolint:unparam
func (cfg *attest) parseConfigValues() error {
if cfg.Key != "" {
expandedPath, err := homedir.Expand(cfg.Key)
if err != nil {
return fmt.Errorf("unable to expand key path=%q: %w", cfg.Key, err)
}
cfg.Key = expandedPath
}

if cfg.Password == "" {
// we allow for configuration via syft config/env vars and additionally interop with known cosign config env vars
if pw, ok := os.LookupEnv("COSIGN_PASSWORD"); ok {
Expand Down
14 changes: 14 additions & 0 deletions internal/config/logging.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package config

import (
"fmt"

"github.com/mitchellh/go-homedir"
"github.com/sirupsen/logrus"
"github.com/spf13/viper"
)
Expand All @@ -13,6 +16,17 @@ type logging struct {
FileLocation string `yaml:"file" json:"file-location" mapstructure:"file"` // the file path to write logs to
}

func (cfg *logging) parseConfigValues() error {
if cfg.FileLocation != "" {
expandedPath, err := homedir.Expand(cfg.FileLocation)
if err != nil {
return fmt.Errorf("unable to expand log file path=%q: %w", cfg.FileLocation, err)
}
cfg.FileLocation = expandedPath
}
return nil
}

func (cfg logging) loadDefaultValues(v *viper.Viper) {
v.SetDefault("log.structured", false)
v.SetDefault("log.file", "")
Expand Down
25 changes: 20 additions & 5 deletions syft/sbom/multi_writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"path"

"github.com/anchore/syft/internal/log"

"github.com/hashicorp/go-multierror"
"github.com/mitchellh/go-homedir"
)

// multiWriter holds a list of child sbom.Writers to apply all Write and Close operations to
Expand All @@ -21,18 +21,33 @@ type WriterOption struct {
Path string
}

func NewWriterOption(f Format, p string) WriterOption {
expandedPath, err := homedir.Expand(p)
if err != nil {
log.Warnf("could not expand given writer output path=%q: %w", p, err)
// ignore errors
expandedPath = p
}
return WriterOption{
Format: f,
Path: expandedPath,
}
}

// NewWriter create all report writers from input options; if a file is not specified, os.Stdout is used
func NewWriter(options ...WriterOption) (Writer, error) {
func NewWriter(options ...WriterOption) (_ Writer, err error) {
if len(options) == 0 {
return nil, fmt.Errorf("no output options provided")
}

out := &multiWriter{}

defer func() {
// close any previously opened files; we can't really recover from any errors
if err := out.Close(); err != nil {
log.Warnf("unable to close sbom writers: %+v", err)
if err != nil {
// close any previously opened files; we can't really recover from any errors
if err := out.Close(); err != nil {
log.Warnf("unable to close sbom writers: %+v", err)
}
}
}()

Expand Down
32 changes: 32 additions & 0 deletions syft/sbom/multi_writer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package sbom

import (
"io"
"path/filepath"
"strings"
"testing"

"github.com/docker/docker/pkg/homedir"
"github.com/stretchr/testify/assert"
)

Expand Down Expand Up @@ -170,3 +172,33 @@ func TestOutputWriter(t *testing.T) {
})
}
}

func TestNewWriterOption(t *testing.T) {
tests := []struct {
name string
path string
expected string
}{
{
name: "expand home dir",
path: "~/place.txt",
expected: filepath.Join(homedir.Get(), "place.txt"),
},
{
name: "passthrough other paths",
path: "/other/place.txt",
expected: "/other/place.txt",
},
{
name: "no path",
path: "",
expected: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
o := NewWriterOption(dummyFormat("table"), tt.path)
assert.Equal(t, tt.expected, o.Path)
})
}
}
21 changes: 21 additions & 0 deletions test/cli/packages_cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cli

import (
"fmt"
"path/filepath"
"strings"
"testing"
)
Expand Down Expand Up @@ -192,6 +193,26 @@ func TestPackagesCmdFlags(t *testing.T) {
assertSuccessfulReturnCode,
},
},
{
name: "json-file-flag",
args: []string{"packages", "-o", "json", "--file", filepath.Join(tmp, "output-1.json"), coverageImage},
assertions: []traitAssertion{
assertSuccessfulReturnCode,
assertFileOutput(t, filepath.Join(tmp, "output-1.json"),
assertJsonReport,
),
},
},
{
name: "json-output-flag-to-file",
args: []string{"packages", "-o", fmt.Sprintf("json=%s", filepath.Join(tmp, "output-2.json")), coverageImage},
assertions: []traitAssertion{
assertSuccessfulReturnCode,
assertFileOutput(t, filepath.Join(tmp, "output-2.json"),
assertJsonReport,
),
},
},
}

for _, test := range tests {
Expand Down
16 changes: 16 additions & 0 deletions test/cli/trait_assertions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,26 @@ import (
"testing"

"github.com/acarl005/stripansi"
"github.com/stretchr/testify/require"
)

type traitAssertion func(tb testing.TB, stdout, stderr string, rc int)

func assertFileOutput(tb testing.TB, path string, assertions ...traitAssertion) traitAssertion {
tb.Helper()

return func(tb testing.TB, _, stderr string, rc int) {
content, err := os.ReadFile(path)
require.NoError(tb, err)
contentStr := string(content)

for _, assertion := range assertions {
// treat the file content as stdout
assertion(tb, contentStr, stderr, rc)
}
}
}

func assertJsonReport(tb testing.TB, stdout, _ string, _ int) {
tb.Helper()
var data interface{}
Expand Down