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  }