mirror of
https://github.com/anchore/syft.git
synced 2026-11-05 00:46:38 +01:00
feat: report unknowns in sbom (#2998)
Signed-off-by: Keith Zantow <kzantow@gmail.com> Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
co-authored by
Alex Goodman
parent
4d7ed9f749
commit
ccbee94b87
@@ -1,6 +1,7 @@
|
||||
package githubactions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/anchore/packageurl-go"
|
||||
@@ -9,19 +10,19 @@ import (
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
)
|
||||
|
||||
func newPackageFromUsageStatement(use string, location file.Location) *pkg.Package {
|
||||
func newPackageFromUsageStatement(use string, location file.Location) (*pkg.Package, error) {
|
||||
name, version := parseStepUsageStatement(use)
|
||||
|
||||
if name == "" {
|
||||
log.WithFields("file", location.RealPath, "statement", use).Trace("unable to parse github action usage statement")
|
||||
return nil
|
||||
return nil, fmt.Errorf("unable to parse github action usage statement")
|
||||
}
|
||||
|
||||
if strings.Contains(name, ".github/workflows/") {
|
||||
return newGithubActionWorkflowPackageUsage(name, version, location)
|
||||
return newGithubActionWorkflowPackageUsage(name, version, location), nil
|
||||
}
|
||||
|
||||
return newGithubActionPackageUsage(name, version, location)
|
||||
return newGithubActionPackageUsage(name, version, location), nil
|
||||
}
|
||||
|
||||
func newGithubActionWorkflowPackageUsage(name, version string, workflowLocation file.Location) *pkg.Package {
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/anchore/syft/internal/unknown"
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
@@ -24,14 +25,14 @@ type compositeActionRunsDef struct {
|
||||
}
|
||||
|
||||
func parseCompositeActionForActionUsage(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||
contents, err := io.ReadAll(reader)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to read yaml composite action file: %w", err)
|
||||
contents, errs := io.ReadAll(reader)
|
||||
if errs != nil {
|
||||
return nil, nil, fmt.Errorf("unable to read yaml composite action file: %w", errs)
|
||||
}
|
||||
|
||||
var ca compositeActionDef
|
||||
if err = yaml.Unmarshal(contents, &ca); err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to parse yaml composite action file: %w", err)
|
||||
if errs = yaml.Unmarshal(contents, &ca); errs != nil {
|
||||
return nil, nil, fmt.Errorf("unable to parse yaml composite action file: %w", errs)
|
||||
}
|
||||
|
||||
// we use a collection to help with deduplication before raising to higher level processing
|
||||
@@ -42,11 +43,14 @@ func parseCompositeActionForActionUsage(_ context.Context, _ file.Resolver, _ *g
|
||||
continue
|
||||
}
|
||||
|
||||
p := newPackageFromUsageStatement(step.Uses, reader.Location)
|
||||
p, err := newPackageFromUsageStatement(step.Uses, reader.Location)
|
||||
if err != nil {
|
||||
errs = unknown.Append(errs, reader, err)
|
||||
}
|
||||
if p != nil {
|
||||
pkgs.Add(*p)
|
||||
}
|
||||
}
|
||||
|
||||
return pkgs.Sorted(), nil, nil
|
||||
return pkgs.Sorted(), nil, errs
|
||||
}
|
||||
|
||||
@@ -33,3 +33,10 @@ func Test_parseCompositeActionForActionUsage(t *testing.T) {
|
||||
var expectedRelationships []artifact.Relationship
|
||||
pkgtest.TestFileParser(t, fixture, parseCompositeActionForActionUsage, expected, expectedRelationships)
|
||||
}
|
||||
|
||||
func Test_corruptCompositeAction(t *testing.T) {
|
||||
pkgtest.NewCatalogTester().
|
||||
FromFile(t, "test-fixtures/corrupt/composite-action.yaml").
|
||||
WithError().
|
||||
TestParser(t, parseCompositeActionForActionUsage)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/anchore/syft/internal/unknown"
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
@@ -37,14 +38,14 @@ type stepDef struct {
|
||||
}
|
||||
|
||||
func parseWorkflowForWorkflowUsage(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||
contents, err := io.ReadAll(reader)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to read yaml workflow file: %w", err)
|
||||
contents, errs := io.ReadAll(reader)
|
||||
if errs != nil {
|
||||
return nil, nil, fmt.Errorf("unable to read yaml workflow file: %w", errs)
|
||||
}
|
||||
|
||||
var wf workflowDef
|
||||
if err = yaml.Unmarshal(contents, &wf); err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to parse yaml workflow file: %w", err)
|
||||
if errs = yaml.Unmarshal(contents, &wf); errs != nil {
|
||||
return nil, nil, fmt.Errorf("unable to parse yaml workflow file: %w", errs)
|
||||
}
|
||||
|
||||
// we use a collection to help with deduplication before raising to higher level processing
|
||||
@@ -52,25 +53,28 @@ func parseWorkflowForWorkflowUsage(_ context.Context, _ file.Resolver, _ *generi
|
||||
|
||||
for _, job := range wf.Jobs {
|
||||
if job.Uses != "" {
|
||||
p := newPackageFromUsageStatement(job.Uses, reader.Location)
|
||||
p, err := newPackageFromUsageStatement(job.Uses, reader.Location)
|
||||
if err != nil {
|
||||
errs = unknown.Append(errs, reader, err)
|
||||
}
|
||||
if p != nil {
|
||||
pkgs.Add(*p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pkgs.Sorted(), nil, nil
|
||||
return pkgs.Sorted(), nil, errs
|
||||
}
|
||||
|
||||
func parseWorkflowForActionUsage(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||
contents, err := io.ReadAll(reader)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to read yaml workflow file: %w", err)
|
||||
contents, errs := io.ReadAll(reader)
|
||||
if errs != nil {
|
||||
return nil, nil, fmt.Errorf("unable to read yaml workflow file: %w", errs)
|
||||
}
|
||||
|
||||
var wf workflowDef
|
||||
if err = yaml.Unmarshal(contents, &wf); err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to parse yaml workflow file: %w", err)
|
||||
if errs = yaml.Unmarshal(contents, &wf); errs != nil {
|
||||
return nil, nil, fmt.Errorf("unable to parse yaml workflow file: %w", errs)
|
||||
}
|
||||
|
||||
// we use a collection to help with deduplication before raising to higher level processing
|
||||
@@ -81,12 +85,15 @@ func parseWorkflowForActionUsage(_ context.Context, _ file.Resolver, _ *generic.
|
||||
if step.Uses == "" {
|
||||
continue
|
||||
}
|
||||
p := newPackageFromUsageStatement(step.Uses, reader.Location)
|
||||
p, err := newPackageFromUsageStatement(step.Uses, reader.Location)
|
||||
if err != nil {
|
||||
errs = unknown.Append(errs, reader, err)
|
||||
}
|
||||
if p != nil {
|
||||
pkgs.Add(*p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pkgs.Sorted(), nil, nil
|
||||
return pkgs.Sorted(), nil, errs
|
||||
}
|
||||
|
||||
@@ -86,3 +86,17 @@ func Test_parseWorkflowForWorkflowUsage(t *testing.T) {
|
||||
var expectedRelationships []artifact.Relationship
|
||||
pkgtest.TestFileParser(t, fixture, parseWorkflowForWorkflowUsage, expected, expectedRelationships)
|
||||
}
|
||||
|
||||
func Test_corruptActionWorkflow(t *testing.T) {
|
||||
pkgtest.NewCatalogTester().
|
||||
FromFile(t, "test-fixtures/corrupt/workflow-multi-job.yaml").
|
||||
WithError().
|
||||
TestParser(t, parseWorkflowForActionUsage)
|
||||
}
|
||||
|
||||
func Test_corruptWorkflowWorkflow(t *testing.T) {
|
||||
pkgtest.NewCatalogTester().
|
||||
FromFile(t, "test-fixtures/corrupt/workflow-multi-job.yaml").
|
||||
WithError().
|
||||
TestParser(t, parseWorkflowForWorkflowUsage)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
name: "Bootstrap"
|
||||
description: "Bootstrap all tools and dependencies"
|
||||
ints:
|
||||
go-version:
|
||||
descrapt-packages:
|
||||
description: "Space delimited list of tools to install via apt"
|
||||
default: "libxml2-utils"
|
||||
|
||||
rns:
|
||||
us all cache fingerprints
|
||||
shell: bash
|
||||
run: make fingerprints
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
name: "Validations"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jbs
|
||||
|
||||
Statnapshot
|
||||
key: snapshot-build-${{ github.run_id }}
|
||||
|
||||
- name: Run CLI Tests (Linux)
|
||||
run: make cli
|
||||
Reference in New Issue
Block a user