mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-12 07:40:48 -08:00
refactor: move artifact types under artifact package to avoid import cycles (#6652)
Signed-off-by: knqyf263 <knqyf263@gmail.com>
This commit is contained in:
@@ -4,12 +4,13 @@ package integration
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
@@ -379,7 +380,7 @@ func TestRepository(t *testing.T) {
|
||||
},
|
||||
golden: "testdata/gomod-skip.json.golden",
|
||||
override: func(_ *testing.T, want, _ *types.Report) {
|
||||
want.ArtifactType = ftypes.ArtifactFilesystem
|
||||
want.ArtifactType = artifact.TypeFilesystem
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -393,7 +394,7 @@ func TestRepository(t *testing.T) {
|
||||
},
|
||||
golden: "testdata/dockerfile-custom-policies.json.golden",
|
||||
override: func(_ *testing.T, want, got *types.Report) {
|
||||
want.ArtifactType = ftypes.ArtifactFilesystem
|
||||
want.ArtifactType = artifact.TypeFilesystem
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
@@ -37,7 +37,7 @@ func TestSBOM(t *testing.T) {
|
||||
golden: "testdata/centos-7.json.golden",
|
||||
override: func(t *testing.T, want, got *types.Report) {
|
||||
want.ArtifactName = "testdata/fixtures/sbom/centos-7-cyclonedx.json"
|
||||
want.ArtifactType = ftypes.ArtifactCycloneDX
|
||||
want.ArtifactType = artifact.TypeCycloneDX
|
||||
|
||||
require.Len(t, got.Results, 1)
|
||||
want.Results[0].Target = "testdata/fixtures/sbom/centos-7-cyclonedx.json (centos 7.6.1810)"
|
||||
@@ -76,7 +76,7 @@ func TestSBOM(t *testing.T) {
|
||||
golden: "testdata/centos-7.json.golden",
|
||||
override: func(t *testing.T, want, got *types.Report) {
|
||||
want.ArtifactName = "testdata/fixtures/sbom/centos-7-cyclonedx.intoto.jsonl"
|
||||
want.ArtifactType = ftypes.ArtifactCycloneDX
|
||||
want.ArtifactType = artifact.TypeCycloneDX
|
||||
|
||||
require.Len(t, got.Results, 1)
|
||||
want.Results[0].Target = "testdata/fixtures/sbom/centos-7-cyclonedx.intoto.jsonl (centos 7.6.1810)"
|
||||
@@ -97,7 +97,7 @@ func TestSBOM(t *testing.T) {
|
||||
golden: "testdata/centos-7.json.golden",
|
||||
override: func(t *testing.T, want, got *types.Report) {
|
||||
want.ArtifactName = "testdata/fixtures/sbom/centos-7-spdx.txt"
|
||||
want.ArtifactType = ftypes.ArtifactSPDX
|
||||
want.ArtifactType = artifact.TypeSPDX
|
||||
|
||||
require.Len(t, got.Results, 1)
|
||||
want.Results[0].Target = "testdata/fixtures/sbom/centos-7-spdx.txt (centos 7.6.1810)"
|
||||
@@ -113,7 +113,7 @@ func TestSBOM(t *testing.T) {
|
||||
golden: "testdata/centos-7.json.golden",
|
||||
override: func(t *testing.T, want, got *types.Report) {
|
||||
want.ArtifactName = "testdata/fixtures/sbom/centos-7-spdx.json"
|
||||
want.ArtifactType = ftypes.ArtifactSPDX
|
||||
want.ArtifactType = artifact.TypeSPDX
|
||||
|
||||
require.Len(t, got.Results, 1)
|
||||
want.Results[0].Target = "testdata/fixtures/sbom/centos-7-spdx.json (centos 7.6.1810)"
|
||||
|
||||
20
integration/testdata/conda-spdx.json.golden
vendored
20
integration/testdata/conda-spdx.json.golden
vendored
@@ -14,7 +14,7 @@
|
||||
"packages": [
|
||||
{
|
||||
"name": "openssl",
|
||||
"SPDXID": "SPDXRef-Package-b8061a5279413d55",
|
||||
"SPDXID": "SPDXRef-Package-32b6b37a6fa2e57f",
|
||||
"versionInfo": "1.1.1q",
|
||||
"supplier": "NOASSERTION",
|
||||
"downloadLocation": "NONE",
|
||||
@@ -38,7 +38,7 @@
|
||||
},
|
||||
{
|
||||
"name": "pip",
|
||||
"SPDXID": "SPDXRef-Package-84198b3828050c11",
|
||||
"SPDXID": "SPDXRef-Package-e260029d0b6fd07b",
|
||||
"versionInfo": "22.2.2",
|
||||
"supplier": "NOASSERTION",
|
||||
"downloadLocation": "NONE",
|
||||
@@ -103,23 +103,23 @@
|
||||
},
|
||||
{
|
||||
"spdxElementId": "SPDXRef-Filesystem-2e2426fd0f2580ef",
|
||||
"relatedSpdxElement": "SPDXRef-Package-84198b3828050c11",
|
||||
"relatedSpdxElement": "SPDXRef-Package-32b6b37a6fa2e57f",
|
||||
"relationshipType": "CONTAINS"
|
||||
},
|
||||
{
|
||||
"spdxElementId": "SPDXRef-Filesystem-2e2426fd0f2580ef",
|
||||
"relatedSpdxElement": "SPDXRef-Package-b8061a5279413d55",
|
||||
"relatedSpdxElement": "SPDXRef-Package-e260029d0b6fd07b",
|
||||
"relationshipType": "CONTAINS"
|
||||
},
|
||||
{
|
||||
"spdxElementId": "SPDXRef-Package-84198b3828050c11",
|
||||
"relatedSpdxElement": "SPDXRef-File-7eb62e2a3edddc0a",
|
||||
"relationshipType": "CONTAINS"
|
||||
},
|
||||
{
|
||||
"spdxElementId": "SPDXRef-Package-b8061a5279413d55",
|
||||
"spdxElementId": "SPDXRef-Package-32b6b37a6fa2e57f",
|
||||
"relatedSpdxElement": "SPDXRef-File-600e5e0110a84891",
|
||||
"relationshipType": "CONTAINS"
|
||||
},
|
||||
{
|
||||
"spdxElementId": "SPDXRef-Package-e260029d0b6fd07b",
|
||||
"relatedSpdxElement": "SPDXRef-File-7eb62e2a3edddc0a",
|
||||
"relationshipType": "CONTAINS"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
"github.com/aquasecurity/tml"
|
||||
"github.com/aquasecurity/trivy/pkg/clock"
|
||||
cr "github.com/aquasecurity/trivy/pkg/compliance/report"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
|
||||
"github.com/aquasecurity/trivy/pkg/flag"
|
||||
"github.com/aquasecurity/trivy/pkg/iac/scan"
|
||||
pkgReport "github.com/aquasecurity/trivy/pkg/report"
|
||||
@@ -97,7 +97,7 @@ func Write(ctx context.Context, rep *Report, opt flag.Options, fromCache bool) e
|
||||
base := types.Report{
|
||||
CreatedAt: clock.Now(ctx),
|
||||
ArtifactName: rep.AccountID,
|
||||
ArtifactType: ftypes.ArtifactAWSAccount,
|
||||
ArtifactType: artifact.TypeAWSAccount,
|
||||
Results: filtered,
|
||||
}
|
||||
|
||||
|
||||
@@ -4,10 +4,13 @@ import (
|
||||
"context"
|
||||
"sort"
|
||||
|
||||
"github.com/google/go-containerregistry/pkg/v1"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/analyzer"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/walker"
|
||||
"github.com/aquasecurity/trivy/pkg/misconf"
|
||||
"github.com/aquasecurity/trivy/pkg/sbom/core"
|
||||
)
|
||||
|
||||
type Option struct {
|
||||
@@ -72,6 +75,39 @@ func (o *Option) Sort() {
|
||||
}
|
||||
|
||||
type Artifact interface {
|
||||
Inspect(ctx context.Context) (reference types.ArtifactReference, err error)
|
||||
Clean(reference types.ArtifactReference) error
|
||||
Inspect(ctx context.Context) (reference Reference, err error)
|
||||
Clean(reference Reference) error
|
||||
}
|
||||
|
||||
// Type represents a type of artifact
|
||||
type Type string
|
||||
|
||||
const (
|
||||
TypeContainerImage Type = "container_image"
|
||||
TypeFilesystem Type = "filesystem"
|
||||
TypeRepository Type = "repository"
|
||||
TypeCycloneDX Type = "cyclonedx"
|
||||
TypeSPDX Type = "spdx"
|
||||
TypeAWSAccount Type = "aws_account"
|
||||
TypeVM Type = "vm"
|
||||
)
|
||||
|
||||
// Reference represents a reference of container image, local filesystem and repository
|
||||
type Reference struct {
|
||||
Name string // image name, tar file name, directory or repository name
|
||||
Type Type
|
||||
ID string
|
||||
BlobIDs []string
|
||||
ImageMetadata ImageMetadata
|
||||
|
||||
// SBOM
|
||||
BOM *core.BOM
|
||||
}
|
||||
|
||||
type ImageMetadata struct {
|
||||
ID string // image ID
|
||||
DiffIDs []string // uncompressed layer IDs
|
||||
RepoTags []string
|
||||
RepoDigests []string
|
||||
ConfigFile v1.ConfigFile
|
||||
}
|
||||
|
||||
@@ -73,16 +73,16 @@ func NewArtifact(img types.Image, c cache.ArtifactCache, opt artifact.Option) (a
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a Artifact) Inspect(ctx context.Context) (types.ArtifactReference, error) {
|
||||
func (a Artifact) Inspect(ctx context.Context) (artifact.Reference, error) {
|
||||
imageID, err := a.image.ID()
|
||||
if err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("unable to get the image ID: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("unable to get the image ID: %w", err)
|
||||
}
|
||||
a.logger.Debug("Detected image ID", log.String("image_id", imageID))
|
||||
|
||||
configFile, err := a.image.ConfigFile()
|
||||
if err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("unable to get the image's config file: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("unable to get the image's config file: %w", err)
|
||||
}
|
||||
|
||||
diffIDs := a.diffIDs(configFile)
|
||||
@@ -94,7 +94,7 @@ func (a Artifact) Inspect(ctx context.Context) (types.ArtifactReference, error)
|
||||
return res, nil
|
||||
} else if !errors.Is(err, errNoSBOMFound) {
|
||||
// Fail on unexpected error, otherwise it falls into the usual scanning.
|
||||
return types.ArtifactReference{}, xerrors.Errorf("remote SBOM fetching error: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("remote SBOM fetching error: %w", err)
|
||||
}
|
||||
|
||||
// Try to detect base layers.
|
||||
@@ -104,7 +104,7 @@ func (a Artifact) Inspect(ctx context.Context) (types.ArtifactReference, error)
|
||||
// Convert image ID and layer IDs to cache keys
|
||||
imageKey, layerKeys, err := a.calcCacheKeys(imageID, diffIDs)
|
||||
if err != nil {
|
||||
return types.ArtifactReference{}, err
|
||||
return artifact.Reference{}, err
|
||||
}
|
||||
|
||||
// Parse histories and extract a list of "created_by"
|
||||
@@ -112,7 +112,7 @@ func (a Artifact) Inspect(ctx context.Context) (types.ArtifactReference, error)
|
||||
|
||||
missingImage, missingLayers, err := a.cache.MissingBlobs(imageKey, layerKeys)
|
||||
if err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("unable to get missing layers: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("unable to get missing layers: %w", err)
|
||||
}
|
||||
|
||||
missingImageKey := imageKey
|
||||
@@ -123,15 +123,15 @@ func (a Artifact) Inspect(ctx context.Context) (types.ArtifactReference, error)
|
||||
}
|
||||
|
||||
if err = a.inspect(ctx, missingImageKey, missingLayers, baseDiffIDs, layerKeyMap, configFile); err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("analyze error: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("analyze error: %w", err)
|
||||
}
|
||||
|
||||
return types.ArtifactReference{
|
||||
return artifact.Reference{
|
||||
Name: a.image.Name(),
|
||||
Type: types.ArtifactContainerImage,
|
||||
Type: artifact.TypeContainerImage,
|
||||
ID: imageKey,
|
||||
BlobIDs: layerKeys,
|
||||
ImageMetadata: types.ImageMetadata{
|
||||
ImageMetadata: artifact.ImageMetadata{
|
||||
ID: imageID,
|
||||
DiffIDs: diffIDs,
|
||||
RepoTags: a.image.RepoTags(),
|
||||
@@ -141,7 +141,7 @@ func (a Artifact) Inspect(ctx context.Context) (types.ArtifactReference, error)
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (Artifact) Clean(_ types.ArtifactReference) error {
|
||||
func (Artifact) Clean(_ artifact.Reference) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -340,7 +340,7 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
missingBlobsExpectation cache.ArtifactCacheMissingBlobsExpectation
|
||||
putBlobExpectations []cache.ArtifactCachePutBlobExpectation
|
||||
putArtifactExpectations []cache.ArtifactCachePutArtifactExpectation
|
||||
want types.ArtifactReference
|
||||
want artifact.Reference
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
@@ -425,12 +425,12 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "../../test/testdata/alpine-311.tar.gz",
|
||||
Type: types.ArtifactContainerImage,
|
||||
Type: artifact.TypeContainerImage,
|
||||
ID: "sha256:c232b7d8ac8aa08aa767313d0b53084c4380d1c01a213a5971bdb039e6538313",
|
||||
BlobIDs: []string{"sha256:1fd280c63e1416a2261e76454caa19a5b77c6bddedd48309c9687c4fe72b34c0"},
|
||||
ImageMetadata: types.ImageMetadata{
|
||||
ImageMetadata: artifact.ImageMetadata{
|
||||
ID: "sha256:a187dde48cd289ac374ad8539930628314bc581a481cdb41409c9289419ddb72",
|
||||
DiffIDs: []string{
|
||||
"sha256:beee9f30bc1f711043e78d4a2be0668955d4b761d587d6f60c2c8dc081efb203",
|
||||
@@ -1756,9 +1756,9 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "../../test/testdata/vuln-image.tar.gz",
|
||||
Type: types.ArtifactContainerImage,
|
||||
Type: artifact.TypeContainerImage,
|
||||
ID: "sha256:33f9415ed2cd5a9cef5d5144333619745b9ec0f851f0684dd45fa79c6b26a650",
|
||||
BlobIDs: []string{
|
||||
"sha256:dd0a4f4754bf4590327be34f4266f63c92184352afadb72e4c9b162f76224000",
|
||||
@@ -1766,7 +1766,7 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
"sha256:b6be0de11c6090f71dea119f43dd360335643420058e317baffb089f0dff4001",
|
||||
"sha256:37c561c19b169f5f9832f4b0060bf74ebc8d1c9e01662ad4fa21c394da159440",
|
||||
},
|
||||
ImageMetadata: types.ImageMetadata{
|
||||
ImageMetadata: artifact.ImageMetadata{
|
||||
ID: "sha256:58701fd185bda36cab0557bb6438661831267aa4a9e0b54211c4d5317a48aff4",
|
||||
DiffIDs: []string{
|
||||
"sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
|
||||
@@ -1921,9 +1921,9 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "../../test/testdata/vuln-image.tar.gz",
|
||||
Type: types.ArtifactContainerImage,
|
||||
Type: artifact.TypeContainerImage,
|
||||
ID: "sha256:33f9415ed2cd5a9cef5d5144333619745b9ec0f851f0684dd45fa79c6b26a650",
|
||||
BlobIDs: []string{
|
||||
"sha256:e1187118cdbe8893fc2fd4b345f813d195ee6aaeb4820d4576694199f8c10350",
|
||||
@@ -1931,7 +1931,7 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
"sha256:47adac0e28b12338e99dedbd7e8b0ef1f7aaa28e646f637ab2db8908b80704c8",
|
||||
"sha256:dd1082b33b17401fdc31bcbf60eaaecb9ce29e23956c50db6f34b2cc6cfa13c8",
|
||||
},
|
||||
ImageMetadata: types.ImageMetadata{
|
||||
ImageMetadata: artifact.ImageMetadata{
|
||||
ID: "sha256:58701fd185bda36cab0557bb6438661831267aa4a9e0b54211c4d5317a48aff4",
|
||||
DiffIDs: []string{
|
||||
"sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
sbomatt "github.com/aquasecurity/trivy/pkg/attestation/sbom"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact/sbom"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
@@ -24,9 +25,9 @@ import (
|
||||
|
||||
var errNoSBOMFound = xerrors.New("remote SBOM not found")
|
||||
|
||||
type inspectRemoteSBOM func(context.Context) (ftypes.ArtifactReference, error)
|
||||
type inspectRemoteSBOM func(context.Context) (artifact.Reference, error)
|
||||
|
||||
func (a Artifact) retrieveRemoteSBOM(ctx context.Context) (ftypes.ArtifactReference, error) {
|
||||
func (a Artifact) retrieveRemoteSBOM(ctx context.Context) (artifact.Reference, error) {
|
||||
for _, sbomSource := range a.artifactOption.SBOMSources {
|
||||
var inspect inspectRemoteSBOM
|
||||
switch sbomSource {
|
||||
@@ -45,27 +46,27 @@ func (a Artifact) retrieveRemoteSBOM(ctx context.Context) (ftypes.ArtifactRefere
|
||||
a.logger.Debug("No SBOM found in the source", log.String("source", sbomSource))
|
||||
continue
|
||||
} else if err != nil {
|
||||
return ftypes.ArtifactReference{}, xerrors.Errorf("SBOM searching error: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("SBOM searching error: %w", err)
|
||||
}
|
||||
return ref, nil
|
||||
}
|
||||
return ftypes.ArtifactReference{}, errNoSBOMFound
|
||||
return artifact.Reference{}, errNoSBOMFound
|
||||
}
|
||||
|
||||
func (a Artifact) inspectOCIReferrerSBOM(ctx context.Context) (ftypes.ArtifactReference, error) {
|
||||
func (a Artifact) inspectOCIReferrerSBOM(ctx context.Context) (artifact.Reference, error) {
|
||||
digest, err := repoDigest(a.image, a.artifactOption.Insecure)
|
||||
if err != nil {
|
||||
return ftypes.ArtifactReference{}, xerrors.Errorf("repo digest error: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("repo digest error: %w", err)
|
||||
}
|
||||
|
||||
// Fetch referrers
|
||||
index, err := remote.Referrers(ctx, digest, a.artifactOption.ImageOption.RegistryOptions)
|
||||
if err != nil {
|
||||
return ftypes.ArtifactReference{}, xerrors.Errorf("unable to fetch referrers: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("unable to fetch referrers: %w", err)
|
||||
}
|
||||
manifest, err := index.IndexManifest()
|
||||
if err != nil {
|
||||
return ftypes.ArtifactReference{}, xerrors.Errorf("unable to get manifest: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("unable to get manifest: %w", err)
|
||||
}
|
||||
for _, m := range lo.FromPtr(manifest).Manifests {
|
||||
// Unsupported artifact type
|
||||
@@ -80,20 +81,20 @@ func (a Artifact) inspectOCIReferrerSBOM(ctx context.Context) (ftypes.ArtifactRe
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
return ftypes.ArtifactReference{}, errNoSBOMFound
|
||||
return artifact.Reference{}, errNoSBOMFound
|
||||
}
|
||||
|
||||
func (a Artifact) parseReferrer(ctx context.Context, repo string, desc v1.Descriptor) (ftypes.ArtifactReference, error) {
|
||||
func (a Artifact) parseReferrer(ctx context.Context, repo string, desc v1.Descriptor) (artifact.Reference, error) {
|
||||
const fileName string = "referrer.sbom"
|
||||
repoName := fmt.Sprintf("%s@%s", repo, desc.Digest)
|
||||
referrer, err := oci.NewArtifact(repoName, true, a.artifactOption.ImageOption.RegistryOptions)
|
||||
if err != nil {
|
||||
return ftypes.ArtifactReference{}, xerrors.Errorf("OCI error: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("OCI error: %w", err)
|
||||
}
|
||||
|
||||
tmpDir, err := os.MkdirTemp("", "trivy-sbom-*")
|
||||
if err != nil {
|
||||
return ftypes.ArtifactReference{}, xerrors.Errorf("mkdir temp error: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("mkdir temp error: %w", err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
@@ -102,7 +103,7 @@ func (a Artifact) parseReferrer(ctx context.Context, repo string, desc v1.Descri
|
||||
MediaType: desc.ArtifactType,
|
||||
Filename: fileName,
|
||||
}); err != nil {
|
||||
return ftypes.ArtifactReference{}, xerrors.Errorf("SBOM download error: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("SBOM download error: %w", err)
|
||||
}
|
||||
|
||||
res, err := a.inspectSBOMFile(ctx, filepath.Join(tmpDir, fileName))
|
||||
@@ -116,35 +117,35 @@ func (a Artifact) parseReferrer(ctx context.Context, repo string, desc v1.Descri
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (a Artifact) inspectRekorSBOMAttestation(ctx context.Context) (ftypes.ArtifactReference, error) {
|
||||
func (a Artifact) inspectRekorSBOMAttestation(ctx context.Context) (artifact.Reference, error) {
|
||||
digest, err := repoDigest(a.image, a.artifactOption.Insecure)
|
||||
if err != nil {
|
||||
return ftypes.ArtifactReference{}, xerrors.Errorf("repo digest error: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("repo digest error: %w", err)
|
||||
}
|
||||
|
||||
client, err := sbomatt.NewRekor(a.artifactOption.RekorURL)
|
||||
if err != nil {
|
||||
return ftypes.ArtifactReference{}, xerrors.Errorf("failed to create rekor client: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("failed to create rekor client: %w", err)
|
||||
}
|
||||
|
||||
raw, err := client.RetrieveSBOM(ctx, digest.DigestStr())
|
||||
if errors.Is(err, sbomatt.ErrNoSBOMAttestation) {
|
||||
return ftypes.ArtifactReference{}, errNoSBOMFound
|
||||
return artifact.Reference{}, errNoSBOMFound
|
||||
} else if err != nil {
|
||||
return ftypes.ArtifactReference{}, xerrors.Errorf("failed to retrieve SBOM attestation: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("failed to retrieve SBOM attestation: %w", err)
|
||||
}
|
||||
|
||||
f, err := os.CreateTemp("", "sbom-*")
|
||||
if err != nil {
|
||||
return ftypes.ArtifactReference{}, xerrors.Errorf("failed to create a temporary file: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("failed to create a temporary file: %w", err)
|
||||
}
|
||||
defer os.Remove(f.Name())
|
||||
|
||||
if _, err = f.Write(raw); err != nil {
|
||||
return ftypes.ArtifactReference{}, xerrors.Errorf("copy error: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("copy error: %w", err)
|
||||
}
|
||||
if err = f.Close(); err != nil {
|
||||
return ftypes.ArtifactReference{}, xerrors.Errorf("failed to close %s: %w", f.Name(), err)
|
||||
return artifact.Reference{}, xerrors.Errorf("failed to close %s: %w", f.Name(), err)
|
||||
}
|
||||
res, err := a.inspectSBOMFile(ctx, f.Name())
|
||||
if err != nil {
|
||||
@@ -158,15 +159,15 @@ func (a Artifact) inspectRekorSBOMAttestation(ctx context.Context) (ftypes.Artif
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (a Artifact) inspectSBOMFile(ctx context.Context, filePath string) (ftypes.ArtifactReference, error) {
|
||||
func (a Artifact) inspectSBOMFile(ctx context.Context, filePath string) (artifact.Reference, error) {
|
||||
ar, err := sbom.NewArtifact(filePath, a.cache, a.artifactOption)
|
||||
if err != nil {
|
||||
return ftypes.ArtifactReference{}, xerrors.Errorf("failed to new artifact: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("failed to new artifact: %w", err)
|
||||
}
|
||||
|
||||
results, err := ar.Inspect(ctx)
|
||||
if err != nil {
|
||||
return ftypes.ArtifactReference{}, xerrors.Errorf("failed to inspect: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("failed to inspect: %w", err)
|
||||
}
|
||||
results.Name = a.image.Name()
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ func TestArtifact_InspectRekorAttestation(t *testing.T) {
|
||||
fields fields
|
||||
artifactOpt artifact.Option
|
||||
putBlobExpectations []cache.ArtifactCachePutBlobExpectation
|
||||
want types.ArtifactReference
|
||||
want artifact.Reference
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
@@ -117,9 +117,9 @@ func TestArtifact_InspectRekorAttestation(t *testing.T) {
|
||||
artifactOpt: artifact.Option{
|
||||
SBOMSources: []string{"rekor"},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "test/image:10",
|
||||
Type: types.ArtifactCycloneDX,
|
||||
Type: artifact.TypeCycloneDX,
|
||||
ID: "sha256:066b9998617ffb7dfe0a3219ac5c3efc1008a6223606fcf474e7d5c965e4e8da",
|
||||
BlobIDs: []string{
|
||||
"sha256:066b9998617ffb7dfe0a3219ac5c3efc1008a6223606fcf474e7d5c965e4e8da",
|
||||
@@ -206,7 +206,7 @@ func TestArtifact_inspectOCIReferrerSBOM(t *testing.T) {
|
||||
fields fields
|
||||
artifactOpt artifact.Option
|
||||
putBlobExpectations []cache.ArtifactCachePutBlobExpectation
|
||||
want types.ArtifactReference
|
||||
want artifact.Reference
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
@@ -265,9 +265,9 @@ func TestArtifact_inspectOCIReferrerSBOM(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: registry + "/test/image:10",
|
||||
Type: types.ArtifactCycloneDX,
|
||||
Type: artifact.TypeCycloneDX,
|
||||
ID: "sha256:a06ed679a3289fba254040e1ce8f3467fadcc454ee3d0d4720f6978065f56684",
|
||||
BlobIDs: []string{
|
||||
"sha256:a06ed679a3289fba254040e1ce8f3467fadcc454ee3d0d4720f6978065f56684",
|
||||
|
||||
@@ -68,7 +68,7 @@ func NewArtifact(rootPath string, c cache.ArtifactCache, w Walker, opt artifact.
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a Artifact) Inspect(ctx context.Context) (types.ArtifactReference, error) {
|
||||
func (a Artifact) Inspect(ctx context.Context) (artifact.Reference, error) {
|
||||
var wg sync.WaitGroup
|
||||
result := analyzer.NewAnalysisResult()
|
||||
limit := semaphore.New(a.artifactOption.Parallel)
|
||||
@@ -80,7 +80,7 @@ func (a Artifact) Inspect(ctx context.Context) (types.ArtifactReference, error)
|
||||
// Prepare filesystem for post analysis
|
||||
composite, err := a.analyzer.PostAnalyzerFS()
|
||||
if err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("failed to prepare filesystem for post analysis: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("failed to prepare filesystem for post analysis: %w", err)
|
||||
}
|
||||
|
||||
err = a.walker.Walk(a.rootPath, a.artifactOption.WalkerOption, func(filePath string, info os.FileInfo, opener analyzer.Opener) error {
|
||||
@@ -110,7 +110,7 @@ func (a Artifact) Inspect(ctx context.Context) (types.ArtifactReference, error)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("walk filesystem: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("walk filesystem: %w", err)
|
||||
}
|
||||
|
||||
// Wait for all the goroutine to finish.
|
||||
@@ -118,7 +118,7 @@ func (a Artifact) Inspect(ctx context.Context) (types.ArtifactReference, error)
|
||||
|
||||
// Post-analysis
|
||||
if err = a.analyzer.PostAnalyze(ctx, composite, result, opts); err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("post analysis error: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("post analysis error: %w", err)
|
||||
}
|
||||
|
||||
// Sort the analysis result for consistent results
|
||||
@@ -137,16 +137,16 @@ func (a Artifact) Inspect(ctx context.Context) (types.ArtifactReference, error)
|
||||
}
|
||||
|
||||
if err = a.handlerManager.PostHandle(ctx, result, &blobInfo); err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("failed to call hooks: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("failed to call hooks: %w", err)
|
||||
}
|
||||
|
||||
cacheKey, err := a.calcCacheKey(blobInfo)
|
||||
if err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("failed to calculate a cache key: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("failed to calculate a cache key: %w", err)
|
||||
}
|
||||
|
||||
if err = a.cache.PutBlob(cacheKey, blobInfo); err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("failed to store blob (%s) in cache: %w", cacheKey, err)
|
||||
return artifact.Reference{}, xerrors.Errorf("failed to store blob (%s) in cache: %w", cacheKey, err)
|
||||
}
|
||||
|
||||
// get hostname
|
||||
@@ -159,15 +159,15 @@ func (a Artifact) Inspect(ctx context.Context) (types.ArtifactReference, error)
|
||||
hostName = filepath.ToSlash(a.rootPath)
|
||||
}
|
||||
|
||||
return types.ArtifactReference{
|
||||
return artifact.Reference{
|
||||
Name: hostName,
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: cacheKey, // use a cache key as pseudo artifact ID
|
||||
BlobIDs: []string{cacheKey},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a Artifact) Clean(reference types.ArtifactReference) error {
|
||||
func (a Artifact) Clean(reference artifact.Reference) error {
|
||||
return a.cache.DeleteBlobs(reference.BlobIDs)
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
disabledAnalyzers []analyzer.Type
|
||||
disabledHandlers []types.HandlerType
|
||||
putBlobExpectation cache.ArtifactCachePutBlobExpectation
|
||||
want types.ArtifactReference
|
||||
want artifact.Reference
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
@@ -78,9 +78,9 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "host",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:afc2bc421aac8c61d89d4dd1c1865efb5441e3877c8a4c919232729d7c574dab",
|
||||
BlobIDs: []string{
|
||||
"sha256:afc2bc421aac8c61d89d4dd1c1865efb5441e3877c8a4c919232729d7c574dab",
|
||||
@@ -108,9 +108,9 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "host",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:7db98974b2231d3e25f4890008c4d42f6f26a7da5a8aba99e954dec97f050bd6",
|
||||
BlobIDs: []string{
|
||||
"sha256:7db98974b2231d3e25f4890008c4d42f6f26a7da5a8aba99e954dec97f050bd6",
|
||||
@@ -193,9 +193,9 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/requirements.txt",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:9e999fcf6fd571e175601fb7cc0da28f0d7960e26eab67dad93152e0bebf21ca",
|
||||
BlobIDs: []string{
|
||||
"sha256:9e999fcf6fd571e175601fb7cc0da28f0d7960e26eab67dad93152e0bebf21ca",
|
||||
@@ -228,9 +228,9 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/requirements.txt",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:9e999fcf6fd571e175601fb7cc0da28f0d7960e26eab67dad93152e0bebf21ca",
|
||||
BlobIDs: []string{
|
||||
"sha256:9e999fcf6fd571e175601fb7cc0da28f0d7960e26eab67dad93152e0bebf21ca",
|
||||
@@ -279,7 +279,7 @@ func TestTerraformMisconfigurationScan(t *testing.T) {
|
||||
fields fields
|
||||
putBlobExpectation cache.ArtifactCachePutBlobExpectation
|
||||
artifactOpt artifact.Option
|
||||
want types.ArtifactReference
|
||||
want artifact.Reference
|
||||
}{
|
||||
{
|
||||
name: "single failure",
|
||||
@@ -325,9 +325,9 @@ func TestTerraformMisconfigurationScan(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/misconfig/terraform/single-failure",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:1a6ce0acc3b57eb6c830c96fcd868fec1eb4d3b57ad51e481c76d85f22870a65",
|
||||
BlobIDs: []string{
|
||||
"sha256:1a6ce0acc3b57eb6c830c96fcd868fec1eb4d3b57ad51e481c76d85f22870a65",
|
||||
@@ -410,9 +410,9 @@ func TestTerraformMisconfigurationScan(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/misconfig/terraform/multiple-failures",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:afc20cf0fc99c62bbc79b00cb9fbc70ba7ee76c946a6d560639ba9279344787d",
|
||||
BlobIDs: []string{
|
||||
"sha256:afc20cf0fc99c62bbc79b00cb9fbc70ba7ee76c946a6d560639ba9279344787d",
|
||||
@@ -440,9 +440,9 @@ func TestTerraformMisconfigurationScan(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/misconfig/terraform/no-results",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:1827b6a0b0a17e0d623a2045e9d9c331ef613390eda2fed823969ee0dd730257",
|
||||
BlobIDs: []string{
|
||||
"sha256:1827b6a0b0a17e0d623a2045e9d9c331ef613390eda2fed823969ee0dd730257",
|
||||
@@ -489,9 +489,9 @@ func TestTerraformMisconfigurationScan(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/misconfig/terraform/passed",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:eec58ef10d1b04df4af76b2472e615f8c27e253a16f90d7542670a7001d88915",
|
||||
BlobIDs: []string{
|
||||
"sha256:eec58ef10d1b04df4af76b2472e615f8c27e253a16f90d7542670a7001d88915",
|
||||
@@ -555,9 +555,9 @@ func TestTerraformMisconfigurationScan(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/misconfig/terraform/busted-relative-paths/child/main.tf",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:8db34d644bfb98077180616caeab0b41a26d9029a47a23d4b36e1d6e45584919",
|
||||
BlobIDs: []string{
|
||||
"sha256:8db34d644bfb98077180616caeab0b41a26d9029a47a23d4b36e1d6e45584919",
|
||||
@@ -605,9 +605,9 @@ func TestTerraformMisconfigurationScan(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/misconfig/terraform/tfvar-outside/tf",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:eec58ef10d1b04df4af76b2472e615f8c27e253a16f90d7542670a7001d88915",
|
||||
BlobIDs: []string{
|
||||
"sha256:eec58ef10d1b04df4af76b2472e615f8c27e253a16f90d7542670a7001d88915",
|
||||
@@ -695,9 +695,9 @@ func TestTerraformMisconfigurationScan(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/misconfig/terraform/relative-paths/child",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:f13b89447db61be1c1e4099ef18aec7272091f8f2d3581643a9d1fabc74eda83",
|
||||
BlobIDs: []string{
|
||||
"sha256:f13b89447db61be1c1e4099ef18aec7272091f8f2d3581643a9d1fabc74eda83",
|
||||
@@ -776,7 +776,7 @@ func TestTerraformPlanSnapshotMisconfScan(t *testing.T) {
|
||||
name string
|
||||
fields fields
|
||||
putBlobExpectation cache.ArtifactCachePutBlobExpectation
|
||||
want types.ArtifactReference
|
||||
want artifact.Reference
|
||||
}{
|
||||
{
|
||||
name: "single failure",
|
||||
@@ -814,9 +814,9 @@ func TestTerraformPlanSnapshotMisconfScan(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/misconfig/terraformplan/snapshots/single-failure",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:732c38451bde877a94d1ff5b6f2019655bed04fd24b1169de195eeee1199045e",
|
||||
BlobIDs: []string{
|
||||
"sha256:732c38451bde877a94d1ff5b6f2019655bed04fd24b1169de195eeee1199045e",
|
||||
@@ -890,9 +890,9 @@ func TestTerraformPlanSnapshotMisconfScan(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/misconfig/terraformplan/snapshots/multiple-failures",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:752c0b470adfcfe7e21892cf4c6fc3bc28dba873c9c1696f40b71b7a51ad7231",
|
||||
BlobIDs: []string{
|
||||
"sha256:752c0b470adfcfe7e21892cf4c6fc3bc28dba873c9c1696f40b71b7a51ad7231",
|
||||
@@ -930,9 +930,9 @@ func TestTerraformPlanSnapshotMisconfScan(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/misconfig/terraformplan/snapshots/passed",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:8947704a08f54ab1df32cd905d6bca72edf1785a42702968bafa331172da7176",
|
||||
BlobIDs: []string{
|
||||
"sha256:8947704a08f54ab1df32cd905d6bca72edf1785a42702968bafa331172da7176",
|
||||
@@ -990,7 +990,7 @@ func TestCloudFormationMisconfigurationScan(t *testing.T) {
|
||||
fields fields
|
||||
putBlobExpectation cache.ArtifactCachePutBlobExpectation
|
||||
artifactOpt artifact.Option
|
||||
want types.ArtifactReference
|
||||
want artifact.Reference
|
||||
}{
|
||||
{
|
||||
name: "single failure",
|
||||
@@ -1045,9 +1045,9 @@ func TestCloudFormationMisconfigurationScan(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/misconfig/cloudformation/single-failure/src",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:889a94522970c6e55f1f7543914b2f0131f79f9c4526445fb95309f64a9947d7",
|
||||
BlobIDs: []string{
|
||||
"sha256:889a94522970c6e55f1f7543914b2f0131f79f9c4526445fb95309f64a9947d7",
|
||||
@@ -1129,9 +1129,9 @@ func TestCloudFormationMisconfigurationScan(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/misconfig/cloudformation/multiple-failures/src",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:17c9c72a759856445e6d3847b2d5ed90c3bad3e4ee50cea0c812ef53c179f8ca",
|
||||
BlobIDs: []string{
|
||||
"sha256:17c9c72a759856445e6d3847b2d5ed90c3bad3e4ee50cea0c812ef53c179f8ca",
|
||||
@@ -1161,9 +1161,9 @@ func TestCloudFormationMisconfigurationScan(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/misconfig/cloudformation/no-results/src",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:26c76a2cb55cb0ef2c3a2dd79e237bddb508ca2c4cefdb103698a1972c8a9c2d",
|
||||
BlobIDs: []string{
|
||||
"sha256:26c76a2cb55cb0ef2c3a2dd79e237bddb508ca2c4cefdb103698a1972c8a9c2d",
|
||||
@@ -1219,9 +1219,9 @@ func TestCloudFormationMisconfigurationScan(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/misconfig/cloudformation/params/code/src",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:267b572211115db6a2a4484a02317fbb6d4f050da0e95b1db4243d49889483de",
|
||||
BlobIDs: []string{
|
||||
"sha256:267b572211115db6a2a4484a02317fbb6d4f050da0e95b1db4243d49889483de",
|
||||
@@ -1277,9 +1277,9 @@ func TestCloudFormationMisconfigurationScan(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/misconfig/cloudformation/passed/src",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:8ca92725ce2f47b7ffb1b0a9e0359d59ac2b3b3f517ba42f66a859436057e54a",
|
||||
BlobIDs: []string{
|
||||
"sha256:8ca92725ce2f47b7ffb1b0a9e0359d59ac2b3b3f517ba42f66a859436057e54a",
|
||||
@@ -1314,7 +1314,7 @@ func TestDockerfileMisconfigurationScan(t *testing.T) {
|
||||
fields fields
|
||||
putBlobExpectation cache.ArtifactCachePutBlobExpectation
|
||||
artifactOpt artifact.Option
|
||||
want types.ArtifactReference
|
||||
want artifact.Reference
|
||||
}{
|
||||
{
|
||||
name: "single failure",
|
||||
@@ -1365,9 +1365,9 @@ func TestDockerfileMisconfigurationScan(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/misconfig/dockerfile/single-failure/src",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:627cbf451ec7929dfe5151dfe0e2305ed855906bf79136f198528a0cc3f6e4f9",
|
||||
BlobIDs: []string{
|
||||
"sha256:627cbf451ec7929dfe5151dfe0e2305ed855906bf79136f198528a0cc3f6e4f9",
|
||||
@@ -1423,9 +1423,9 @@ func TestDockerfileMisconfigurationScan(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/misconfig/dockerfile/multiple-failures/src",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:627cbf451ec7929dfe5151dfe0e2305ed855906bf79136f198528a0cc3f6e4f9",
|
||||
BlobIDs: []string{
|
||||
"sha256:627cbf451ec7929dfe5151dfe0e2305ed855906bf79136f198528a0cc3f6e4f9",
|
||||
@@ -1453,9 +1453,9 @@ func TestDockerfileMisconfigurationScan(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/misconfig/dockerfile/no-results/src",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:26c76a2cb55cb0ef2c3a2dd79e237bddb508ca2c4cefdb103698a1972c8a9c2d",
|
||||
BlobIDs: []string{
|
||||
"sha256:26c76a2cb55cb0ef2c3a2dd79e237bddb508ca2c4cefdb103698a1972c8a9c2d",
|
||||
@@ -1513,9 +1513,9 @@ func TestDockerfileMisconfigurationScan(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/misconfig/dockerfile/passed/src",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:4cc7f6bba417cc65c5391bc9c07fd1e205e21bdec87b271889433af18be1e454",
|
||||
BlobIDs: []string{
|
||||
"sha256:4cc7f6bba417cc65c5391bc9c07fd1e205e21bdec87b271889433af18be1e454",
|
||||
@@ -1549,7 +1549,7 @@ func TestKubernetesMisconfigurationScan(t *testing.T) {
|
||||
fields fields
|
||||
putBlobExpectation cache.ArtifactCachePutBlobExpectation
|
||||
artifactOpt artifact.Option
|
||||
want types.ArtifactReference
|
||||
want artifact.Reference
|
||||
}{
|
||||
{
|
||||
name: "single failure",
|
||||
@@ -1605,9 +1605,9 @@ func TestKubernetesMisconfigurationScan(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/misconfig/kubernetes/single-failure/src",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:d5ca0b4e96aaaeafa424a2250db6297a5182cb6ca5db49bc1ff11790f6cdbee9",
|
||||
BlobIDs: []string{
|
||||
"sha256:d5ca0b4e96aaaeafa424a2250db6297a5182cb6ca5db49bc1ff11790f6cdbee9",
|
||||
@@ -1691,9 +1691,9 @@ func TestKubernetesMisconfigurationScan(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/misconfig/kubernetes/multiple-failures/src",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:eef9fff2fe8f5c4a123c018b4f91db25d9676e7d171a3a683c2fbfbbbe82fa54",
|
||||
BlobIDs: []string{
|
||||
"sha256:eef9fff2fe8f5c4a123c018b4f91db25d9676e7d171a3a683c2fbfbbbe82fa54",
|
||||
@@ -1721,9 +1721,9 @@ func TestKubernetesMisconfigurationScan(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/misconfig/kubernetes/no-results/src",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:2b54cf33feaa1fe1f5bf223f873ca6c3f7c3693b0bb3b0ce9e2e7fd79cd37b5a",
|
||||
BlobIDs: []string{
|
||||
"sha256:2b54cf33feaa1fe1f5bf223f873ca6c3f7c3693b0bb3b0ce9e2e7fd79cd37b5a",
|
||||
@@ -1781,9 +1781,9 @@ func TestKubernetesMisconfigurationScan(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/misconfig/kubernetes/passed/src",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:dc7a0fd3ea2f13b0ea05f4e517a16e602b0fc17fbd72aa5e34107ef12a91a30b",
|
||||
BlobIDs: []string{
|
||||
"sha256:dc7a0fd3ea2f13b0ea05f4e517a16e602b0fc17fbd72aa5e34107ef12a91a30b",
|
||||
@@ -1817,7 +1817,7 @@ func TestAzureARMMisconfigurationScan(t *testing.T) {
|
||||
fields fields
|
||||
putBlobExpectation cache.ArtifactCachePutBlobExpectation
|
||||
artifactOpt artifact.Option
|
||||
want types.ArtifactReference
|
||||
want artifact.Reference
|
||||
}{
|
||||
{
|
||||
name: "single failure",
|
||||
@@ -1870,9 +1870,9 @@ func TestAzureARMMisconfigurationScan(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/misconfig/azurearm/single-failure/src",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:c1a8bfd544b9041ad194382cc42b54289f70966d061ef501b267aec8fd07c5df",
|
||||
BlobIDs: []string{
|
||||
"sha256:c1a8bfd544b9041ad194382cc42b54289f70966d061ef501b267aec8fd07c5df",
|
||||
@@ -1952,9 +1952,9 @@ func TestAzureARMMisconfigurationScan(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/misconfig/azurearm/multiple-failures/src",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:75bf0e88f8d2857be90fb8d10a350c04c1532ba7f510e1eb404a8bae30ce97d8",
|
||||
BlobIDs: []string{
|
||||
"sha256:75bf0e88f8d2857be90fb8d10a350c04c1532ba7f510e1eb404a8bae30ce97d8",
|
||||
@@ -1982,9 +1982,9 @@ func TestAzureARMMisconfigurationScan(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/misconfig/azurearm/no-results/src",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:26c76a2cb55cb0ef2c3a2dd79e237bddb508ca2c4cefdb103698a1972c8a9c2d",
|
||||
BlobIDs: []string{
|
||||
"sha256:26c76a2cb55cb0ef2c3a2dd79e237bddb508ca2c4cefdb103698a1972c8a9c2d",
|
||||
@@ -2038,9 +2038,9 @@ func TestAzureARMMisconfigurationScan(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/misconfig/azurearm/passed/src",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
ID: "sha256:b9ba7c4eafec405c8b6998dbb98ee1c7f7830caf8487fd1461433ff82d8779e9",
|
||||
BlobIDs: []string{
|
||||
"sha256:b9ba7c4eafec405c8b6998dbb98ee1c7f7830caf8487fd1461433ff82d8779e9",
|
||||
@@ -2074,7 +2074,7 @@ func TestMixedConfigurationScan(t *testing.T) {
|
||||
fields fields
|
||||
putBlobExpectation cache.ArtifactCachePutBlobExpectation
|
||||
artifactOpt artifact.Option
|
||||
want types.ArtifactReference
|
||||
want artifact.Reference
|
||||
}{
|
||||
{
|
||||
name: "single failure each within terraform and cloudformation",
|
||||
@@ -2157,9 +2157,9 @@ func TestMixedConfigurationScan(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "testdata/misconfig/mixed/src",
|
||||
Type: types.ArtifactFilesystem,
|
||||
Type: artifact.TypeFilesystem,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -6,8 +6,6 @@ import (
|
||||
context "context"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
types "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
)
|
||||
|
||||
// MockArtifact is an autogenerated mock type for the Artifact type
|
||||
@@ -16,7 +14,7 @@ type MockArtifact struct {
|
||||
}
|
||||
|
||||
type ArtifactCleanArgs struct {
|
||||
Reference types.ArtifactReference
|
||||
Reference Reference
|
||||
ReferenceAnything bool
|
||||
}
|
||||
|
||||
@@ -46,7 +44,7 @@ func (_m *MockArtifact) ApplyCleanExpectations(expectations []ArtifactCleanExpec
|
||||
}
|
||||
|
||||
// Clean provides a mock function with given fields: reference
|
||||
func (_m *MockArtifact) Clean(reference types.ArtifactReference) error {
|
||||
func (_m *MockArtifact) Clean(reference Reference) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -56,7 +54,7 @@ type ArtifactInspectArgs struct {
|
||||
}
|
||||
|
||||
type ArtifactInspectReturns struct {
|
||||
Reference types.ArtifactReference
|
||||
Reference Reference
|
||||
Err error
|
||||
}
|
||||
|
||||
@@ -82,14 +80,14 @@ func (_m *MockArtifact) ApplyInspectExpectations(expectations []ArtifactInspectE
|
||||
}
|
||||
|
||||
// Inspect provides a mock function with given fields: ctx
|
||||
func (_m *MockArtifact) Inspect(ctx context.Context) (types.ArtifactReference, error) {
|
||||
func (_m *MockArtifact) Inspect(ctx context.Context) (Reference, error) {
|
||||
ret := _m.Called(ctx)
|
||||
|
||||
var r0 types.ArtifactReference
|
||||
if rf, ok := ret.Get(0).(func(context.Context) types.ArtifactReference); ok {
|
||||
var r0 Reference
|
||||
if rf, ok := ret.Get(0).(func(context.Context) Reference); ok {
|
||||
r0 = rf(ctx)
|
||||
} else {
|
||||
r0 = ret.Get(0).(types.ArtifactReference)
|
||||
r0 = ret.Get(0).(Reference)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact/local"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/cache"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/walker"
|
||||
)
|
||||
|
||||
@@ -62,21 +61,21 @@ func NewArtifact(target string, c cache.ArtifactCache, w Walker, artifactOpt art
|
||||
return nil, cleanup, errs
|
||||
}
|
||||
|
||||
func (a Artifact) Inspect(ctx context.Context) (types.ArtifactReference, error) {
|
||||
func (a Artifact) Inspect(ctx context.Context) (artifact.Reference, error) {
|
||||
ref, err := a.local.Inspect(ctx)
|
||||
if err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("remote repository error: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("remote repository error: %w", err)
|
||||
}
|
||||
|
||||
if a.url != "" {
|
||||
ref.Name = a.url
|
||||
}
|
||||
ref.Type = types.ArtifactRepository
|
||||
ref.Type = artifact.TypeRepository
|
||||
|
||||
return ref, nil
|
||||
}
|
||||
|
||||
func (Artifact) Clean(_ types.ArtifactReference) error {
|
||||
func (Artifact) Clean(_ artifact.Reference) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -12,12 +12,10 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/cache"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
|
||||
_ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/config/all"
|
||||
_ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/secret"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/cache"
|
||||
)
|
||||
|
||||
func setupGitServer() (*httptest.Server, error) {
|
||||
@@ -186,15 +184,15 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
rawurl string
|
||||
want types.ArtifactReference
|
||||
want artifact.Reference
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "happy path",
|
||||
rawurl: ts.URL + "/test.git",
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: ts.URL + "/test.git",
|
||||
Type: types.ArtifactRepository,
|
||||
Type: artifact.TypeRepository,
|
||||
ID: "sha256:6a89d4fcd50f840a79da64523c255da80171acd3d286df2acc60056c778d9304",
|
||||
BlobIDs: []string{
|
||||
"sha256:6a89d4fcd50f840a79da64523c255da80171acd3d286df2acc60056c778d9304",
|
||||
|
||||
@@ -37,23 +37,23 @@ func NewArtifact(filePath string, c cache.ArtifactCache, opt artifact.Option) (a
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a Artifact) Inspect(_ context.Context) (types.ArtifactReference, error) {
|
||||
func (a Artifact) Inspect(_ context.Context) (artifact.Reference, error) {
|
||||
f, err := os.Open(a.filePath)
|
||||
if err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("failed to open sbom file error: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("failed to open sbom file error: %w", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
// Format auto-detection
|
||||
format, err := sbom.DetectFormat(f)
|
||||
if err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("failed to detect SBOM format: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("failed to detect SBOM format: %w", err)
|
||||
}
|
||||
log.Info("Detected SBOM format", log.String("format", string(format)))
|
||||
|
||||
bom, err := sbom.Decode(f, format)
|
||||
if err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("SBOM decode error: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("SBOM decode error: %w", err)
|
||||
}
|
||||
|
||||
blobInfo := types.BlobInfo{
|
||||
@@ -65,23 +65,23 @@ func (a Artifact) Inspect(_ context.Context) (types.ArtifactReference, error) {
|
||||
|
||||
cacheKey, err := a.calcCacheKey(blobInfo)
|
||||
if err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("failed to calculate a cache key: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("failed to calculate a cache key: %w", err)
|
||||
}
|
||||
|
||||
if err = a.cache.PutBlob(cacheKey, blobInfo); err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("failed to store blob (%s) in cache: %w", cacheKey, err)
|
||||
return artifact.Reference{}, xerrors.Errorf("failed to store blob (%s) in cache: %w", cacheKey, err)
|
||||
}
|
||||
|
||||
var artifactType types.ArtifactType
|
||||
var artifactType artifact.Type
|
||||
switch format {
|
||||
case sbom.FormatCycloneDXJSON, sbom.FormatCycloneDXXML, sbom.FormatAttestCycloneDXJSON, sbom.FormatLegacyCosignAttestCycloneDXJSON:
|
||||
artifactType = types.ArtifactCycloneDX
|
||||
artifactType = artifact.TypeCycloneDX
|
||||
case sbom.FormatSPDXTV, sbom.FormatSPDXJSON:
|
||||
artifactType = types.ArtifactSPDX
|
||||
artifactType = artifact.TypeSPDX
|
||||
|
||||
}
|
||||
|
||||
return types.ArtifactReference{
|
||||
return artifact.Reference{
|
||||
Name: a.filePath,
|
||||
Type: artifactType,
|
||||
ID: cacheKey, // use a cache key as pseudo artifact ID
|
||||
@@ -92,7 +92,7 @@ func (a Artifact) Inspect(_ context.Context) (types.ArtifactReference, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a Artifact) Clean(reference types.ArtifactReference) error {
|
||||
func (a Artifact) Clean(reference artifact.Reference) error {
|
||||
return a.cache.DeleteBlobs(reference.BlobIDs)
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
name string
|
||||
filePath string
|
||||
putBlobExpectation cache.ArtifactCachePutBlobExpectation
|
||||
want types.ArtifactReference
|
||||
want artifact.Reference
|
||||
wantErr []string
|
||||
}{
|
||||
{
|
||||
@@ -188,9 +188,9 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: filepath.Join("testdata", "bom.json"),
|
||||
Type: types.ArtifactCycloneDX,
|
||||
Type: artifact.TypeCycloneDX,
|
||||
ID: "sha256:76bc49ae239d24c6a122e730bafb9d5295d0af380492aeb92a3bf34bea3a14ca",
|
||||
BlobIDs: []string{
|
||||
"sha256:76bc49ae239d24c6a122e730bafb9d5295d0af380492aeb92a3bf34bea3a14ca",
|
||||
@@ -360,9 +360,9 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: filepath.Join("testdata", "sbom.cdx.intoto.jsonl"),
|
||||
Type: types.ArtifactCycloneDX,
|
||||
Type: artifact.TypeCycloneDX,
|
||||
ID: "sha256:76bc49ae239d24c6a122e730bafb9d5295d0af380492aeb92a3bf34bea3a14ca",
|
||||
BlobIDs: []string{
|
||||
"sha256:76bc49ae239d24c6a122e730bafb9d5295d0af380492aeb92a3bf34bea3a14ca",
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/cloud/aws/config"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
)
|
||||
|
||||
@@ -55,10 +55,10 @@ func newAMI(imageID string, storage Storage, region, endpoint string) (*AMI, err
|
||||
return nil, xerrors.New("no snapshot found")
|
||||
}
|
||||
|
||||
func (a *AMI) Inspect(ctx context.Context) (types.ArtifactReference, error) {
|
||||
func (a *AMI) Inspect(ctx context.Context) (artifact.Reference, error) {
|
||||
ref, err := a.EBS.Inspect(ctx)
|
||||
if err != nil {
|
||||
return types.ArtifactReference{}, err
|
||||
return artifact.Reference{}, err
|
||||
}
|
||||
ref.Name = a.imageID
|
||||
return ref, nil
|
||||
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/cloud/aws/config"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/cache"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
)
|
||||
|
||||
@@ -40,21 +40,21 @@ func newEBS(snapshotID string, vm Storage, region, endpoint string) (*EBS, error
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *EBS) Inspect(ctx context.Context) (types.ArtifactReference, error) {
|
||||
func (a *EBS) Inspect(ctx context.Context) (artifact.Reference, error) {
|
||||
sr, err := a.openEBS(ctx)
|
||||
if err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("EBS open error: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("EBS open error: %w", err)
|
||||
}
|
||||
|
||||
cacheKey, err := a.calcCacheKey(a.snapshotID)
|
||||
if err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("cache key calculation error: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("cache key calculation error: %w", err)
|
||||
}
|
||||
|
||||
if a.hasCache(cacheKey) {
|
||||
return types.ArtifactReference{
|
||||
return artifact.Reference{
|
||||
Name: a.snapshotID,
|
||||
Type: types.ArtifactVM,
|
||||
Type: artifact.TypeVM,
|
||||
ID: cacheKey, // use a cache key as pseudo artifact ID
|
||||
BlobIDs: []string{cacheKey},
|
||||
}, nil
|
||||
@@ -62,16 +62,16 @@ func (a *EBS) Inspect(ctx context.Context) (types.ArtifactReference, error) {
|
||||
|
||||
blobInfo, err := a.Analyze(ctx, sr)
|
||||
if err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("inspection error: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("inspection error: %w", err)
|
||||
}
|
||||
|
||||
if err = a.cache.PutBlob(cacheKey, blobInfo); err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("failed to store blob (%s) in cache: %w", cacheKey, err)
|
||||
return artifact.Reference{}, xerrors.Errorf("failed to store blob (%s) in cache: %w", cacheKey, err)
|
||||
}
|
||||
|
||||
return types.ArtifactReference{
|
||||
return artifact.Reference{
|
||||
Name: a.snapshotID,
|
||||
Type: types.ArtifactVM,
|
||||
Type: artifact.TypeVM,
|
||||
ID: cacheKey, // use a cache key as pseudo artifact ID
|
||||
BlobIDs: []string{cacheKey},
|
||||
}, nil
|
||||
@@ -90,7 +90,7 @@ func (a *EBS) openEBS(ctx context.Context) (*io.SectionReader, error) {
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (a *EBS) Clean(_ types.ArtifactReference) error {
|
||||
func (a *EBS) Clean(_ artifact.Reference) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/opencontainers/go-digest"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/cache"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/vm"
|
||||
@@ -68,24 +69,24 @@ func newFile(filePath string, storage Storage) (*ImageFile, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *ImageFile) Inspect(ctx context.Context) (types.ArtifactReference, error) {
|
||||
func (a *ImageFile) Inspect(ctx context.Context) (artifact.Reference, error) {
|
||||
blobInfo, err := a.Analyze(ctx, a.reader)
|
||||
if err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("inspection error: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("inspection error: %w", err)
|
||||
}
|
||||
|
||||
cacheKey, err := a.calcCacheKey(blobInfo)
|
||||
if err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("cache calculation error: %w", err)
|
||||
return artifact.Reference{}, xerrors.Errorf("cache calculation error: %w", err)
|
||||
}
|
||||
|
||||
if err = a.cache.PutBlob(cacheKey, blobInfo); err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("failed to store blob (%s) in cache: %w", cacheKey, err)
|
||||
return artifact.Reference{}, xerrors.Errorf("failed to store blob (%s) in cache: %w", cacheKey, err)
|
||||
}
|
||||
|
||||
return types.ArtifactReference{
|
||||
return artifact.Reference{
|
||||
Name: a.filePath,
|
||||
Type: types.ArtifactVM,
|
||||
Type: artifact.TypeVM,
|
||||
ID: cacheKey, // use a cache key as pseudo artifact ID
|
||||
BlobIDs: []string{cacheKey},
|
||||
}, nil
|
||||
@@ -107,7 +108,7 @@ func (a *ImageFile) calcCacheKey(blobInfo types.BlobInfo) (string, error) {
|
||||
return cacheKey, nil
|
||||
}
|
||||
|
||||
func (a *ImageFile) Clean(reference types.ArtifactReference) error {
|
||||
func (a *ImageFile) Clean(reference artifact.Reference) error {
|
||||
_ = a.file.Close()
|
||||
return a.cache.DeleteBlobs(reference.BlobIDs)
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
missingBlobsExpectation cache.ArtifactCacheMissingBlobsExpectation
|
||||
putBlobExpectation cache.ArtifactCachePutBlobExpectation
|
||||
putArtifactExpectations []cache.ArtifactCachePutArtifactExpectation
|
||||
want types.ArtifactReference
|
||||
want artifact.Reference
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
@@ -136,9 +136,9 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "rawdata.img",
|
||||
Type: types.ArtifactVM,
|
||||
Type: artifact.TypeVM,
|
||||
ID: "sha256:84a726d23c36d0e1857101969b257c1199de5432489d44581750d54ea8eff8cd",
|
||||
BlobIDs: []string{
|
||||
"sha256:84a726d23c36d0e1857101969b257c1199de5432489d44581750d54ea8eff8cd",
|
||||
@@ -172,9 +172,9 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
want: artifact.Reference{
|
||||
Name: "ebs-012345",
|
||||
Type: types.ArtifactVM,
|
||||
Type: artifact.TypeVM,
|
||||
ID: "sha256:c28da2df41e019b5d18459440178341ec05e9082b12b6f11afe73f0600bfe96a",
|
||||
BlobIDs: []string{
|
||||
"sha256:c28da2df41e019b5d18459440178341ec05e9082b12b6f11afe73f0600bfe96a",
|
||||
|
||||
@@ -295,13 +295,13 @@ func localImageTestWithNamespace(t *testing.T, namespace string) {
|
||||
name string
|
||||
imageName string
|
||||
tarArchive string
|
||||
wantMetadata types.ImageMetadata
|
||||
wantMetadata artifact.ImageMetadata
|
||||
}{
|
||||
{
|
||||
name: "alpine 3.10",
|
||||
imageName: "ghcr.io/aquasecurity/trivy-test-images:alpine-310",
|
||||
tarArchive: "../../../../integration/testdata/fixtures/images/alpine-310.tar.gz",
|
||||
wantMetadata: types.ImageMetadata{
|
||||
wantMetadata: artifact.ImageMetadata{
|
||||
ID: "sha256:961769676411f082461f9ef46626dd7a2d1e2b2a38e6a44364bcbecf51e66dd4",
|
||||
DiffIDs: []string{
|
||||
"sha256:03901b4a2ea88eeaad62dbe59b072b28b6efa00491962b8741081c5df50c65e0",
|
||||
@@ -349,7 +349,7 @@ func localImageTestWithNamespace(t *testing.T, namespace string) {
|
||||
name: "vulnimage",
|
||||
imageName: "ghcr.io/aquasecurity/trivy-test-images:vulnimage",
|
||||
tarArchive: "../../../../integration/testdata/fixtures/images/vulnimage.tar.gz",
|
||||
wantMetadata: types.ImageMetadata{
|
||||
wantMetadata: artifact.ImageMetadata{
|
||||
ID: "sha256:c17083664da903e13e9092fa3a3a1aeee2431aa2728298e3dbcec72f26369c41",
|
||||
DiffIDs: []string{
|
||||
"sha256:ebf12965380b39889c99a9c02e82ba465f887b45975b6e389d42e9e6a3857888",
|
||||
@@ -746,12 +746,12 @@ func TestContainerd_PullImage(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
imageName string
|
||||
wantMetadata types.ImageMetadata
|
||||
wantMetadata artifact.ImageMetadata
|
||||
}{
|
||||
{
|
||||
name: "remote alpine 3.10",
|
||||
imageName: "ghcr.io/aquasecurity/trivy-test-images:alpine-310",
|
||||
wantMetadata: types.ImageMetadata{
|
||||
wantMetadata: artifact.ImageMetadata{
|
||||
ID: "sha256:961769676411f082461f9ef46626dd7a2d1e2b2a38e6a44364bcbecf51e66dd4",
|
||||
DiffIDs: []string{
|
||||
"sha256:03901b4a2ea88eeaad62dbe59b072b28b6efa00491962b8741081c5df50c65e0",
|
||||
|
||||
@@ -1,17 +1,9 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||
"github.com/package-url/packageurl-go"
|
||||
"github.com/samber/lo"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/digest"
|
||||
"github.com/aquasecurity/trivy/pkg/sbom/core"
|
||||
)
|
||||
|
||||
type OS struct {
|
||||
@@ -66,260 +58,6 @@ type Layer struct {
|
||||
CreatedBy string `json:",omitempty"`
|
||||
}
|
||||
|
||||
type Relationship int
|
||||
|
||||
const (
|
||||
RelationshipUnknown Relationship = iota
|
||||
RelationshipRoot
|
||||
RelationshipDirect
|
||||
RelationshipIndirect
|
||||
)
|
||||
|
||||
var relationshipNames = [...]string{
|
||||
"unknown",
|
||||
"root",
|
||||
"direct",
|
||||
"indirect",
|
||||
}
|
||||
|
||||
func (r Relationship) String() string {
|
||||
if r <= RelationshipUnknown || int(r) >= len(relationshipNames) {
|
||||
return "unknown"
|
||||
}
|
||||
return relationshipNames[r]
|
||||
}
|
||||
|
||||
func (r Relationship) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(r.String())
|
||||
}
|
||||
|
||||
func (r *Relationship) UnmarshalJSON(data []byte) error {
|
||||
var s string
|
||||
if err := json.Unmarshal(data, &s); err != nil {
|
||||
return err
|
||||
}
|
||||
for i, name := range relationshipNames {
|
||||
if s == name {
|
||||
*r = Relationship(i)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return xerrors.Errorf("invalid relationship (%s)", s)
|
||||
}
|
||||
|
||||
type Package struct {
|
||||
ID string `json:",omitempty"`
|
||||
Name string `json:",omitempty"`
|
||||
Identifier PkgIdentifier `json:",omitempty"`
|
||||
Version string `json:",omitempty"`
|
||||
Release string `json:",omitempty"`
|
||||
Epoch int `json:",omitempty"`
|
||||
Arch string `json:",omitempty"`
|
||||
Dev bool `json:",omitempty"`
|
||||
SrcName string `json:",omitempty"`
|
||||
SrcVersion string `json:",omitempty"`
|
||||
SrcRelease string `json:",omitempty"`
|
||||
SrcEpoch int `json:",omitempty"`
|
||||
Licenses []string `json:",omitempty"`
|
||||
Maintainer string `json:",omitempty"`
|
||||
ExternalReferences []ExternalRef `json:"-"`
|
||||
|
||||
Modularitylabel string `json:",omitempty"` // only for Red Hat based distributions
|
||||
BuildInfo *BuildInfo `json:",omitempty"` // only for Red Hat
|
||||
|
||||
Indirect bool `json:",omitempty"` // Deprecated: Use relationship. Kept for backward compatibility.
|
||||
Relationship Relationship `json:",omitempty"`
|
||||
|
||||
// Dependencies of this package
|
||||
// Note: it may have interdependencies, which may lead to infinite loops.
|
||||
DependsOn []string `json:",omitempty"`
|
||||
|
||||
Layer Layer `json:",omitempty"`
|
||||
|
||||
// Each package metadata have the file path, while the package from lock files does not have.
|
||||
FilePath string `json:",omitempty"`
|
||||
|
||||
// This is required when using SPDX formats. Otherwise, it will be empty.
|
||||
Digest digest.Digest `json:",omitempty"`
|
||||
|
||||
// lines from the lock file where the dependency is written
|
||||
Locations Locations `json:",omitempty"`
|
||||
|
||||
// Files installed by the package
|
||||
InstalledFiles []string `json:",omitempty"`
|
||||
}
|
||||
|
||||
// PkgIdentifier represents a software identifiers in one of more of the supported formats.
|
||||
type PkgIdentifier struct {
|
||||
UID string `json:",omitempty"` // Calculated by the package struct
|
||||
PURL *packageurl.PackageURL `json:"-"`
|
||||
BOMRef string `json:",omitempty"` // For CycloneDX
|
||||
}
|
||||
|
||||
// MarshalJSON customizes the JSON encoding of PkgIdentifier.
|
||||
func (id *PkgIdentifier) MarshalJSON() ([]byte, error) {
|
||||
var p string
|
||||
if id.PURL != nil {
|
||||
p = id.PURL.String()
|
||||
}
|
||||
|
||||
type Alias PkgIdentifier
|
||||
return json.Marshal(&struct {
|
||||
PURL string `json:",omitempty"`
|
||||
*Alias
|
||||
}{
|
||||
PURL: p,
|
||||
Alias: (*Alias)(id),
|
||||
})
|
||||
}
|
||||
|
||||
// UnmarshalJSON customizes the JSON decoding of PkgIdentifier.
|
||||
func (id *PkgIdentifier) UnmarshalJSON(data []byte) error {
|
||||
type Alias PkgIdentifier
|
||||
aux := &struct {
|
||||
PURL string `json:",omitempty"`
|
||||
*Alias
|
||||
}{
|
||||
Alias: (*Alias)(id),
|
||||
}
|
||||
if err := json.Unmarshal(data, &aux); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if aux.PURL != "" {
|
||||
p, err := packageurl.FromString(aux.PURL)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if len(p.Qualifiers) == 0 {
|
||||
p.Qualifiers = nil
|
||||
}
|
||||
id.PURL = &p
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (id *PkgIdentifier) Empty() bool {
|
||||
return id.UID == "" && id.PURL == nil && id.BOMRef == ""
|
||||
}
|
||||
|
||||
func (id *PkgIdentifier) Match(s string) bool {
|
||||
// Encode string as PURL
|
||||
if strings.HasPrefix(s, "pkg:") {
|
||||
if p, err := packageurl.FromString(s); err == nil {
|
||||
s = p.String()
|
||||
}
|
||||
}
|
||||
|
||||
switch {
|
||||
case id.BOMRef == s:
|
||||
return true
|
||||
case id.PURL != nil && id.PURL.String() == s:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type Dependency struct {
|
||||
ID string
|
||||
DependsOn []string
|
||||
}
|
||||
|
||||
type Dependencies []Dependency
|
||||
|
||||
func (deps Dependencies) Len() int { return len(deps) }
|
||||
func (deps Dependencies) Less(i, j int) bool {
|
||||
return deps[i].ID < deps[j].ID
|
||||
}
|
||||
func (deps Dependencies) Swap(i, j int) { deps[i], deps[j] = deps[j], deps[i] }
|
||||
|
||||
type Location struct {
|
||||
StartLine int `json:",omitempty"`
|
||||
EndLine int `json:",omitempty"`
|
||||
}
|
||||
|
||||
type Locations []Location
|
||||
|
||||
func (locs Locations) Len() int { return len(locs) }
|
||||
func (locs Locations) Less(i, j int) bool {
|
||||
return locs[i].StartLine < locs[j].StartLine
|
||||
}
|
||||
func (locs Locations) Swap(i, j int) { locs[i], locs[j] = locs[j], locs[i] }
|
||||
|
||||
type ExternalRef struct {
|
||||
Type RefType
|
||||
URL string
|
||||
}
|
||||
|
||||
type RefType string
|
||||
|
||||
const (
|
||||
RefVCS RefType = "vcs"
|
||||
RefOther RefType = "other"
|
||||
)
|
||||
|
||||
// BuildInfo represents information under /root/buildinfo in RHEL
|
||||
type BuildInfo struct {
|
||||
ContentSets []string `json:",omitempty"`
|
||||
Nvr string `json:",omitempty"`
|
||||
Arch string `json:",omitempty"`
|
||||
}
|
||||
|
||||
func (pkg *Package) Empty() bool {
|
||||
return pkg.Name == "" || pkg.Version == ""
|
||||
}
|
||||
|
||||
type Packages []Package
|
||||
|
||||
func (pkgs Packages) Len() int {
|
||||
return len(pkgs)
|
||||
}
|
||||
|
||||
func (pkgs Packages) Swap(i, j int) {
|
||||
pkgs[i], pkgs[j] = pkgs[j], pkgs[i]
|
||||
}
|
||||
|
||||
func (pkgs Packages) Less(i, j int) bool {
|
||||
switch {
|
||||
case pkgs[i].Relationship != pkgs[j].Relationship:
|
||||
if pkgs[i].Relationship == RelationshipUnknown {
|
||||
return false
|
||||
} else if pkgs[j].Relationship == RelationshipUnknown {
|
||||
return true
|
||||
}
|
||||
return pkgs[i].Relationship < pkgs[j].Relationship
|
||||
case pkgs[i].Name != pkgs[j].Name:
|
||||
return pkgs[i].Name < pkgs[j].Name
|
||||
case pkgs[i].Version != pkgs[j].Version:
|
||||
return pkgs[i].Version < pkgs[j].Version
|
||||
}
|
||||
return pkgs[i].FilePath < pkgs[j].FilePath
|
||||
}
|
||||
|
||||
// ParentDeps returns a map where the keys are package IDs and the values are the packages
|
||||
// that depend on the respective package ID (parent dependencies).
|
||||
func (pkgs Packages) ParentDeps() map[string]Packages {
|
||||
parents := make(map[string]Packages)
|
||||
for _, pkg := range pkgs {
|
||||
for _, dependOn := range pkg.DependsOn {
|
||||
parents[dependOn] = append(parents[dependOn], pkg)
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range parents {
|
||||
parents[k] = lo.UniqBy(v, func(pkg Package) string {
|
||||
return pkg.ID
|
||||
})
|
||||
}
|
||||
return parents
|
||||
}
|
||||
|
||||
type SrcPackage struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
BinaryNames []string `json:"binaryNames"`
|
||||
}
|
||||
|
||||
type PackageInfo struct {
|
||||
FilePath string
|
||||
Packages Packages
|
||||
@@ -342,39 +80,6 @@ type File struct {
|
||||
Content []byte
|
||||
}
|
||||
|
||||
// ArtifactType represents a type of artifact
|
||||
type ArtifactType string
|
||||
|
||||
const (
|
||||
ArtifactContainerImage ArtifactType = "container_image"
|
||||
ArtifactFilesystem ArtifactType = "filesystem"
|
||||
ArtifactRepository ArtifactType = "repository"
|
||||
ArtifactCycloneDX ArtifactType = "cyclonedx"
|
||||
ArtifactSPDX ArtifactType = "spdx"
|
||||
ArtifactAWSAccount ArtifactType = "aws_account"
|
||||
ArtifactVM ArtifactType = "vm"
|
||||
)
|
||||
|
||||
// ArtifactReference represents a reference of container image, local filesystem and repository
|
||||
type ArtifactReference struct {
|
||||
Name string // image name, tar file name, directory or repository name
|
||||
Type ArtifactType
|
||||
ID string
|
||||
BlobIDs []string
|
||||
ImageMetadata ImageMetadata
|
||||
|
||||
// SBOM
|
||||
BOM *core.BOM
|
||||
}
|
||||
|
||||
type ImageMetadata struct {
|
||||
ID string // image ID
|
||||
DiffIDs []string // uncompressed layer IDs
|
||||
RepoTags []string
|
||||
RepoDigests []string
|
||||
ConfigFile v1.ConfigFile
|
||||
}
|
||||
|
||||
// ArtifactInfo is stored in cache
|
||||
type ArtifactInfo struct {
|
||||
SchemaVersion int
|
||||
|
||||
260
pkg/fanal/types/package.go
Normal file
260
pkg/fanal/types/package.go
Normal file
@@ -0,0 +1,260 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"github.com/package-url/packageurl-go"
|
||||
"github.com/samber/lo"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/digest"
|
||||
)
|
||||
|
||||
type Relationship int
|
||||
|
||||
const (
|
||||
RelationshipUnknown Relationship = iota
|
||||
RelationshipRoot
|
||||
RelationshipDirect
|
||||
RelationshipIndirect
|
||||
)
|
||||
|
||||
var relationshipNames = [...]string{
|
||||
"unknown",
|
||||
"root",
|
||||
"direct",
|
||||
"indirect",
|
||||
}
|
||||
|
||||
func (r Relationship) String() string {
|
||||
if r <= RelationshipUnknown || int(r) >= len(relationshipNames) {
|
||||
return "unknown"
|
||||
}
|
||||
return relationshipNames[r]
|
||||
}
|
||||
|
||||
func (r Relationship) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(r.String())
|
||||
}
|
||||
|
||||
func (r *Relationship) UnmarshalJSON(data []byte) error {
|
||||
var s string
|
||||
if err := json.Unmarshal(data, &s); err != nil {
|
||||
return err
|
||||
}
|
||||
for i, name := range relationshipNames {
|
||||
if s == name {
|
||||
*r = Relationship(i)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return xerrors.Errorf("invalid relationship (%s)", s)
|
||||
}
|
||||
|
||||
// PkgIdentifier represents a software identifiers in one of more of the supported formats.
|
||||
type PkgIdentifier struct {
|
||||
UID string `json:",omitempty"` // Calculated by the package struct
|
||||
PURL *packageurl.PackageURL `json:"-"`
|
||||
BOMRef string `json:",omitempty"` // For CycloneDX
|
||||
}
|
||||
|
||||
// MarshalJSON customizes the JSON encoding of PkgIdentifier.
|
||||
func (id *PkgIdentifier) MarshalJSON() ([]byte, error) {
|
||||
var p string
|
||||
if id.PURL != nil {
|
||||
p = id.PURL.String()
|
||||
}
|
||||
|
||||
type Alias PkgIdentifier
|
||||
return json.Marshal(&struct {
|
||||
PURL string `json:",omitempty"`
|
||||
*Alias
|
||||
}{
|
||||
PURL: p,
|
||||
Alias: (*Alias)(id),
|
||||
})
|
||||
}
|
||||
|
||||
// UnmarshalJSON customizes the JSON decoding of PkgIdentifier.
|
||||
func (id *PkgIdentifier) UnmarshalJSON(data []byte) error {
|
||||
type Alias PkgIdentifier
|
||||
aux := &struct {
|
||||
PURL string `json:",omitempty"`
|
||||
*Alias
|
||||
}{
|
||||
Alias: (*Alias)(id),
|
||||
}
|
||||
if err := json.Unmarshal(data, &aux); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if aux.PURL != "" {
|
||||
p, err := packageurl.FromString(aux.PURL)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if len(p.Qualifiers) == 0 {
|
||||
p.Qualifiers = nil
|
||||
}
|
||||
id.PURL = &p
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (id *PkgIdentifier) Empty() bool {
|
||||
return id.UID == "" && id.PURL == nil && id.BOMRef == ""
|
||||
}
|
||||
|
||||
func (id *PkgIdentifier) Match(s string) bool {
|
||||
// Encode string as PURL
|
||||
if strings.HasPrefix(s, "pkg:") {
|
||||
if p, err := packageurl.FromString(s); err == nil {
|
||||
s = p.String()
|
||||
}
|
||||
}
|
||||
|
||||
switch {
|
||||
case id.BOMRef == s:
|
||||
return true
|
||||
case id.PURL != nil && id.PURL.String() == s:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type Location struct {
|
||||
StartLine int `json:",omitempty"`
|
||||
EndLine int `json:",omitempty"`
|
||||
}
|
||||
|
||||
type Locations []Location
|
||||
|
||||
func (locs Locations) Len() int { return len(locs) }
|
||||
func (locs Locations) Less(i, j int) bool {
|
||||
return locs[i].StartLine < locs[j].StartLine
|
||||
}
|
||||
func (locs Locations) Swap(i, j int) { locs[i], locs[j] = locs[j], locs[i] }
|
||||
|
||||
type ExternalRef struct {
|
||||
Type RefType
|
||||
URL string
|
||||
}
|
||||
|
||||
type RefType string
|
||||
|
||||
const (
|
||||
RefVCS RefType = "vcs"
|
||||
RefOther RefType = "other"
|
||||
)
|
||||
|
||||
// BuildInfo represents information under /root/buildinfo in RHEL
|
||||
type BuildInfo struct {
|
||||
ContentSets []string `json:",omitempty"`
|
||||
Nvr string `json:",omitempty"`
|
||||
Arch string `json:",omitempty"`
|
||||
}
|
||||
|
||||
type Package struct {
|
||||
ID string `json:",omitempty"`
|
||||
Name string `json:",omitempty"`
|
||||
Identifier PkgIdentifier `json:",omitempty"`
|
||||
Version string `json:",omitempty"`
|
||||
Release string `json:",omitempty"`
|
||||
Epoch int `json:",omitempty"`
|
||||
Arch string `json:",omitempty"`
|
||||
Dev bool `json:",omitempty"`
|
||||
SrcName string `json:",omitempty"`
|
||||
SrcVersion string `json:",omitempty"`
|
||||
SrcRelease string `json:",omitempty"`
|
||||
SrcEpoch int `json:",omitempty"`
|
||||
Licenses []string `json:",omitempty"`
|
||||
Maintainer string `json:",omitempty"`
|
||||
ExternalReferences []ExternalRef `json:"-"`
|
||||
|
||||
Modularitylabel string `json:",omitempty"` // only for Red Hat based distributions
|
||||
BuildInfo *BuildInfo `json:",omitempty"` // only for Red Hat
|
||||
|
||||
Indirect bool `json:",omitempty"` // Deprecated: Use relationship. Kept for backward compatibility.
|
||||
Relationship Relationship `json:",omitempty"`
|
||||
|
||||
// Dependencies of this package
|
||||
// Note: it may have interdependencies, which may lead to infinite loops.
|
||||
DependsOn []string `json:",omitempty"`
|
||||
|
||||
Layer Layer `json:",omitempty"`
|
||||
|
||||
// Each package metadata have the file path, while the package from lock files does not have.
|
||||
FilePath string `json:",omitempty"`
|
||||
|
||||
// This is required when using SPDX formats. Otherwise, it will be empty.
|
||||
Digest digest.Digest `json:",omitempty"`
|
||||
|
||||
// lines from the lock file where the dependency is written
|
||||
Locations Locations `json:",omitempty"`
|
||||
|
||||
// Files installed by the package
|
||||
InstalledFiles []string `json:",omitempty"`
|
||||
}
|
||||
|
||||
func (pkg *Package) Empty() bool {
|
||||
return pkg.Name == "" || pkg.Version == ""
|
||||
}
|
||||
|
||||
type Packages []Package
|
||||
|
||||
func (pkgs Packages) Len() int {
|
||||
return len(pkgs)
|
||||
}
|
||||
|
||||
func (pkgs Packages) Swap(i, j int) {
|
||||
pkgs[i], pkgs[j] = pkgs[j], pkgs[i]
|
||||
}
|
||||
|
||||
func (pkgs Packages) Less(i, j int) bool {
|
||||
switch {
|
||||
case pkgs[i].Relationship != pkgs[j].Relationship:
|
||||
if pkgs[i].Relationship == RelationshipUnknown {
|
||||
return false
|
||||
} else if pkgs[j].Relationship == RelationshipUnknown {
|
||||
return true
|
||||
}
|
||||
return pkgs[i].Relationship < pkgs[j].Relationship
|
||||
case pkgs[i].Name != pkgs[j].Name:
|
||||
return pkgs[i].Name < pkgs[j].Name
|
||||
case pkgs[i].Version != pkgs[j].Version:
|
||||
return pkgs[i].Version < pkgs[j].Version
|
||||
}
|
||||
return pkgs[i].FilePath < pkgs[j].FilePath
|
||||
}
|
||||
|
||||
// ParentDeps returns a map where the keys are package IDs and the values are the packages
|
||||
// that depend on the respective package ID (parent dependencies).
|
||||
func (pkgs Packages) ParentDeps() map[string]Packages {
|
||||
parents := make(map[string]Packages)
|
||||
for _, pkg := range pkgs {
|
||||
for _, dependOn := range pkg.DependsOn {
|
||||
parents[dependOn] = append(parents[dependOn], pkg)
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range parents {
|
||||
parents[k] = lo.UniqBy(v, func(pkg Package) string {
|
||||
return pkg.ID
|
||||
})
|
||||
}
|
||||
return parents
|
||||
}
|
||||
|
||||
type Dependency struct {
|
||||
ID string
|
||||
DependsOn []string
|
||||
}
|
||||
|
||||
type Dependencies []Dependency
|
||||
|
||||
func (deps Dependencies) Len() int { return len(deps) }
|
||||
func (deps Dependencies) Less(i, j int) bool {
|
||||
return deps[i].ID < deps[j].ID
|
||||
}
|
||||
func (deps Dependencies) Swap(i, j int) { deps[i], deps[j] = deps[j], deps[i] }
|
||||
@@ -379,7 +379,7 @@ func (s *Scanner) clusterInfoToReportResources(allArtifact []*artifacts.Artifact
|
||||
Version: comp.Version,
|
||||
Type: core.TypeApplication,
|
||||
Properties: toProperties(comp.Properties, k8sCoreComponentNamespace),
|
||||
PkgID: core.PkgID{
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
PURL: generatePURL(comp.Name, comp.Version, nodeName),
|
||||
},
|
||||
}
|
||||
@@ -406,7 +406,7 @@ func (s *Scanner) clusterInfoToReportResources(allArtifact []*artifacts.Artifact
|
||||
Type: core.TypeContainerImage,
|
||||
Name: name,
|
||||
Version: cDigest,
|
||||
PkgID: core.PkgID{
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
PURL: imagePURL.Unwrap(),
|
||||
},
|
||||
Properties: []core.Property{
|
||||
@@ -439,7 +439,7 @@ func (s *Scanner) clusterInfoToReportResources(allArtifact []*artifacts.Artifact
|
||||
Name: cf.Name,
|
||||
Version: cf.Version,
|
||||
Properties: toProperties(cf.Properties, k8sCoreComponentNamespace),
|
||||
PkgID: core.PkgID{
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
PURL: generatePURL(cf.Name, cf.Version, nodeName),
|
||||
},
|
||||
Root: true,
|
||||
@@ -512,7 +512,7 @@ func (s *Scanner) nodeComponent(b *core.BOM, nf bom.NodeInfo) *core.Component {
|
||||
Namespace: k8sCoreComponentNamespace,
|
||||
},
|
||||
},
|
||||
PkgID: core.PkgID{
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
PURL: generatePURL(kubelet, kubeletVersion, nf.NodeName),
|
||||
},
|
||||
}
|
||||
@@ -534,7 +534,7 @@ func (s *Scanner) nodeComponent(b *core.BOM, nf bom.NodeInfo) *core.Component {
|
||||
Namespace: k8sCoreComponentNamespace,
|
||||
},
|
||||
},
|
||||
PkgID: core.PkgID{
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
PURL: packageurl.NewPackageURL(packageurl.TypeGolang, "", runtimeName, runtimeVersion, packageurl.Qualifiers{}, ""),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package scanner
|
||||
|
||||
import (
|
||||
"context"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/sbom/core"
|
||||
"github.com/aquasecurity/trivy/pkg/uuid"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -99,7 +100,7 @@ func TestScanner_Scan(t *testing.T) {
|
||||
Namespace: k8sCoreComponentNamespace,
|
||||
},
|
||||
},
|
||||
PkgID: core.PkgID{
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
PURL: &packageurl.PackageURL{
|
||||
Type: "golang",
|
||||
Name: "github.com/containerd/containerd",
|
||||
@@ -113,7 +114,7 @@ func TestScanner_Scan(t *testing.T) {
|
||||
Type: core.TypeApplication,
|
||||
Name: "k8s.io/apiserver",
|
||||
Version: "1.21.1",
|
||||
PkgID: core.PkgID{
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
PURL: &packageurl.PackageURL{
|
||||
Type: purl.TypeK8s,
|
||||
Name: "k8s.io/apiserver",
|
||||
@@ -138,7 +139,7 @@ func TestScanner_Scan(t *testing.T) {
|
||||
Namespace: k8sCoreComponentNamespace,
|
||||
},
|
||||
},
|
||||
PkgID: core.PkgID{
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
PURL: &packageurl.PackageURL{
|
||||
Type: "k8s",
|
||||
Name: "k8s.io/kubelet",
|
||||
@@ -150,7 +151,7 @@ func TestScanner_Scan(t *testing.T) {
|
||||
{
|
||||
Type: core.TypeApplication,
|
||||
Name: "node-core-components",
|
||||
PkgID: core.PkgID{
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
BOMRef: "3ff14136-e09f-4df9-80ea-000000000006",
|
||||
},
|
||||
},
|
||||
@@ -158,7 +159,7 @@ func TestScanner_Scan(t *testing.T) {
|
||||
Type: core.TypeContainerImage,
|
||||
Name: "k8s.gcr.io/kube-apiserver",
|
||||
Version: "sha256:18e61c783b41758dd391ab901366ec3546b26fae00eef7e223d1f94da808e02f",
|
||||
PkgID: core.PkgID{
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
PURL: &packageurl.PackageURL{
|
||||
Type: "oci",
|
||||
Name: "kube-apiserver",
|
||||
@@ -199,7 +200,7 @@ func TestScanner_Scan(t *testing.T) {
|
||||
Namespace: "",
|
||||
},
|
||||
},
|
||||
PkgID: core.PkgID{
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
BOMRef: "3ff14136-e09f-4df9-80ea-000000000005",
|
||||
},
|
||||
},
|
||||
@@ -220,7 +221,7 @@ func TestScanner_Scan(t *testing.T) {
|
||||
Namespace: k8sCoreComponentNamespace,
|
||||
},
|
||||
},
|
||||
PkgID: core.PkgID{
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
PURL: &packageurl.PackageURL{
|
||||
Type: purl.TypeK8s,
|
||||
Name: "k8s.io/kubernetes",
|
||||
@@ -264,7 +265,7 @@ func TestScanner_Scan(t *testing.T) {
|
||||
Namespace: k8sCoreComponentNamespace,
|
||||
},
|
||||
},
|
||||
PkgID: core.PkgID{
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
BOMRef: "3ff14136-e09f-4df9-80ea-000000000004",
|
||||
},
|
||||
},
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/clock"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/purl"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
@@ -105,7 +106,7 @@ func (w Writer) Write(ctx context.Context, report types.Report) error {
|
||||
manifest.Name = string(result.Type)
|
||||
// show path for language-specific packages only
|
||||
if result.Class == types.ClassLangPkg {
|
||||
if report.ArtifactType == ftypes.ArtifactContainerImage {
|
||||
if report.ArtifactType == artifact.TypeContainerImage {
|
||||
// `RepoDigests` ~= <registry>/<image_name>@sha256:<image_hash>
|
||||
// `RepoTag` ~= <registry>/<image_name>:<image_tag>
|
||||
// By concatenating the hash from `RepoDigests` at the end of `RepoTag` we get all the information
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
|
||||
"github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability"
|
||||
"github.com/aquasecurity/trivy/pkg/clock"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
|
||||
"github.com/aquasecurity/trivy/pkg/report/predicate"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
@@ -49,7 +49,7 @@ func TestWriter_Write(t *testing.T) {
|
||||
Result: types.Report{
|
||||
SchemaVersion: 2,
|
||||
ArtifactName: "alpine:3.14",
|
||||
ArtifactType: ftypes.ArtifactType(""),
|
||||
ArtifactType: artifact.Type(""),
|
||||
Metadata: types.Metadata{},
|
||||
Results: types.Results{
|
||||
{
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/owenrumney/go-sarif/v2/sarif"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
@@ -131,7 +132,7 @@ func (sw *SarifWriter) Write(ctx context.Context, report types.Report) error {
|
||||
sw.run.Tool.Driver.WithVersion(sw.Version)
|
||||
sw.run.Tool.Driver.WithFullName("Trivy Vulnerability Scanner")
|
||||
sw.locationCache = make(map[string][]location)
|
||||
if report.ArtifactType == ftypes.ArtifactContainerImage {
|
||||
if report.ArtifactType == artifact.TypeContainerImage {
|
||||
sw.run.Properties = sarif.Properties{
|
||||
"imageName": report.ArtifactName,
|
||||
"repoTags": report.Metadata.RepoTags,
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
|
||||
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
|
||||
"github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/report"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
@@ -27,7 +28,7 @@ func TestReportWriter_Sarif(t *testing.T) {
|
||||
name: "report with vulnerabilities",
|
||||
input: types.Report{
|
||||
ArtifactName: "debian:9",
|
||||
ArtifactType: ftypes.ArtifactContainerImage,
|
||||
ArtifactType: artifact.TypeContainerImage,
|
||||
Metadata: types.Metadata{
|
||||
RepoTags: []string{
|
||||
"debian:9",
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
cr "github.com/aquasecurity/trivy/pkg/compliance/report"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
|
||||
"github.com/aquasecurity/trivy/pkg/flag"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/report/cyclonedx"
|
||||
@@ -82,7 +82,7 @@ func Write(ctx context.Context, report types.Report, option flag.Options) (err e
|
||||
}
|
||||
case types.FormatSarif:
|
||||
target := ""
|
||||
if report.ArtifactType == ftypes.ArtifactFilesystem {
|
||||
if report.ArtifactType == artifact.TypeFilesystem {
|
||||
target = option.Target
|
||||
}
|
||||
writer = &SarifWriter{
|
||||
|
||||
@@ -3,10 +3,9 @@ package core
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/package-url/packageurl-go"
|
||||
|
||||
dtypes "github.com/aquasecurity/trivy-db/pkg/types"
|
||||
"github.com/aquasecurity/trivy/pkg/digest"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/uuid"
|
||||
)
|
||||
|
||||
@@ -124,14 +123,14 @@ type Component struct {
|
||||
// SPDX: package.licenseConcluded, package.licenseDeclared
|
||||
Licenses []string
|
||||
|
||||
// PkgID has PURL and BOMRef for the component
|
||||
// PkgIdentifier has PURL and BOMRef for the component
|
||||
// PURL:
|
||||
// CycloneDX: component.purl
|
||||
// SPDX: package.externalRefs.referenceLocator
|
||||
// BOMRef:
|
||||
// CycloneDX: component.bom-ref
|
||||
// SPDX: N/A
|
||||
PkgID PkgID
|
||||
PkgIdentifier ftypes.PkgIdentifier
|
||||
|
||||
// Supplier is the name of the supplier of the component
|
||||
// CycloneDX: component.supplier
|
||||
@@ -188,11 +187,6 @@ type Relationship struct {
|
||||
Type RelationshipType
|
||||
}
|
||||
|
||||
type PkgID struct {
|
||||
PURL *packageurl.PackageURL
|
||||
BOMRef string
|
||||
}
|
||||
|
||||
type Vulnerability struct {
|
||||
dtypes.Vulnerability
|
||||
ID string
|
||||
@@ -222,8 +216,8 @@ func (b *BOM) setupComponent(c *Component) {
|
||||
if c.id == uuid.Nil {
|
||||
c.id = uuid.New()
|
||||
}
|
||||
if c.PkgID.PURL != nil {
|
||||
p := c.PkgID.PURL.String()
|
||||
if c.PkgIdentifier.PURL != nil {
|
||||
p := c.PkgIdentifier.PURL.String()
|
||||
b.purls[p] = append(b.purls[p], c.id)
|
||||
}
|
||||
sort.Sort(c.Properties)
|
||||
@@ -281,7 +275,7 @@ func (b *BOM) Root() *Component {
|
||||
return nil
|
||||
}
|
||||
if b.opts.GenerateBOMRef {
|
||||
root.PkgID.BOMRef = b.bomRef(root)
|
||||
root.PkgIdentifier.BOMRef = b.bomRef(root)
|
||||
}
|
||||
return root
|
||||
}
|
||||
@@ -290,7 +284,7 @@ func (b *BOM) Components() map[uuid.UUID]*Component {
|
||||
// Fill in BOMRefs for components
|
||||
if b.opts.GenerateBOMRef {
|
||||
for id, c := range b.components {
|
||||
b.components[id].PkgID.BOMRef = b.bomRef(c)
|
||||
b.components[id].PkgIdentifier.BOMRef = b.bomRef(c)
|
||||
}
|
||||
}
|
||||
return b.components
|
||||
@@ -312,14 +306,14 @@ func (b *BOM) NumComponents() int {
|
||||
// When multiple lock files have the same dependency with the same name and version, PURL in the BOM can conflict.
|
||||
// In that case, PURL cannot be used as a unique identifier, and UUIDv4 be used for BOMRef.
|
||||
func (b *BOM) bomRef(c *Component) string {
|
||||
if c.PkgID.BOMRef != "" {
|
||||
return c.PkgID.BOMRef
|
||||
if c.PkgIdentifier.BOMRef != "" {
|
||||
return c.PkgIdentifier.BOMRef
|
||||
}
|
||||
// Return the UUID of the component if the PURL is not present.
|
||||
if c.PkgID.PURL == nil {
|
||||
if c.PkgIdentifier.PURL == nil {
|
||||
return c.id.String()
|
||||
}
|
||||
p := c.PkgID.PURL.String()
|
||||
p := c.PkgIdentifier.PURL.String()
|
||||
|
||||
// Return the UUID of the component if the PURL is not unique in the BOM.
|
||||
if len(b.purls[p]) > 1 {
|
||||
|
||||
@@ -108,12 +108,12 @@ func (m *Marshaler) MarshalComponent(component *core.Component) (*cdx.Component,
|
||||
}
|
||||
|
||||
cdxComponent := &cdx.Component{
|
||||
BOMRef: component.PkgID.BOMRef,
|
||||
BOMRef: component.PkgIdentifier.BOMRef,
|
||||
Type: componentType,
|
||||
Name: component.Name,
|
||||
Group: component.Group,
|
||||
Version: component.Version,
|
||||
PackageURL: m.PackageURL(component.PkgID.PURL),
|
||||
PackageURL: m.PackageURL(component.PkgIdentifier.PURL),
|
||||
Supplier: m.Supplier(component.Supplier),
|
||||
Hashes: m.Hashes(component.Files),
|
||||
Licenses: m.Licenses(component.Licenses),
|
||||
|
||||
@@ -2,6 +2,7 @@ package cyclonedx_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
|
||||
"github.com/aquasecurity/trivy/pkg/sbom/core"
|
||||
"github.com/package-url/packageurl-go"
|
||||
"testing"
|
||||
@@ -29,7 +30,7 @@ func TestMarshaler_MarshalReport(t *testing.T) {
|
||||
Root: true,
|
||||
Type: core.TypeApplication,
|
||||
Name: "jackson-databind-2.13.4.1.jar",
|
||||
PkgID: core.PkgID{
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
BOMRef: "aff65b54-6009-4c32-968d-748949ef46e8",
|
||||
},
|
||||
Properties: []core.Property{
|
||||
@@ -50,7 +51,7 @@ func TestMarshaler_MarshalReport(t *testing.T) {
|
||||
inputReport: types.Report{
|
||||
SchemaVersion: report.SchemaVersion,
|
||||
ArtifactName: "rails:latest",
|
||||
ArtifactType: ftypes.ArtifactContainerImage,
|
||||
ArtifactType: artifact.TypeContainerImage,
|
||||
Metadata: types.Metadata{
|
||||
Size: 1024,
|
||||
OS: &ftypes.OS{
|
||||
@@ -668,7 +669,7 @@ func TestMarshaler_MarshalReport(t *testing.T) {
|
||||
inputReport: types.Report{
|
||||
SchemaVersion: report.SchemaVersion,
|
||||
ArtifactName: "centos:latest",
|
||||
ArtifactType: ftypes.ArtifactContainerImage,
|
||||
ArtifactType: artifact.TypeContainerImage,
|
||||
Metadata: types.Metadata{
|
||||
Size: 1024,
|
||||
OS: &ftypes.OS{
|
||||
@@ -1229,7 +1230,7 @@ func TestMarshaler_MarshalReport(t *testing.T) {
|
||||
inputReport: types.Report{
|
||||
SchemaVersion: report.SchemaVersion,
|
||||
ArtifactName: "masahiro331/CVE-2021-41098",
|
||||
ArtifactType: ftypes.ArtifactFilesystem,
|
||||
ArtifactType: artifact.TypeFilesystem,
|
||||
Results: types.Results{
|
||||
{
|
||||
Target: "Gemfile.lock",
|
||||
@@ -1445,7 +1446,7 @@ func TestMarshaler_MarshalReport(t *testing.T) {
|
||||
inputReport: types.Report{
|
||||
SchemaVersion: report.SchemaVersion,
|
||||
ArtifactName: "./report.cdx.json",
|
||||
ArtifactType: ftypes.ArtifactCycloneDX,
|
||||
ArtifactType: artifact.TypeCycloneDX,
|
||||
Results: types.Results{
|
||||
{
|
||||
Target: "Java",
|
||||
@@ -1629,7 +1630,7 @@ func TestMarshaler_MarshalReport(t *testing.T) {
|
||||
inputReport: types.Report{
|
||||
SchemaVersion: report.SchemaVersion,
|
||||
ArtifactName: "CVE-2023-34468",
|
||||
ArtifactType: ftypes.ArtifactFilesystem,
|
||||
ArtifactType: artifact.TypeFilesystem,
|
||||
Results: types.Results{
|
||||
{
|
||||
Target: "Java",
|
||||
@@ -1926,7 +1927,7 @@ func TestMarshaler_MarshalReport(t *testing.T) {
|
||||
inputReport: types.Report{
|
||||
SchemaVersion: report.SchemaVersion,
|
||||
ArtifactName: "test-aggregate",
|
||||
ArtifactType: ftypes.ArtifactRepository,
|
||||
ArtifactType: artifact.TypeRepository,
|
||||
Results: types.Results{
|
||||
{
|
||||
Target: "Node.js",
|
||||
@@ -2039,7 +2040,7 @@ func TestMarshaler_MarshalReport(t *testing.T) {
|
||||
inputReport: types.Report{
|
||||
SchemaVersion: report.SchemaVersion,
|
||||
ArtifactName: "empty/path",
|
||||
ArtifactType: ftypes.ArtifactFilesystem,
|
||||
ArtifactType: artifact.TypeFilesystem,
|
||||
Results: types.Results{},
|
||||
},
|
||||
want: &cdx.BOM{
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/digest"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/sbom/core"
|
||||
)
|
||||
@@ -69,7 +70,7 @@ func (b *BOM) parseBOM(bom *cdx.BOM) error {
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to parse root component: %w", err)
|
||||
} else if mComponent != nil {
|
||||
components[mComponent.PkgID.BOMRef] = mComponent
|
||||
components[mComponent.PkgIdentifier.BOMRef] = mComponent
|
||||
}
|
||||
|
||||
// Parse dependencies and build relationships
|
||||
@@ -147,7 +148,7 @@ func (b *BOM) parseComponent(c cdx.Component) (*core.Component, error) {
|
||||
Digests: b.unmarshalHashes(c.Hashes),
|
||||
},
|
||||
},
|
||||
PkgID: core.PkgID{
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
PURL: &purl,
|
||||
BOMRef: c.BOMRef,
|
||||
},
|
||||
|
||||
@@ -135,7 +135,7 @@ func (m *Decoder) decodeComponents(sbom *types.SBOM) error {
|
||||
}
|
||||
|
||||
// Third-party SBOMs may contain packages in types other than "Library"
|
||||
if c.Type == core.TypeLibrary || c.PkgID.PURL != nil {
|
||||
if c.Type == core.TypeLibrary || c.PkgIdentifier.PURL != nil {
|
||||
pkg, err := m.decodeLibrary(c)
|
||||
if errors.Is(err, ErrUnsupportedType) || errors.Is(err, ErrPURLEmpty) {
|
||||
continue
|
||||
@@ -184,7 +184,7 @@ func (m *Decoder) decodeApplication(c *core.Component) *ftypes.Application {
|
||||
}
|
||||
|
||||
func (m *Decoder) decodeLibrary(c *core.Component) (*ftypes.Package, error) {
|
||||
p := (*purl.PackageURL)(c.PkgID.PURL)
|
||||
p := (*purl.PackageURL)(c.PkgIdentifier.PURL)
|
||||
if p == nil {
|
||||
log.Debug("Skipping a component without PURL",
|
||||
log.String("name", c.Name), log.String("version", c.Version))
|
||||
@@ -226,7 +226,7 @@ func (m *Decoder) decodeLibrary(c *core.Component) (*ftypes.Package, error) {
|
||||
}
|
||||
}
|
||||
|
||||
pkg.Identifier.BOMRef = c.PkgID.BOMRef
|
||||
pkg.Identifier.BOMRef = c.PkgIdentifier.BOMRef
|
||||
pkg.Licenses = c.Licenses
|
||||
|
||||
for _, f := range c.Files {
|
||||
@@ -249,10 +249,10 @@ func (m *Decoder) decodeLibrary(c *core.Component) (*ftypes.Package, error) {
|
||||
// pkgName returns the package name.
|
||||
// PURL loses case-sensitivity (e.g. Go, Npm, PyPI), so we have to use an original package name.
|
||||
func (m *Decoder) pkgName(pkg *ftypes.Package, c *core.Component) string {
|
||||
p := c.PkgID.PURL
|
||||
p := c.PkgIdentifier.PURL
|
||||
|
||||
// A name from PURL takes precedence for CocoaPods since it has subpath.
|
||||
if c.PkgID.PURL.Type == packageurl.TypeCocoapods {
|
||||
if c.PkgIdentifier.PURL.Type == packageurl.TypeCocoapods {
|
||||
return pkg.Name
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/digest"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/purl"
|
||||
"github.com/aquasecurity/trivy/pkg/sbom/core"
|
||||
@@ -61,7 +62,7 @@ func (e *Encoder) rootComponent(r types.Report) (*core.Component, error) {
|
||||
}
|
||||
|
||||
switch r.ArtifactType {
|
||||
case ftypes.ArtifactContainerImage:
|
||||
case artifact.TypeContainerImage:
|
||||
root.Type = core.TypeContainerImage
|
||||
props = append(props, core.Property{
|
||||
Name: core.PropertyImageID,
|
||||
@@ -73,16 +74,16 @@ func (e *Encoder) rootComponent(r types.Report) (*core.Component, error) {
|
||||
return nil, xerrors.Errorf("failed to new package url for oci: %w", err)
|
||||
}
|
||||
if p != nil {
|
||||
root.PkgID.PURL = p.Unwrap()
|
||||
root.PkgIdentifier.PURL = p.Unwrap()
|
||||
}
|
||||
|
||||
case ftypes.ArtifactVM:
|
||||
case artifact.TypeVM:
|
||||
root.Type = core.TypeVM
|
||||
case ftypes.ArtifactFilesystem:
|
||||
case artifact.TypeFilesystem:
|
||||
root.Type = core.TypeFilesystem
|
||||
case ftypes.ArtifactRepository:
|
||||
case artifact.TypeRepository:
|
||||
root.Type = core.TypeRepository
|
||||
case ftypes.ArtifactCycloneDX:
|
||||
case artifact.TypeCycloneDX:
|
||||
return r.BOM.Root(), nil
|
||||
}
|
||||
|
||||
@@ -346,7 +347,7 @@ func (*Encoder) component(result types.Result, pkg ftypes.Package) *core.Compone
|
||||
SrcName: pkg.SrcName,
|
||||
SrcVersion: utils.FormatSrcVersion(pkg),
|
||||
SrcFile: srcFile,
|
||||
PkgID: core.PkgID{
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
PURL: pkg.Identifier.PURL,
|
||||
},
|
||||
Supplier: pkg.Maintainer,
|
||||
|
||||
@@ -2,6 +2,7 @@ package io_test
|
||||
|
||||
import (
|
||||
dtypes "github.com/aquasecurity/trivy-db/pkg/types"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/sbom/core"
|
||||
sbomio "github.com/aquasecurity/trivy/pkg/sbom/io"
|
||||
@@ -27,7 +28,7 @@ func TestEncoder_Encode(t *testing.T) {
|
||||
report: types.Report{
|
||||
SchemaVersion: 2,
|
||||
ArtifactName: "debian:12",
|
||||
ArtifactType: ftypes.ArtifactContainerImage,
|
||||
ArtifactType: artifact.TypeContainerImage,
|
||||
Metadata: types.Metadata{
|
||||
OS: &ftypes.OS{
|
||||
Family: ftypes.Debian,
|
||||
@@ -116,7 +117,7 @@ func TestEncoder_Encode(t *testing.T) {
|
||||
Type: core.TypeContainerImage,
|
||||
Name: "debian:12",
|
||||
Root: true,
|
||||
PkgID: core.PkgID{
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
PURL: &packageurl.PackageURL{
|
||||
Type: packageurl.TypeOCI,
|
||||
Name: "debian",
|
||||
@@ -163,7 +164,7 @@ func TestEncoder_Encode(t *testing.T) {
|
||||
Value: "debian",
|
||||
},
|
||||
},
|
||||
PkgID: core.PkgID{
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
BOMRef: "3ff14136-e09f-4df9-80ea-000000000002",
|
||||
},
|
||||
},
|
||||
@@ -181,7 +182,7 @@ func TestEncoder_Encode(t *testing.T) {
|
||||
Value: "debian",
|
||||
},
|
||||
},
|
||||
PkgID: core.PkgID{
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
PURL: &packageurl.PackageURL{
|
||||
Type: packageurl.TypeDebian,
|
||||
Name: "libc6",
|
||||
@@ -204,7 +205,7 @@ func TestEncoder_Encode(t *testing.T) {
|
||||
Value: "debian",
|
||||
},
|
||||
},
|
||||
PkgID: core.PkgID{
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
PURL: &packageurl.PackageURL{
|
||||
Type: packageurl.TypeDebian,
|
||||
Name: "curl",
|
||||
@@ -237,7 +238,7 @@ func TestEncoder_Encode(t *testing.T) {
|
||||
Value: "jar",
|
||||
},
|
||||
},
|
||||
PkgID: core.PkgID{
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
PURL: &packageurl.PackageURL{
|
||||
Type: packageurl.TypeMaven,
|
||||
Namespace: "org.apache.xmlgraphics",
|
||||
@@ -298,7 +299,7 @@ func TestEncoder_Encode(t *testing.T) {
|
||||
report: types.Report{
|
||||
SchemaVersion: 2,
|
||||
ArtifactName: "gobinary",
|
||||
ArtifactType: ftypes.ArtifactFilesystem,
|
||||
ArtifactType: artifact.TypeFilesystem,
|
||||
Results: []types.Result{
|
||||
{
|
||||
Target: "test",
|
||||
@@ -379,7 +380,7 @@ func TestEncoder_Encode(t *testing.T) {
|
||||
Value: "2",
|
||||
},
|
||||
},
|
||||
PkgID: core.PkgID{
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
BOMRef: "3ff14136-e09f-4df9-80ea-000000000001",
|
||||
},
|
||||
},
|
||||
@@ -396,7 +397,7 @@ func TestEncoder_Encode(t *testing.T) {
|
||||
Value: "gobinary",
|
||||
},
|
||||
},
|
||||
PkgID: core.PkgID{
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
BOMRef: "3ff14136-e09f-4df9-80ea-000000000002",
|
||||
},
|
||||
},
|
||||
@@ -414,7 +415,7 @@ func TestEncoder_Encode(t *testing.T) {
|
||||
Value: "gobinary",
|
||||
},
|
||||
},
|
||||
PkgID: core.PkgID{
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
PURL: &packageurl.PackageURL{
|
||||
Type: packageurl.TypeGolang,
|
||||
Namespace: "github.com/org",
|
||||
@@ -438,7 +439,7 @@ func TestEncoder_Encode(t *testing.T) {
|
||||
Value: "gobinary",
|
||||
},
|
||||
},
|
||||
PkgID: core.PkgID{
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
PURL: &packageurl.PackageURL{
|
||||
Type: packageurl.TypeGolang,
|
||||
Namespace: "github.com/org",
|
||||
@@ -463,7 +464,7 @@ func TestEncoder_Encode(t *testing.T) {
|
||||
Value: "gobinary",
|
||||
},
|
||||
},
|
||||
PkgID: core.PkgID{
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
PURL: &packageurl.PackageURL{
|
||||
Type: packageurl.TypeGolang,
|
||||
Namespace: "github.com/org",
|
||||
@@ -488,7 +489,7 @@ func TestEncoder_Encode(t *testing.T) {
|
||||
Value: "gobinary",
|
||||
},
|
||||
},
|
||||
PkgID: core.PkgID{
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
PURL: &packageurl.PackageURL{
|
||||
Type: packageurl.TypeGolang,
|
||||
Name: "stdlib",
|
||||
@@ -537,7 +538,7 @@ func TestEncoder_Encode(t *testing.T) {
|
||||
report: types.Report{
|
||||
SchemaVersion: 2,
|
||||
ArtifactName: "debian:12",
|
||||
ArtifactType: ftypes.ArtifactContainerImage,
|
||||
ArtifactType: artifact.TypeContainerImage,
|
||||
Metadata: types.Metadata{
|
||||
OS: &ftypes.OS{
|
||||
Family: ftypes.Debian,
|
||||
|
||||
@@ -229,8 +229,8 @@ func (m *Marshaler) packageDownloadLocation(root *core.Component) string {
|
||||
func (m *Marshaler) rootSPDXPackage(root *core.Component, pkgDownloadLocation string) (*spdx.Package, error) {
|
||||
var externalReferences []*spdx.PackageExternalReference
|
||||
// When the target is a container image, add PURL to the external references of the root package.
|
||||
if root.PkgID.PURL != nil {
|
||||
externalReferences = append(externalReferences, m.purlExternalReference(root.PkgID.PURL.String()))
|
||||
if root.PkgIdentifier.PURL != nil {
|
||||
externalReferences = append(externalReferences, m.purlExternalReference(root.PkgIdentifier.PURL.String()))
|
||||
}
|
||||
|
||||
pkgID, err := calcPkgID(m.hasher, fmt.Sprintf("%s-%s", root.Name, root.Type))
|
||||
@@ -304,8 +304,8 @@ func (m *Marshaler) spdxPackage(c *core.Component, pkgDownloadLocation string) (
|
||||
}
|
||||
|
||||
var pkgExtRefs []*spdx.PackageExternalReference
|
||||
if c.PkgID.PURL != nil {
|
||||
pkgExtRefs = []*spdx.PackageExternalReference{m.purlExternalReference(c.PkgID.PURL.String())}
|
||||
if c.PkgIdentifier.PURL != nil {
|
||||
pkgExtRefs = []*spdx.PackageExternalReference{m.purlExternalReference(c.PkgIdentifier.PURL.String())}
|
||||
}
|
||||
|
||||
var digests []digest.Digest
|
||||
@@ -338,7 +338,7 @@ func (m *Marshaler) spdxPackage(c *core.Component, pkgDownloadLocation string) (
|
||||
}
|
||||
|
||||
func spdxPkgName(component *core.Component) string {
|
||||
if p := component.PkgID.PURL; p != nil && component.Group != "" {
|
||||
if p := component.PkgIdentifier.PURL; p != nil && component.Group != "" {
|
||||
if p.Type == packageurl.TypeMaven || p.Type == packageurl.TypeGradle {
|
||||
return component.Group + ":" + component.Name
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package spdx_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
|
||||
"github.com/aquasecurity/trivy/pkg/sbom/core"
|
||||
"github.com/package-url/packageurl-go"
|
||||
"hash/fnv"
|
||||
@@ -34,7 +35,7 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
inputReport: types.Report{
|
||||
SchemaVersion: report.SchemaVersion,
|
||||
ArtifactName: "rails:latest",
|
||||
ArtifactType: ftypes.ArtifactContainerImage,
|
||||
ArtifactType: artifact.TypeContainerImage,
|
||||
Metadata: types.Metadata{
|
||||
Size: 1024,
|
||||
OS: &ftypes.OS{
|
||||
@@ -358,7 +359,7 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
inputReport: types.Report{
|
||||
SchemaVersion: report.SchemaVersion,
|
||||
ArtifactName: "centos:latest",
|
||||
ArtifactType: ftypes.ArtifactContainerImage,
|
||||
ArtifactType: artifact.TypeContainerImage,
|
||||
Metadata: types.Metadata{
|
||||
Size: 1024,
|
||||
OS: &ftypes.OS{
|
||||
@@ -649,7 +650,7 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
inputReport: types.Report{
|
||||
SchemaVersion: report.SchemaVersion,
|
||||
ArtifactName: "masahiro331/CVE-2021-41098",
|
||||
ArtifactType: ftypes.ArtifactFilesystem,
|
||||
ArtifactType: artifact.TypeFilesystem,
|
||||
Results: types.Results{
|
||||
{
|
||||
Target: "Gemfile.lock",
|
||||
@@ -818,7 +819,7 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
inputReport: types.Report{
|
||||
SchemaVersion: report.SchemaVersion,
|
||||
ArtifactName: "http://test-aggregate",
|
||||
ArtifactType: ftypes.ArtifactRepository,
|
||||
ArtifactType: artifact.TypeRepository,
|
||||
Results: types.Results{
|
||||
{
|
||||
Target: "Node.js",
|
||||
@@ -937,7 +938,7 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
inputReport: types.Report{
|
||||
SchemaVersion: report.SchemaVersion,
|
||||
ArtifactName: "empty/path",
|
||||
ArtifactType: ftypes.ArtifactFilesystem,
|
||||
ArtifactType: artifact.TypeFilesystem,
|
||||
Results: types.Results{},
|
||||
},
|
||||
wantSBOM: &spdx.Document{
|
||||
@@ -985,7 +986,7 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
inputReport: types.Report{
|
||||
SchemaVersion: report.SchemaVersion,
|
||||
ArtifactName: "secret",
|
||||
ArtifactType: ftypes.ArtifactFilesystem,
|
||||
ArtifactType: artifact.TypeFilesystem,
|
||||
Results: types.Results{
|
||||
{
|
||||
Target: "key.pem",
|
||||
@@ -1047,7 +1048,7 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
inputReport: types.Report{
|
||||
SchemaVersion: report.SchemaVersion,
|
||||
ArtifactName: "go-artifact",
|
||||
ArtifactType: ftypes.ArtifactFilesystem,
|
||||
ArtifactType: artifact.TypeFilesystem,
|
||||
Results: types.Results{
|
||||
{
|
||||
Target: "/usr/local/bin/test",
|
||||
|
||||
@@ -167,7 +167,7 @@ func (s *SPDX) parsePackage(spdxPkg spdx.Package) (*core.Component, error) {
|
||||
}
|
||||
|
||||
// PURL
|
||||
if component.PkgID.PURL, err = s.parseExternalReferences(spdxPkg.PackageExternalReferences); err != nil {
|
||||
if component.PkgIdentifier.PURL, err = s.parseExternalReferences(spdxPkg.PackageExternalReferences); err != nil {
|
||||
return nil, xerrors.Errorf("external references error: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -169,7 +169,7 @@ func (s Scanner) ScanArtifact(ctx context.Context, options types.ScanOptions) (t
|
||||
}
|
||||
|
||||
// Layer makes sense only when scanning container images
|
||||
if artifactInfo.Type != ftypes.ArtifactContainerImage {
|
||||
if artifactInfo.Type != artifact.TypeContainerImage {
|
||||
removeLayer(results)
|
||||
}
|
||||
|
||||
|
||||
@@ -37,12 +37,12 @@ func TestScanner_ScanArtifact(t *testing.T) {
|
||||
CtxAnything: true,
|
||||
},
|
||||
Returns: artifact.ArtifactInspectReturns{
|
||||
Reference: ftypes.ArtifactReference{
|
||||
Reference: artifact.Reference{
|
||||
Name: "alpine:3.11",
|
||||
Type: ftypes.ArtifactContainerImage,
|
||||
Type: artifact.TypeContainerImage,
|
||||
ID: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a",
|
||||
BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
|
||||
ImageMetadata: ftypes.ImageMetadata{
|
||||
ImageMetadata: artifact.ImageMetadata{
|
||||
ID: "sha256:e389ae58922402a7ded319e79f06ac428d05698d8e61ecbe88d2cf850e42651d",
|
||||
DiffIDs: []string{"sha256:9a5d14f9f5503e55088666beef7e85a8d9625d4fa7418e2fe269e9c54bcb853c"},
|
||||
RepoTags: []string{"alpine:3.11"},
|
||||
@@ -100,7 +100,7 @@ func TestScanner_ScanArtifact(t *testing.T) {
|
||||
SchemaVersion: 2,
|
||||
CreatedAt: time.Date(2021, 8, 25, 12, 20, 30, 5, time.UTC),
|
||||
ArtifactName: "alpine:3.11",
|
||||
ArtifactType: ftypes.ArtifactContainerImage,
|
||||
ArtifactType: artifact.TypeContainerImage,
|
||||
Metadata: types.Metadata{
|
||||
OS: &ftypes.OS{
|
||||
Family: "alpine",
|
||||
@@ -168,7 +168,7 @@ func TestScanner_ScanArtifact(t *testing.T) {
|
||||
CtxAnything: true,
|
||||
},
|
||||
Returns: artifact.ArtifactInspectReturns{
|
||||
Reference: ftypes.ArtifactReference{
|
||||
Reference: artifact.Reference{
|
||||
Name: "alpine:3.11",
|
||||
ID: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a",
|
||||
BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
|
||||
|
||||
@@ -5,18 +5,19 @@ import (
|
||||
|
||||
v1 "github.com/google/go-containerregistry/pkg/v1" // nolint: goimports
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/sbom/core"
|
||||
)
|
||||
|
||||
// Report represents a scan result
|
||||
type Report struct {
|
||||
SchemaVersion int `json:",omitempty"`
|
||||
CreatedAt time.Time `json:",omitempty"`
|
||||
ArtifactName string `json:",omitempty"`
|
||||
ArtifactType ftypes.ArtifactType `json:",omitempty"`
|
||||
Metadata Metadata `json:",omitempty"`
|
||||
Results Results `json:",omitempty"`
|
||||
SchemaVersion int `json:",omitempty"`
|
||||
CreatedAt time.Time `json:",omitempty"`
|
||||
ArtifactName string `json:",omitempty"`
|
||||
ArtifactType artifact.Type `json:",omitempty"`
|
||||
Metadata Metadata `json:",omitempty"`
|
||||
Results Results `json:",omitempty"`
|
||||
|
||||
// parsed SBOM
|
||||
BOM *core.BOM `json:"-"` // Just for internal usage, not exported in JSON
|
||||
|
||||
@@ -44,8 +44,8 @@ func (v *OpenVEX) Filter(result *types.Result, bom *core.BOM) {
|
||||
|
||||
func (v *OpenVEX) Matches(vuln types.DetectedVulnerability, bom *core.BOM) []openvex.Statement {
|
||||
root := bom.Root()
|
||||
if root != nil && root.PkgID.PURL != nil {
|
||||
stmts := v.vex.Matches(vuln.VulnerabilityID, root.PkgID.PURL.String(), []string{vuln.PkgIdentifier.PURL.String()})
|
||||
if root != nil && root.PkgIdentifier.PURL != nil {
|
||||
stmts := v.vex.Matches(vuln.VulnerabilityID, root.PkgIdentifier.PURL.String(), []string{vuln.PkgIdentifier.PURL.String()})
|
||||
if len(stmts) != 0 {
|
||||
return stmts
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
|
||||
"github.com/aquasecurity/trivy/pkg/sbom"
|
||||
"github.com/aquasecurity/trivy/pkg/sbom/core"
|
||||
"github.com/aquasecurity/trivy/pkg/sbom/cyclonedx"
|
||||
@@ -68,7 +68,7 @@ func decodeCycloneDXJSON(r io.ReadSeeker, report types.Report) (VEX, error) {
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("json decode error: %w", err)
|
||||
}
|
||||
if report.ArtifactType != ftypes.ArtifactCycloneDX {
|
||||
if report.ArtifactType != artifact.TypeCycloneDX {
|
||||
return nil, xerrors.New("CycloneDX VEX can be used with CycloneDX SBOM")
|
||||
}
|
||||
return newCycloneDX(report.BOM, vex), nil
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package vex_test
|
||||
|
||||
import (
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
|
||||
"github.com/aquasecurity/trivy/pkg/sbom/core"
|
||||
"os"
|
||||
"testing"
|
||||
@@ -135,7 +136,7 @@ func TestVEX_Filter(t *testing.T) {
|
||||
fields: fields{
|
||||
filePath: "testdata/cyclonedx.json",
|
||||
report: types.Report{
|
||||
ArtifactType: ftypes.ArtifactCycloneDX,
|
||||
ArtifactType: artifact.TypeCycloneDX,
|
||||
BOM: &core.BOM{
|
||||
SerialNumber: "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79",
|
||||
Version: 1,
|
||||
@@ -218,7 +219,7 @@ func TestVEX_Filter(t *testing.T) {
|
||||
fields: fields{
|
||||
filePath: "testdata/cyclonedx.json",
|
||||
report: types.Report{
|
||||
ArtifactType: ftypes.ArtifactCycloneDX,
|
||||
ArtifactType: artifact.TypeCycloneDX,
|
||||
BOM: &core.BOM{
|
||||
SerialNumber: "urn:uuid:wrong",
|
||||
Version: 1,
|
||||
@@ -378,7 +379,7 @@ func newTestBOM() *core.BOM {
|
||||
Root: true,
|
||||
Type: core.TypeContainerImage,
|
||||
Name: "debian:12",
|
||||
PkgID: core.PkgID{
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
PURL: &packageurl.PackageURL{
|
||||
Type: packageurl.TypeOCI,
|
||||
Name: "debian",
|
||||
@@ -405,7 +406,7 @@ func newTestBOM2() *core.BOM {
|
||||
Root: true,
|
||||
Type: core.TypeContainerImage,
|
||||
Name: "ubuntu:24.04",
|
||||
PkgID: core.PkgID{
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
PURL: &packageurl.PackageURL{
|
||||
Type: packageurl.TypeOCI,
|
||||
Name: "ubuntu",
|
||||
|
||||
Reference in New Issue
Block a user