syft/syft/pkg/cataloger/cataloger.go
Dan Luhring 8478e0bef7
Add support for parsing .NET assemblies (#1943)
* Add support for parsing .NET assemblies

Signed-off-by: Dan Luhring <dluhring@chainguard.dev>

Former-commit-id: 69c33fe4d77357d843c11590f3b07825bc6249ac

* Add dll and exe files

Signed-off-by: Dan Luhring <dluhring@chainguard.dev>

Former-commit-id: b9d204efa6d2ef385b5fbb7a59a3474ecabea641

* Add PE cataloger to directory catalogers

Signed-off-by: Dan Luhring <dluhring@chainguard.dev>

Former-commit-id: 9711c00d9da92e2887e0c1f92edd740ea5345849

* Don't set language to dotnet for PEs

Signed-off-by: Dan Luhring <dluhring@chainguard.dev>

Former-commit-id: 368313fddac9160d8a06a01ebe8c5ac7990232f5

* Fix spelling of cataloger in constructor

Signed-off-by: Dan Luhring <dluhring@chainguard.dev>

Former-commit-id: e42fd77b2f8b6d42e076a84f6cce386861260941

* Adjust which cases in PE parsing return errors

Signed-off-by: Dan Luhring <dluhring@chainguard.dev>

Former-commit-id: 95b25f8fc3a7d4e18fe30e489b09851f316795ff

* remove build binary from branch

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

Former-commit-id: fa54c0d0aef0998d5520e9f44cae51f5f9cd38a2

* Fix failing CLI tests

Signed-off-by: Dan Luhring <dluhring@chainguard.dev>

---------

Signed-off-by: Dan Luhring <dluhring@chainguard.dev>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
2023-07-19 15:34:07 -04:00

203 lines
6.6 KiB
Go

/*
Package cataloger provides the ability to process files from a container image or file system and discover packages
(gems, wheels, jars, rpms, debs, etc). Specifically, this package contains both a catalog function to utilize all
catalogers defined in child packages as well as the interface definition to implement a cataloger.
*/
package cataloger
import (
"strings"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/pkg/cataloger/alpm"
"github.com/anchore/syft/syft/pkg/cataloger/apkdb"
"github.com/anchore/syft/syft/pkg/cataloger/binary"
"github.com/anchore/syft/syft/pkg/cataloger/cpp"
"github.com/anchore/syft/syft/pkg/cataloger/dart"
"github.com/anchore/syft/syft/pkg/cataloger/deb"
"github.com/anchore/syft/syft/pkg/cataloger/dotnet"
"github.com/anchore/syft/syft/pkg/cataloger/elixir"
"github.com/anchore/syft/syft/pkg/cataloger/erlang"
"github.com/anchore/syft/syft/pkg/cataloger/golang"
"github.com/anchore/syft/syft/pkg/cataloger/haskell"
"github.com/anchore/syft/syft/pkg/cataloger/java"
"github.com/anchore/syft/syft/pkg/cataloger/javascript"
"github.com/anchore/syft/syft/pkg/cataloger/kernel"
"github.com/anchore/syft/syft/pkg/cataloger/nix"
"github.com/anchore/syft/syft/pkg/cataloger/php"
"github.com/anchore/syft/syft/pkg/cataloger/portage"
"github.com/anchore/syft/syft/pkg/cataloger/python"
"github.com/anchore/syft/syft/pkg/cataloger/r"
"github.com/anchore/syft/syft/pkg/cataloger/rpm"
"github.com/anchore/syft/syft/pkg/cataloger/ruby"
"github.com/anchore/syft/syft/pkg/cataloger/rust"
"github.com/anchore/syft/syft/pkg/cataloger/sbom"
"github.com/anchore/syft/syft/pkg/cataloger/swift"
)
const AllCatalogersPattern = "all"
// ImageCatalogers returns a slice of locally implemented catalogers that are fit for detecting installations of packages.
func ImageCatalogers(cfg Config) []pkg.Cataloger {
return filterCatalogers([]pkg.Cataloger{
alpm.NewAlpmdbCataloger(),
apkdb.NewApkdbCataloger(),
binary.NewCataloger(),
deb.NewDpkgdbCataloger(),
dotnet.NewDotnetPortableExecutableCataloger(),
golang.NewGoModuleBinaryCataloger(cfg.Go()),
java.NewJavaCataloger(cfg.Java()),
java.NewNativeImageCataloger(),
javascript.NewPackageCataloger(),
nix.NewStoreCataloger(),
php.NewComposerInstalledCataloger(),
portage.NewPortageCataloger(),
python.NewPythonPackageCataloger(),
r.NewPackageCataloger(),
rpm.NewRpmDBCataloger(),
ruby.NewGemSpecCataloger(),
sbom.NewSBOMCataloger(),
}, cfg.Catalogers)
}
// DirectoryCatalogers returns a slice of locally implemented catalogers that are fit for detecting packages from index files (and select installations)
func DirectoryCatalogers(cfg Config) []pkg.Cataloger {
return filterCatalogers([]pkg.Cataloger{
alpm.NewAlpmdbCataloger(),
apkdb.NewApkdbCataloger(),
binary.NewCataloger(),
cpp.NewConanCataloger(),
dart.NewPubspecLockCataloger(),
deb.NewDpkgdbCataloger(),
dotnet.NewDotnetDepsCataloger(),
dotnet.NewDotnetPortableExecutableCataloger(),
elixir.NewMixLockCataloger(),
erlang.NewRebarLockCataloger(),
golang.NewGoModFileCataloger(cfg.Go()),
golang.NewGoModuleBinaryCataloger(cfg.Go()),
haskell.NewHackageCataloger(),
java.NewJavaCataloger(cfg.Java()),
java.NewJavaGradleLockfileCataloger(),
java.NewJavaPomCataloger(),
java.NewNativeImageCataloger(),
javascript.NewLockCataloger(),
nix.NewStoreCataloger(),
php.NewComposerLockCataloger(),
portage.NewPortageCataloger(),
python.NewPythonIndexCataloger(),
python.NewPythonPackageCataloger(),
rpm.NewFileCataloger(),
rpm.NewRpmDBCataloger(),
ruby.NewGemFileLockCataloger(),
rust.NewCargoLockCataloger(),
sbom.NewSBOMCataloger(),
swift.NewCocoapodsCataloger(),
}, cfg.Catalogers)
}
// AllCatalogers returns all implemented catalogers
func AllCatalogers(cfg Config) []pkg.Cataloger {
return filterCatalogers([]pkg.Cataloger{
alpm.NewAlpmdbCataloger(),
apkdb.NewApkdbCataloger(),
binary.NewCataloger(),
cpp.NewConanCataloger(),
dart.NewPubspecLockCataloger(),
deb.NewDpkgdbCataloger(),
dotnet.NewDotnetDepsCataloger(),
dotnet.NewDotnetPortableExecutableCataloger(),
elixir.NewMixLockCataloger(),
erlang.NewRebarLockCataloger(),
golang.NewGoModFileCataloger(cfg.Go()),
golang.NewGoModuleBinaryCataloger(cfg.Go()),
haskell.NewHackageCataloger(),
java.NewJavaCataloger(cfg.Java()),
java.NewJavaGradleLockfileCataloger(),
java.NewJavaPomCataloger(),
java.NewNativeImageCataloger(),
javascript.NewLockCataloger(),
javascript.NewPackageCataloger(),
kernel.NewLinuxKernelCataloger(cfg.Kernel()),
nix.NewStoreCataloger(),
php.NewComposerInstalledCataloger(),
php.NewComposerLockCataloger(),
portage.NewPortageCataloger(),
python.NewPythonIndexCataloger(),
python.NewPythonPackageCataloger(),
r.NewPackageCataloger(),
rpm.NewFileCataloger(),
rpm.NewRpmDBCataloger(),
ruby.NewGemFileLockCataloger(),
ruby.NewGemSpecCataloger(),
rust.NewAuditBinaryCataloger(),
rust.NewCargoLockCataloger(),
sbom.NewSBOMCataloger(),
swift.NewCocoapodsCataloger(),
}, cfg.Catalogers)
}
func RequestedAllCatalogers(cfg Config) bool {
for _, enableCatalogerPattern := range cfg.Catalogers {
if enableCatalogerPattern == AllCatalogersPattern {
return true
}
}
return false
}
func filterCatalogers(catalogers []pkg.Cataloger, enabledCatalogerPatterns []string) []pkg.Cataloger {
// if cataloger is not set, all applicable catalogers are enabled by default
if len(enabledCatalogerPatterns) == 0 {
return catalogers
}
for _, enableCatalogerPattern := range enabledCatalogerPatterns {
if enableCatalogerPattern == AllCatalogersPattern {
return catalogers
}
}
var keepCatalogers []pkg.Cataloger
for _, cataloger := range catalogers {
if contains(enabledCatalogerPatterns, cataloger.Name()) {
keepCatalogers = append(keepCatalogers, cataloger)
continue
}
log.Infof("skipping cataloger %q", cataloger.Name())
}
return keepCatalogers
}
func contains(enabledPartial []string, catalogerName string) bool {
catalogerName = strings.TrimSuffix(catalogerName, "-cataloger")
for _, partial := range enabledPartial {
partial = strings.TrimSuffix(partial, "-cataloger")
if partial == "" {
continue
}
if hasFullWord(partial, catalogerName) {
return true
}
}
return false
}
func hasFullWord(targetPhrase, candidate string) bool {
if targetPhrase == "cataloger" || targetPhrase == "" {
return false
}
start := strings.Index(candidate, targetPhrase)
if start == -1 {
return false
}
if start > 0 && candidate[start-1] != '-' {
return false
}
end := start + len(targetPhrase)
if end < len(candidate) && candidate[end] != '-' {
return false
}
return true
}