这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .cursor/rules/project-description.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
description:
globs:
alwaysApply: true
---
This is a SBOM generator app. It has many plugins in pkg/dependency/parser/. Our goal is to add one new plugin, based on pkg/dependency/parser/node/npm - it should be called pkg/dependency/parser/generic

It's a format for manually recording dependencies in a json file as input for SBOMs for non-supported project types.

Our format is very similar to the node/npm format.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,6 @@ cmd/trivy/trivy

# RPM
*.rpm

# Build output
bin/
20 changes: 20 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/bin/bash

# Run this script to build the trivy binary

set -e

# Change to script directory
cd "$(dirname "$0")"

# Set binary name
BINARY="trivy"
BIN_PATH="bin/$BINARY"

# Create bin directory if it doesn't exist
mkdir -p bin

# Build binary
go build -o "$BIN_PATH" "./cmd/$BINARY"

echo "$BINARY built successfully in $BIN_PATH"
33 changes: 33 additions & 0 deletions integration/testdata/fixtures/repo/generic/dependencies.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"packageName": "M2CPos",
"packageVersion": "2.0 alpha",
"packageLicense": "GPL 2.1",
"dependencies": {
"linuxKernel": {
"version": "2.1",
"source": "https://github.com/....",
"type": "source",
"license": "GPL 2.1",
"checksum": "SHA256: 12345667"
},
"libC": {
"version": "12.1",
"source": "https://github.com/....",
"type": "source",
"license": "LGPL 1.2",
"checksum": "SHA256: 789321456"
}
},
"sourceFiles": {
"path/to/FileName.c": {
"version": "2.2",
"checksum": "SHA256 562145698",
"license": "GPL 2.1"
},
"path/to/FileName2": {
"version": "2.2",
"checksum": "SHA256 562145698",
"license": "proprietary"
}
}
}
98 changes: 98 additions & 0 deletions integration/testdata/fixtures/repo/generic/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

116 changes: 116 additions & 0 deletions pkg/dependency/parser/generic/parse.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package generic

import (
"github.com/aquasecurity/trivy/pkg/dependency"
"io"

"github.com/aquasecurity/jfather"
"golang.org/x/xerrors"

"github.com/aquasecurity/trivy/pkg/dependency/parser/utils"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
xio "github.com/aquasecurity/trivy/pkg/x/io"
)

type Dependency struct {
Version string `json:"version"`
Source string `json:"source"`
Type string `json:"type"`
License string `json:"license,omitempty"`
Copyright string `json:"copyright,omitempty"`
Checksum string `json:"checksum,omitempty"`
}

type SourceFile struct {
Version string `json:"version"`
Checksum string `json:"checksum"`
License string `json:"license"`
Copyright string `json:"copyright,omitempty"`
}

type GenericPackage struct {
PackageName string `json:"packageName"`
PackageVersion string `json:"packageVersion"`
PackageLicense string `json:"packageLicense,omitempty"`
PackageCopyright string `json:"packageCopyright,omitempty"`
Dependencies map[string]Dependency `json:"dependencies"`
SourceFiles map[string]SourceFile `json:"sourceFiles,omitempty"`
}

type Parser struct {
logger *log.Logger
}

func NewParser() *Parser {
return &Parser{
logger: log.WithPrefix("generic"),
}
}

func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
var genericPackage GenericPackage
input, err := io.ReadAll(r)
if err != nil {
return nil, nil, xerrors.Errorf("read error: %w", err)
}

if err := jfather.Unmarshal(input, &genericPackage); err != nil {
return nil, nil, xerrors.Errorf("decode error: %w", err)
}

var pkgs []ftypes.Package
var deps []ftypes.Dependency

// Add the main package
mainPkg := ftypes.Package{
ID: packageID(genericPackage.PackageName, genericPackage.PackageVersion),
Name: genericPackage.PackageName,
Version: genericPackage.PackageVersion,
Licenses: []string{genericPackage.PackageLicense},
Relationship: ftypes.RelationshipRoot,
}
pkgs = append(pkgs, mainPkg)

// Add dependencies
for depName, dep := range genericPackage.Dependencies {
depPkg := ftypes.Package{
ID: packageID(depName, dep.Version),
Name: depName,
Version: dep.Version,
Licenses: []string{dep.License},
Relationship: ftypes.RelationshipDirect,
}
pkgs = append(pkgs, depPkg)

// Add dependency relationship
deps = append(deps, ftypes.Dependency{
ID: mainPkg.ID,
DependsOn: []string{depPkg.ID},
})
}

// Add source files as packages
for filePath, file := range genericPackage.SourceFiles {
filePkg := ftypes.Package{
ID: packageID(filePath, file.Version),
Name: filePath,
Version: file.Version,
Licenses: []string{file.License},
Relationship: ftypes.RelationshipDirect,
}
pkgs = append(pkgs, filePkg)

// Add source file relationship
deps = append(deps, ftypes.Dependency{
ID: mainPkg.ID,
DependsOn: []string{filePkg.ID},
})
}

return utils.UniquePackages(pkgs), deps, nil
}

func packageID(name, version string) string {
return dependency.ID(ftypes.Generic, name, version)
}
12 changes: 12 additions & 0 deletions pkg/dependency/parser/generic/parse_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package generic

import (
"testing"
)

func TestNewParser(t *testing.T) {
p := NewParser()
if p == nil {
t.Error("NewParser() returned nil")
}
}
83 changes: 83 additions & 0 deletions pkg/dependency/parser/generic/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"packageName": {
"type": "string"
},
"packageVersion": {
"type": "string"
},
"packageLicense": {
"type": "string"
},
"packageCopyright": {
"type": "string"
},
"dependencies": {
"type": "object",
"properties": {
"packageName": {
"type": "object",
"properties": {
"version": {
"type": "string"
},
"source": {
"type": "string"
},
"type": {
"type": "string"
},
"license": {
"type": "string"
},
"copyright": {
"type": "string"
},
"checksum": {
"type": "string"
}
},
"required": [
"version",
"source",
"type"
]
}
}
},
"sourceFiles": {
"type": "object",
"properties": {
"filename": {
"type": "object",
"properties": {
"version": {
"type": "string"
},
"checksum": {
"type": "string"
},
"license": {
"type": "string"
},
"copyright": {
"type": "string"
}
},
"required": [
"version",
"checksum",
"license"
]
}
}
}
},
"required": [
"packageName",
"packageVersion",
"dependencies"
]
}
Loading