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