Skip to content
Closed
30 changes: 23 additions & 7 deletions cmd/syft/cli/attest/attest.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,23 @@ var (
intotoJSONDsseType = `application/vnd.in-toto+json`
)

//nolint:funlen
func Run(ctx context.Context, app *config.Application, ko sigopts.KeyOpts, args []string) error {
// We cannot generate an attestation for more than one output
if len(app.Outputs) > 1 {
return fmt.Errorf("unable to generate attestation for more than one output")
}

// can only be an image for attestation or OCI DIR
userInput := args[0]
si, err := parseImageSource(userInput, app)
if err != nil {
return err
// TODO support input from config somehow
var userInputs []source.Input
for _, userInput := range args {
// could be an image or a directory, with or without a scheme
// can only be an image for attestation or OCI DIR
si, err := parseImageSource(userInput, app)
if err != nil {
return err
}
userInputs = append(userInputs, *si)
}

output := parseAttestationOutput(app.Outputs)
Expand Down Expand Up @@ -107,7 +113,7 @@ func Run(ctx context.Context, app *config.Application, ko sigopts.KeyOpts, args
subscription := eventBus.Subscribe()

return eventloop.EventLoop(
execWorker(app, *si, format, predicateType, sv),
execWorkers(app, userInputs, format, predicateType, sv),
eventloop.SetupSignals(),
subscription,
stereoscope.Cleanup,
Expand Down Expand Up @@ -151,6 +157,16 @@ func parseImageSource(userInput string, app *config.Application) (s *source.Inpu
return si, nil
}

func execWorkers(app *config.Application, sourceInputs []source.Input, format sbom.Format, predicateType string, sv *sign.SignerVerifier) <-chan error {
errs := make(chan error)
for _, src := range sourceInputs {
for err := range execWorker(app, src, format, predicateType, sv) {
errs <- err
}
}
return errs
}

func execWorker(app *config.Application, sourceInput source.Input, format sbom.Format, predicateType string, sv *sign.SignerVerifier) <-chan error {
errs := make(chan error)
go func() {
Expand All @@ -165,7 +181,7 @@ func execWorker(app *config.Application, sourceInput source.Input, format sbom.F
return
}

s, err := packages.GenerateSBOM(src, errs, app)
s, err := packages.GenerateSBOM([]source.Source{*src}, errs, app)
if err != nil {
errs <- err
return
Expand Down
2 changes: 1 addition & 1 deletion cmd/syft/cli/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ func validateArgs(cmd *cobra.Command, args []string) error {
return fmt.Errorf("an image/directory argument is required")
}

return cobra.MaximumNArgs(1)(cmd, args)
return nil // cobra.MaximumNArgs(1)(cmd, args)
}

func checkForApplicationUpdate() {
Expand Down
85 changes: 46 additions & 39 deletions cmd/syft/cli/eventloop/tasks.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ import (
"github.com/anchore/syft/syft"
"github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/linux"
"github.com/anchore/syft/syft/sbom"
"github.com/anchore/syft/syft/source"
)

type Task func(*sbom.Artifacts, *source.Source) ([]artifact.Relationship, error)
type Task func(*sbom.SBOM, *source.Source) error

func Tasks(app *config.Application) ([]Task, error) {
var tasks []Task
Expand Down Expand Up @@ -45,16 +46,28 @@ func generateCatalogPackagesTask(app *config.Application) (Task, error) {
return nil, nil
}

task := func(results *sbom.Artifacts, src *source.Source) ([]artifact.Relationship, error) {
task := func(results *sbom.SBOM, src *source.Source) error {
packageCatalog, relationships, theDistro, err := syft.CatalogPackages(src, app.ToCatalogerConfig())
if err != nil {
return nil, err
return err
}

for p := range packageCatalog.Enumerate() {
results.Relationships = append(results.Relationships, artifact.Relationship{
From: p,
To: &src.Metadata,
Type: artifact.SourceRelationship,
})
results.Artifacts.PackageCatalog.Add(p)
}

results.PackageCatalog = packageCatalog
results.LinuxDistribution = theDistro
if theDistro != nil {
results.Artifacts.LinuxDistributions = []linux.Release{*theDistro}
}

results.Relationships = append(results.Relationships, relationships...)

return relationships, nil
return nil
}

return task, nil
Expand All @@ -67,18 +80,18 @@ func generateCatalogFileMetadataTask(app *config.Application) (Task, error) {

metadataCataloger := file.NewMetadataCataloger()

task := func(results *sbom.Artifacts, src *source.Source) ([]artifact.Relationship, error) {
task := func(results *sbom.SBOM, src *source.Source) error {
resolver, err := src.FileResolver(app.FileMetadata.Cataloger.ScopeOpt)
if err != nil {
return nil, err
return err
}

result, err := metadataCataloger.Catalog(resolver)
if err != nil {
return nil, err
return err
}
results.FileMetadata = result
return nil, nil
results.Artifacts.FileMetadata = result
return nil
}

return task, nil
Expand Down Expand Up @@ -113,18 +126,18 @@ func generateCatalogFileDigestsTask(app *config.Application) (Task, error) {
return nil, err
}

task := func(results *sbom.Artifacts, src *source.Source) ([]artifact.Relationship, error) {
task := func(results *sbom.SBOM, src *source.Source) error {
resolver, err := src.FileResolver(app.FileMetadata.Cataloger.ScopeOpt)
if err != nil {
return nil, err
return err
}

result, err := digestsCataloger.Catalog(resolver)
if err != nil {
return nil, err
return err
}
results.FileDigests = result
return nil, nil
results.Artifacts.FileDigests = result
return nil
}

return task, nil
Expand All @@ -145,18 +158,18 @@ func generateCatalogSecretsTask(app *config.Application) (Task, error) {
return nil, err
}

task := func(results *sbom.Artifacts, src *source.Source) ([]artifact.Relationship, error) {
task := func(results *sbom.SBOM, src *source.Source) error {
resolver, err := src.FileResolver(app.Secrets.Cataloger.ScopeOpt)
if err != nil {
return nil, err
return err
}

result, err := secretsCataloger.Catalog(resolver)
if err != nil {
return nil, err
return err
}
results.Secrets = result
return nil, nil
results.Artifacts.Secrets = result
return nil
}

return task, nil
Expand All @@ -173,18 +186,18 @@ func generateCatalogFileClassificationsTask(app *config.Application) (Task, erro
return nil, err
}

task := func(results *sbom.Artifacts, src *source.Source) ([]artifact.Relationship, error) {
task := func(results *sbom.SBOM, src *source.Source) error {
resolver, err := src.FileResolver(app.FileClassification.Cataloger.ScopeOpt)
if err != nil {
return nil, err
return err
}

result, err := classifierCataloger.Catalog(resolver)
if err != nil {
return nil, err
return err
}
results.FileClassifications = result
return nil, nil
results.Artifacts.FileClassifications = result
return nil
}

return task, nil
Expand All @@ -200,33 +213,27 @@ func generateCatalogContentsTask(app *config.Application) (Task, error) {
return nil, err
}

task := func(results *sbom.Artifacts, src *source.Source) ([]artifact.Relationship, error) {
task := func(results *sbom.SBOM, src *source.Source) error {
resolver, err := src.FileResolver(app.FileContents.Cataloger.ScopeOpt)
if err != nil {
return nil, err
return err
}

result, err := contentsCataloger.Catalog(resolver)
if err != nil {
return nil, err
return err
}
results.FileContents = result
return nil, nil
results.Artifacts.FileContents = result
return nil
}

return task, nil
}

func RunTask(t Task, a *sbom.Artifacts, src *source.Source, c chan<- artifact.Relationship, errs chan<- error) {
defer close(c)

relationships, err := t(a, src)
func RunTask(t Task, a *sbom.SBOM, src *source.Source, errs chan<- error) {
err := t(a, src)
if err != nil {
errs <- err
return
}

for _, relationship := range relationships {
c <- relationship
}
}
Loading