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