github.com/nextlinux/gosbom@v0.81.1-0.20230627115839-1ff50c281391/gosbom/pkg/cataloger/cataloger.go (about) 1 /* 2 Package cataloger provides the ability to process files from a container image or file system and discover packages 3 (gems, wheels, jars, rpms, debs, etc). Specifically, this package contains both a catalog function to utilize all 4 catalogers defined in child packages as well as the interface definition to implement a cataloger. 5 */ 6 package cataloger 7 8 import ( 9 "strings" 10 11 "github.com/nextlinux/gosbom/gosbom/pkg" 12 "github.com/nextlinux/gosbom/gosbom/pkg/cataloger/alpm" 13 "github.com/nextlinux/gosbom/gosbom/pkg/cataloger/apkdb" 14 "github.com/nextlinux/gosbom/gosbom/pkg/cataloger/binary" 15 "github.com/nextlinux/gosbom/gosbom/pkg/cataloger/cpp" 16 "github.com/nextlinux/gosbom/gosbom/pkg/cataloger/dart" 17 "github.com/nextlinux/gosbom/gosbom/pkg/cataloger/deb" 18 "github.com/nextlinux/gosbom/gosbom/pkg/cataloger/dotnet" 19 "github.com/nextlinux/gosbom/gosbom/pkg/cataloger/elixir" 20 "github.com/nextlinux/gosbom/gosbom/pkg/cataloger/erlang" 21 "github.com/nextlinux/gosbom/gosbom/pkg/cataloger/golang" 22 "github.com/nextlinux/gosbom/gosbom/pkg/cataloger/haskell" 23 "github.com/nextlinux/gosbom/gosbom/pkg/cataloger/java" 24 "github.com/nextlinux/gosbom/gosbom/pkg/cataloger/javascript" 25 "github.com/nextlinux/gosbom/gosbom/pkg/cataloger/kernel" 26 "github.com/nextlinux/gosbom/gosbom/pkg/cataloger/nix" 27 "github.com/nextlinux/gosbom/gosbom/pkg/cataloger/php" 28 "github.com/nextlinux/gosbom/gosbom/pkg/cataloger/portage" 29 "github.com/nextlinux/gosbom/gosbom/pkg/cataloger/python" 30 "github.com/nextlinux/gosbom/gosbom/pkg/cataloger/r" 31 "github.com/nextlinux/gosbom/gosbom/pkg/cataloger/rpm" 32 "github.com/nextlinux/gosbom/gosbom/pkg/cataloger/ruby" 33 "github.com/nextlinux/gosbom/gosbom/pkg/cataloger/rust" 34 "github.com/nextlinux/gosbom/gosbom/pkg/cataloger/sbom" 35 "github.com/nextlinux/gosbom/gosbom/pkg/cataloger/swift" 36 "github.com/nextlinux/gosbom/internal/log" 37 ) 38 39 const AllCatalogersPattern = "all" 40 41 // ImageCatalogers returns a slice of locally implemented catalogers that are fit for detecting installations of packages. 42 func ImageCatalogers(cfg Config) []pkg.Cataloger { 43 return filterCatalogers([]pkg.Cataloger{ 44 alpm.NewAlpmdbCataloger(), 45 apkdb.NewApkdbCataloger(), 46 binary.NewCataloger(), 47 deb.NewDpkgdbCataloger(), 48 dotnet.NewDotnetDepsCataloger(), 49 golang.NewGoModuleBinaryCataloger(cfg.Go()), 50 java.NewJavaCataloger(cfg.Java()), 51 java.NewNativeImageCataloger(), 52 javascript.NewPackageCataloger(), 53 nix.NewStoreCataloger(), 54 php.NewComposerInstalledCataloger(), 55 portage.NewPortageCataloger(), 56 python.NewPythonPackageCataloger(), 57 r.NewPackageCataloger(), 58 rpm.NewRpmDBCataloger(), 59 ruby.NewGemSpecCataloger(), 60 sbom.NewSBOMCataloger(), 61 }, cfg.Catalogers) 62 } 63 64 // DirectoryCatalogers returns a slice of locally implemented catalogers that are fit for detecting packages from index files (and select installations) 65 func DirectoryCatalogers(cfg Config) []pkg.Cataloger { 66 return filterCatalogers([]pkg.Cataloger{ 67 alpm.NewAlpmdbCataloger(), 68 apkdb.NewApkdbCataloger(), 69 binary.NewCataloger(), 70 cpp.NewConanCataloger(), 71 dart.NewPubspecLockCataloger(), 72 deb.NewDpkgdbCataloger(), 73 dotnet.NewDotnetDepsCataloger(), 74 elixir.NewMixLockCataloger(), 75 erlang.NewRebarLockCataloger(), 76 golang.NewGoModFileCataloger(cfg.Go()), 77 golang.NewGoModuleBinaryCataloger(cfg.Go()), 78 haskell.NewHackageCataloger(), 79 java.NewJavaCataloger(cfg.Java()), 80 java.NewJavaGradleLockfileCataloger(), 81 java.NewJavaPomCataloger(), 82 java.NewNativeImageCataloger(), 83 javascript.NewLockCataloger(), 84 nix.NewStoreCataloger(), 85 php.NewComposerLockCataloger(), 86 portage.NewPortageCataloger(), 87 python.NewPythonIndexCataloger(), 88 python.NewPythonPackageCataloger(), 89 rpm.NewFileCataloger(), 90 rpm.NewRpmDBCataloger(), 91 ruby.NewGemFileLockCataloger(), 92 rust.NewCargoLockCataloger(), 93 sbom.NewSBOMCataloger(), 94 swift.NewCocoapodsCataloger(), 95 }, cfg.Catalogers) 96 } 97 98 // AllCatalogers returns all implemented catalogers 99 func AllCatalogers(cfg Config) []pkg.Cataloger { 100 return filterCatalogers([]pkg.Cataloger{ 101 alpm.NewAlpmdbCataloger(), 102 apkdb.NewApkdbCataloger(), 103 binary.NewCataloger(), 104 cpp.NewConanCataloger(), 105 dart.NewPubspecLockCataloger(), 106 deb.NewDpkgdbCataloger(), 107 dotnet.NewDotnetDepsCataloger(), 108 elixir.NewMixLockCataloger(), 109 erlang.NewRebarLockCataloger(), 110 golang.NewGoModFileCataloger(cfg.Go()), 111 golang.NewGoModuleBinaryCataloger(cfg.Go()), 112 haskell.NewHackageCataloger(), 113 java.NewJavaCataloger(cfg.Java()), 114 java.NewJavaGradleLockfileCataloger(), 115 java.NewJavaPomCataloger(), 116 java.NewNativeImageCataloger(), 117 javascript.NewLockCataloger(), 118 javascript.NewPackageCataloger(), 119 kernel.NewLinuxKernelCataloger(cfg.Kernel()), 120 nix.NewStoreCataloger(), 121 php.NewComposerInstalledCataloger(), 122 php.NewComposerLockCataloger(), 123 portage.NewPortageCataloger(), 124 python.NewPythonIndexCataloger(), 125 python.NewPythonPackageCataloger(), 126 r.NewPackageCataloger(), 127 rpm.NewFileCataloger(), 128 rpm.NewRpmDBCataloger(), 129 ruby.NewGemFileLockCataloger(), 130 ruby.NewGemSpecCataloger(), 131 rust.NewAuditBinaryCataloger(), 132 rust.NewCargoLockCataloger(), 133 sbom.NewSBOMCataloger(), 134 swift.NewCocoapodsCataloger(), 135 }, cfg.Catalogers) 136 } 137 138 func RequestedAllCatalogers(cfg Config) bool { 139 for _, enableCatalogerPattern := range cfg.Catalogers { 140 if enableCatalogerPattern == AllCatalogersPattern { 141 return true 142 } 143 } 144 return false 145 } 146 147 func filterCatalogers(catalogers []pkg.Cataloger, enabledCatalogerPatterns []string) []pkg.Cataloger { 148 // if cataloger is not set, all applicable catalogers are enabled by default 149 if len(enabledCatalogerPatterns) == 0 { 150 return catalogers 151 } 152 for _, enableCatalogerPattern := range enabledCatalogerPatterns { 153 if enableCatalogerPattern == AllCatalogersPattern { 154 return catalogers 155 } 156 } 157 var keepCatalogers []pkg.Cataloger 158 for _, cataloger := range catalogers { 159 if contains(enabledCatalogerPatterns, cataloger.Name()) { 160 keepCatalogers = append(keepCatalogers, cataloger) 161 continue 162 } 163 log.Infof("skipping cataloger %q", cataloger.Name()) 164 } 165 return keepCatalogers 166 } 167 168 func contains(enabledPartial []string, catalogerName string) bool { 169 catalogerName = strings.TrimSuffix(catalogerName, "-cataloger") 170 for _, partial := range enabledPartial { 171 partial = strings.TrimSuffix(partial, "-cataloger") 172 if partial == "" { 173 continue 174 } 175 if hasFullWord(partial, catalogerName) { 176 return true 177 } 178 } 179 return false 180 } 181 182 func hasFullWord(targetPhrase, candidate string) bool { 183 if targetPhrase == "cataloger" || targetPhrase == "" { 184 return false 185 } 186 start := strings.Index(candidate, targetPhrase) 187 if start == -1 { 188 return false 189 } 190 191 if start > 0 && candidate[start-1] != '-' { 192 return false 193 } 194 195 end := start + len(targetPhrase) 196 if end < len(candidate) && candidate[end] != '-' { 197 return false 198 } 199 return true 200 }