diff --git a/internal/cmd/report/sbom/sbom.go b/internal/cmd/report/sbom/sbom.go index 670c3beb..e0c63e80 100644 --- a/internal/cmd/report/sbom/sbom.go +++ b/internal/cmd/report/sbom/sbom.go @@ -13,6 +13,7 @@ import ( var commitId string var repositoryId string var branch string +var format string var vulnerabilities bool var licenses bool var output string @@ -24,6 +25,7 @@ const BranchFlag = "branch" const VulnerabilitiesFlag = "vulnerabilities" const LicensesFlag = "licenses" const OutputFlag = "output" +const FormatFlag = "format" func NewSBOMCmd(reporter report.IReporter) *cobra.Command { cmd := &cobra.Command{ @@ -50,6 +52,12 @@ This is an enterprise feature. Please visit https://debricked.com/pricing/ for m cmd.Flags().StringVarP(&branch, BranchFlag, "b", "", "The branch that you want an SBOM report for") viper.MustBindEnv(BranchFlag) + cmd.Flags().StringVarP(&format, FormatFlag, "f", "", `The format that you want the SBOM report in. + +Supported options are: 'CycloneDX', 'SPDX'`, + ) + viper.MustBindEnv(FormatFlag) + cmd.Flags().BoolVar(&vulnerabilities, VulnerabilitiesFlag, true, "Toggle SBOM vulnerability data inclusion") viper.MustBindEnv(VulnerabilitiesFlag) @@ -74,6 +82,7 @@ func RunE(r report.IReporter) func(_ *cobra.Command, args []string) error { Vulnerabilities: viper.GetBool(VulnerabilitiesFlag), Licenses: viper.GetBool(LicensesFlag), Output: viper.GetString(OutputFlag), + Format: viper.GetString(FormatFlag), } if err := r.Order(orderArgs); err != nil { diff --git a/internal/cmd/root/root_test.go b/internal/cmd/root/root_test.go index 5cdc0446..81a655cf 100644 --- a/internal/cmd/root/root_test.go +++ b/internal/cmd/root/root_test.go @@ -35,7 +35,7 @@ func TestNewRootCmd(t *testing.T) { } } assert.Truef(t, match, "failed to assert that flag was present: "+AccessTokenFlag) - assert.Len(t, viperKeys, 20) + assert.Len(t, viperKeys, 21) } func TestPreRun(t *testing.T) { diff --git a/internal/cmd/scan/scan.go b/internal/cmd/scan/scan.go index 50f5df70..2a2a71ce 100644 --- a/internal/cmd/scan/scan.go +++ b/internal/cmd/scan/scan.go @@ -33,7 +33,7 @@ var repositoryName string var repositoryUrl string var verbose bool var versionHint bool -var sbom bool +var sbom string var sbomOutput string const ( @@ -154,7 +154,10 @@ For example, if there is a "go.mod" in the target path, its dependencies are goi "Example: debricked resolve --prefer-npm", }, "\n") cmd.Flags().BoolP(NpmPreferredFlag, "", npmPreferred, npmPreferredDoc) - cmd.Flags().BoolVar(&sbom, SBOMFlag, false, `Toggle generating and downloading SBOM report after scan completion`) + cmd.Flags().StringVar(&sbom, SBOMFlag, "", `Toggle generating and downloading SBOM report after scan completion of specified format. +Supported formats are: 'CycloneDX', 'SPDX' +Leaving the field empty results in no SBOM generation.`, + ) cmd.Flags().StringVar(&sbomOutput, SBOMOutputFlag, "", `Set output path of downloaded SBOM report (if sbom is toggled)`) viper.MustBindEnv(RepositoryFlag) @@ -181,7 +184,7 @@ func RunE(s *scan.IScanner) func(_ *cobra.Command, args []string) error { Path: path, Resolve: !viper.GetBool(NoResolveFlag), Fingerprint: !viper.GetBool(NoFingerprintFlag), - SBOM: viper.GetBool(SBOMFlag), + SBOM: viper.GetString(SBOMFlag), SBOMOutput: viper.GetString(SBOMOutputFlag), Exclusions: viper.GetStringSlice(ExclusionFlag), Verbose: viper.GetBool(VerboseFlag), diff --git a/internal/report/sbom/report.go b/internal/report/sbom/report.go index 0f62715e..f6539910 100644 --- a/internal/report/sbom/report.go +++ b/internal/report/sbom/report.go @@ -46,6 +46,7 @@ type OrderArgs struct { CommitID string Branch string Output string + Format string Vulnerabilities bool Licenses bool } @@ -78,7 +79,7 @@ func (r Reporter) Order(args report.IOrderArgs) error { func (r Reporter) generate(orderArgs OrderArgs) (string, error) { // Tries to start generating an SBOM and returns the UUID for the report body, err := json.Marshal(generateSbom{ - Format: "CycloneDX", + Format: orderArgs.Format, RepositoryID: orderArgs.RepositoryID, CommitID: orderArgs.CommitID, Email: "", diff --git a/internal/scan/scanner.go b/internal/scan/scanner.go index ef9291da..bfcf7a23 100644 --- a/internal/scan/scanner.go +++ b/internal/scan/scanner.go @@ -49,7 +49,7 @@ type DebrickedOptions struct { Resolve bool Fingerprint bool CallGraph bool - SBOM bool + SBOM string SBOMOutput string Exclusions []string Inclusions []string @@ -146,7 +146,7 @@ func (dScanner *DebrickedScanner) Scan(o IOptions) error { } func (dScanner *DebrickedScanner) scanReportSBOM(options DebrickedOptions, detailsURL string) error { - if !options.SBOM { + if options.SBOM == "" { return nil } reporter := sbom.Reporter{DebClient: *dScanner.client, FileWriter: io.FileWriter{}} @@ -157,6 +157,7 @@ func (dScanner *DebrickedScanner) scanReportSBOM(options DebrickedOptions, detai } return reporter.Order(sbom.OrderArgs{ + Format: options.SBOM, RepositoryID: repositoryID, CommitID: commitID, Branch: options.BranchName, diff --git a/internal/scan/scanner_test.go b/internal/scan/scanner_test.go index cbb3e039..e5cf62e9 100644 --- a/internal/scan/scanner_test.go +++ b/internal/scan/scanner_test.go @@ -88,7 +88,7 @@ func TestScan(t *testing.T) { RepositoryName: repositoryName, CommitName: "commit", Fingerprint: false, - SBOM: false, + SBOM: "", BranchName: "", CommitAuthor: "", RepositoryUrl: "", @@ -152,7 +152,7 @@ func TestScanWithJsonPath(t *testing.T) { Exclusions: nil, RepositoryName: repositoryName, CommitName: "commit", - SBOM: false, + SBOM: "", BranchName: "", CommitAuthor: "", RepositoryUrl: "", @@ -794,7 +794,7 @@ func TestScanWithSBOMReport(t *testing.T) { Fingerprint: false, CallGraph: false, Resolve: false, - SBOM: true, + SBOM: "CycloneDX", BranchName: "", CommitAuthor: "", RepositoryUrl: "", @@ -835,6 +835,7 @@ func TestScanWithSBOMReport(t *testing.T) { assert.Contains(t, string(output), assertion) } err = os.Remove("13-37.sbom.json") // Remove created "SBOM" + assert.NoError(t, err) }