github.com/anchore/syft@v1.38.2/examples/create_custom_sbom/main.go (about) 1 package main 2 3 import ( 4 "context" 5 "crypto" 6 "fmt" 7 "os" 8 9 "go.yaml.in/yaml/v3" 10 _ "modernc.org/sqlite" // required for rpmdb and other features 11 12 "github.com/anchore/syft/syft" 13 "github.com/anchore/syft/syft/cataloging" 14 "github.com/anchore/syft/syft/cataloging/filecataloging" 15 "github.com/anchore/syft/syft/cataloging/pkgcataloging" 16 "github.com/anchore/syft/syft/file" 17 "github.com/anchore/syft/syft/sbom" 18 "github.com/anchore/syft/syft/source" 19 ) 20 21 const defaultImage = "alpine:3.19" 22 23 func main() { 24 // automagically get a source.Source for arbitrary string input 25 src := getSource(imageReference()) 26 defer src.Close() 27 28 // will catalog the given source and return a SBOM keeping in mind several configurable options 29 sbom := getSBOM(src) 30 31 // show a simple package summary 32 summarize(sbom) 33 34 // show the alpine-configuration cataloger results 35 showAlpineConfiguration(sbom) 36 } 37 38 func imageReference() string { 39 // read an image string reference from the command line or use a default 40 if len(os.Args) > 1 { 41 return os.Args[1] 42 } 43 return defaultImage 44 } 45 46 func getSource(input string) source.Source { 47 fmt.Println("detecting source type for input:", input, "...") 48 49 src, err := syft.GetSource(context.Background(), input, nil) 50 if err != nil { 51 panic(err) 52 } 53 54 return src 55 } 56 57 func getSBOM(src source.Source) sbom.SBOM { 58 fmt.Println("creating SBOM...") 59 60 cfg := syft.DefaultCreateSBOMConfig(). 61 // run the catalogers in parallel (5 at a time concurrently max) 62 WithParallelism(5). 63 // bake a specific tool name and version into the SBOM 64 WithTool("my-tool", "v1.0"). 65 // catalog all files with 3 digests 66 WithFilesConfig( 67 filecataloging.DefaultConfig(). 68 WithSelection(file.AllFilesSelection). 69 WithHashers( 70 crypto.MD5, 71 crypto.SHA1, 72 crypto.SHA256, 73 ), 74 ). 75 // only use OS related catalogers that would have been used with the kind of 76 // source type (container image or directory), but also add a specific python cataloger 77 WithCatalogerSelection( 78 cataloging.NewSelectionRequest(). 79 WithSubSelections("os"). 80 WithAdditions("python-package-cataloger"), 81 ). 82 // which relationships to include 83 WithRelationshipsConfig( 84 cataloging.RelationshipsConfig{ 85 PackageFileOwnership: true, 86 PackageFileOwnershipOverlap: true, 87 ExcludeBinaryPackagesWithFileOwnershipOverlap: true, 88 }, 89 ). 90 // add your own cataloger to the mix 91 WithCatalogers( 92 pkgcataloging.NewAlwaysEnabledCatalogerReference( 93 newAlpineConfigurationCataloger(), 94 ), 95 ) 96 97 s, err := syft.CreateSBOM(context.Background(), src, cfg) 98 if err != nil { 99 panic(err) 100 } 101 102 return *s 103 } 104 105 func summarize(s sbom.SBOM) { 106 fmt.Printf("Cataloged %d packages:\n", s.Artifacts.Packages.PackageCount()) 107 for _, p := range s.Artifacts.Packages.Sorted() { 108 fmt.Printf(" - %s@%s (%s)\n", p.Name, p.Version, p.Type) 109 } 110 fmt.Println() 111 } 112 113 func showAlpineConfiguration(s sbom.SBOM) { 114 pkgs := s.Artifacts.Packages.PackagesByName("alpine-configuration") 115 if len(pkgs) == 0 { 116 fmt.Println("no alpine-configuration package found") 117 return 118 } 119 120 p := pkgs[0] 121 122 fmt.Printf("All 'alpine-configuration' packages: %s\n", p.Version) 123 meta, err := yaml.Marshal(p.Metadata) 124 if err != nil { 125 panic(err) 126 } 127 fmt.Println(string(meta)) 128 }