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:
Keith Zantow
2024-10-07 16:11:37 -04:00
committed by GitHub
co-authored by Alex Goodman
parent 4d7ed9f749
commit ccbee94b87
145 changed files with 4420 additions and 233 deletions
+5 -4
View File
@@ -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