github.com/vchain-us/vcn@v0.9.11-0.20210921212052-a2484d23c0b3/pkg/cmd/bom/bom.go (about) 1 /* 2 * Copyright (c) 2021 CodeNotary, Inc. All Rights Reserved. 3 * This software is released under GPL3. 4 * The full license information can be found under: 5 * https://www.gnu.org/licenses/gpl-3.0.en.html 6 * 7 */ 8 9 package bom 10 11 import ( 12 "fmt" 13 "path/filepath" 14 "strings" 15 16 "github.com/spf13/cobra" 17 "github.com/spf13/viper" 18 19 "github.com/vchain-us/vcn/pkg/bom" 20 "github.com/vchain-us/vcn/pkg/bom/artifact" 21 "github.com/vchain-us/vcn/pkg/bom/docker" 22 "github.com/vchain-us/vcn/pkg/uri" 23 ) 24 25 // NewCommand returns the cobra command for `vcn info` 26 func NewCommand() *cobra.Command { 27 cmd := &cobra.Command{ 28 Use: "bom", 29 Example: " vcn bom /bin/vcn", 30 Short: "Collect BoM information", 31 Long: ` 32 Collect BoM (Bill of Material) information 33 34 It identifies dependencies of build artifact and produces the BoM. Dependencies can be 35 later authenticated by 'vcn a --bom', and notarized together with artifact by 'vcn n --bom'. 36 `, 37 RunE: runBom, 38 PreRun: func(cmd *cobra.Command, args []string) { 39 // Bind to all flags to env vars (after flags were parsed), 40 // but only ones retrivied by using viper will be used. 41 viper.BindPFlags(cmd.Flags()) 42 }, 43 Args: func(cmd *cobra.Command, args []string) error { 44 return cobra.ExactValidArgs(1)(cmd, args) 45 }, 46 } 47 48 cmd.Flags().Bool("bom-debug", false, "show extra debug info for BoM processing, also disable progress indicators") 49 cmd.Flags().String("bom-file", "", "store BoM int the file for later processing") 50 // BoM output options 51 cmd.Flags().String("bom-spdx", "", "name of the file to output BoM in SPDX format") 52 cmd.Flags().String("bom-cyclonedx-json", "", "name of the file to output BoM in CycloneDX JSON format") 53 cmd.Flags().String("bom-cyclonedx-xml", "", "name of the file to output BoM in CycloneDX XML format") 54 cmd.Flags().StringSlice("bom-container-binary", []string{}, "list of binaries to be executed inside the container - only the relevant dependencies will be processed") 55 cmd.Flags().String("github-token", "", "Github OAuth token for querying BoM Github package details. Either authenticated or not, requests are subject to Github limits") 56 57 return cmd 58 } 59 60 func runBom(cmd *cobra.Command, args []string) error { 61 path := args[0] 62 u, err := uri.Parse(path) 63 if err != nil { 64 return err 65 } 66 if _, ok := bom.BomSchemes[u.Scheme]; !ok { 67 return fmt.Errorf("unsupported URI %s for --bom option", path) 68 } 69 if u.Scheme != "" { 70 path = strings.TrimPrefix(u.Opaque, "//") 71 } 72 73 var bomArtifact artifact.Artifact 74 if u.Scheme == "docker" { 75 bomArtifact, err = docker.New(path, viper.GetStringSlice("bom-container-binary")) 76 if err != nil { 77 return err 78 } 79 } else { 80 path, err = filepath.Abs(path) 81 if err != nil { 82 return err 83 } 84 bomArtifact = bom.New(path) 85 } 86 if bomArtifact == nil { 87 return fmt.Errorf("unsupported artifact format/language") 88 } 89 90 outputOpts := artifact.Progress 91 if viper.GetBool("silent") { 92 outputOpts = artifact.Silent 93 } else if viper.GetBool("bom-debug") { 94 outputOpts = artifact.Debug 95 } 96 97 fmt.Printf("Resolving dependencies...\n") 98 _, err = bomArtifact.ResolveDependencies(outputOpts) 99 if err != nil { 100 return fmt.Errorf("cannot get dependencies: %w", err) 101 } 102 103 artifact.Display(bomArtifact, artifact.ColNameVersion) 104 105 // store deps in bom file for further processing 106 if bomFile := viper.GetString("bom-file"); bomFile != "" { 107 err := artifact.Store(bomArtifact, bomFile) 108 if err != nil { 109 return err 110 } 111 } 112 113 return bom.Output(bomArtifact) // process all possible BoM output options 114 }