From 0f5f7c09303412d029d0f1b6709d0ea08470d38a Mon Sep 17 00:00:00 2001 From: "ritesh.noronha" Date: Wed, 2 Oct 2024 15:42:17 -0700 Subject: [PATCH] cleanup old code --- cmd/dt.go | 1 - go.mod | 5 - go.sum | 2 - pkg/assemble/cdx/comp_service.go | 8 +- pkg/assemble/cdx/interface.go | 16 +- pkg/assemble/cdx/merge.go | 447 +++++++++++-------------------- pkg/assemble/cdx/util.go | 112 ++++++-- 7 files changed, 249 insertions(+), 342 deletions(-) diff --git a/cmd/dt.go b/cmd/dt.go index 23928a4..9073380 100644 --- a/cmd/dt.go +++ b/cmd/dt.go @@ -62,7 +62,6 @@ Basic Example: dtParams.PopulateInputField(ctx) assembleParams, err := extractArgsFromDTtoAssemble(dtParams) - fmt.Println("assemble.Input: ", assembleParams.Input) if err != nil { return err } diff --git a/go.mod b/go.mod index 152b5b2..6523f46 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,6 @@ require ( github.com/google/go-github/v52 v52.0.0 github.com/google/uuid v1.6.0 github.com/mitchellh/copystructure v1.2.0 - github.com/mitchellh/hashstructure/v2 v2.0.2 github.com/pingcap/log v1.1.0 github.com/samber/lo v1.47.0 github.com/spdx/tools-golang v0.5.5 @@ -27,21 +26,17 @@ require ( github.com/anchore/go-struct-converter v0.0.0-20230627203149-c72ef8859ca9 // indirect github.com/cloudflare/circl v1.3.9 // indirect github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be // indirect - github.com/davecgh/go-spew v1.1.1 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/spdx/gordf v0.0.0-20221230105357-b735bd5aac89 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/stretchr/testify v1.9.0 go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.26.0 // indirect golang.org/x/oauth2 v0.22.0 // indirect golang.org/x/sys v0.24.0 // indirect golang.org/x/text v0.17.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) diff --git a/go.sum b/go.sum index 8cda32a..7f04796 100644 --- a/go.sum +++ b/go.sum @@ -48,8 +48,6 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= -github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/pingcap/errors v0.11.0 h1:DCJQB8jrHbQ1VVlMFIrbj2ApScNNotVmkSNplu2yUt4= diff --git a/pkg/assemble/cdx/comp_service.go b/pkg/assemble/cdx/comp_service.go index dd8cd83..e465c3d 100644 --- a/pkg/assemble/cdx/comp_service.go +++ b/pkg/assemble/cdx/comp_service.go @@ -23,12 +23,6 @@ import ( "github.com/interlynk-io/sbomasm/pkg/logger" ) -type item struct { - comp *cydx.Component - oldID string - newID string -} - type idmap struct { oldID string newID string @@ -57,7 +51,7 @@ func (s *ComponentService) StoreAndCloneWithNewID(c *cydx.Component) *cydx.Compo panic(err) } - newID := newBomRef(nc) + newID := newBomRef() nc.BOMRef = newID s.idList = append(s.idList, idmap{ diff --git a/pkg/assemble/cdx/interface.go b/pkg/assemble/cdx/interface.go index 453646d..d240c20 100644 --- a/pkg/assemble/cdx/interface.go +++ b/pkg/assemble/cdx/interface.go @@ -131,11 +131,6 @@ type MergeSettings struct { } func Merge(ms *MergeSettings) error { - merger := newMerge(ms) - - merger.loadBoms() - merger.initOutBom() - if len(ms.Output.Spec) > 0 && ms.Output.Spec != "cyclonedx" { return errors.New("invalid output spec") } @@ -144,13 +139,6 @@ func Merge(ms *MergeSettings) error { return errors.New("invalid CycloneDX spec version") } - if ms.Assemble.FlatMerge { - return merger.flatMerge() - } else if ms.Assemble.HierarchicalMerge { - return merger.hierarchicalMerge() - } else if ms.Assemble.AssemblyMerge { - return merger.assemblyMerge() - } - - return merger.hierarchicalMerge() + merger := newMerge(ms) + return merger.combinedMerge() } diff --git a/pkg/assemble/cdx/merge.go b/pkg/assemble/cdx/merge.go index b2abc36..9dbad07 100644 --- a/pkg/assemble/cdx/merge.go +++ b/pkg/assemble/cdx/merge.go @@ -52,8 +52,121 @@ func (m *merge) loadBoms() { } } +func (m *merge) combinedMerge() error { + log := logger.FromContext(*m.settings.Ctx) + + log.Debug("loading sboms") + m.loadBoms() + + log.Debugf("initialize component service") + cs := newComponentService(*m.settings.Ctx) + + // Build primary component list from each sbom + priCompList := buildPrimaryComponentList(m.in, cs) + log.Debugf("build primary component list for each sbom found %d", len(priCompList)) + + // Build a flat list of components from each sbom + compList := buildComponentList(m.in, cs) + log.Debugf("build a flat list of components from each sbom found %d", len(compList)) + + // Build a flat list of dependencies from each sbom + depList := buildDependencyList(m.in, cs) + log.Debugf("build a flat list of dependencies from each sbom found %d", len(depList)) + + // build a list of tools from each sbom + toolsList := buildToolList(m.in) + log.Debugf("build a list of tools from each sbom found comps: %d, service: %d", len(*toolsList.Components), len(*toolsList.Services)) + + //Build the final sbom + log.Debugf("generating output sbom") + m.initOutBom() + + log.Debugf("generating primary component") + m.out.Metadata.Component = m.setupPrimaryComp() + + log.Debugf("assign tools to metadata") + m.out.Metadata.Tools = toolsList + + if m.settings.Assemble.FlatMerge { + finalCompList := []cydx.Component{} + finalCompList = append(finalCompList, priCompList...) + finalCompList = append(finalCompList, compList...) + log.Debugf("flat merge: final component list: %d", len(finalCompList)) + m.out.Components = &finalCompList + + priCompIds := lo.Map(priCompList, func(c cydx.Component, _ int) string { + return c.BOMRef + }) + depList = append(depList, cydx.Dependency{ + Ref: m.out.Metadata.Component.BOMRef, + Dependencies: &priCompIds, + }) + log.Debugf("flat merge: final dependency list: %d", len(depList)) + m.out.Dependencies = &depList + } else if m.settings.Assemble.AssemblyMerge { + // Add the sbom primary components to the new primary component + m.out.Metadata.Component.Components = &priCompList + m.out.Components = &compList + m.out.Dependencies = &depList + + log.Debugf("assembly merge: final component list: %d", len(compList)) + log.Debugf("assembly merge: final dependency list: %d", len(depList)) + } else { + for _, b := range m.in { + var oldPc *cydx.Component + var newPc int + + if b.Metadata != nil && b.Metadata.Component != nil { + oldPc = b.Metadata.Component + } + + newPcId, _ := cs.ResolveDepID(oldPc.BOMRef) + + for i, pc := range priCompList { + if pc.BOMRef == newPcId { + newPc = i + break + } + } + + //Initialize the components list for the primary component + priCompList[newPc].Components = &[]cydx.Component{} + + for _, oldComp := range lo.FromPtr(b.Components) { + newCompId, _ := cs.ResolveDepID(oldComp.BOMRef) + for _, comp := range compList { + if comp.BOMRef == newCompId { + *priCompList[newPc].Components = append(*priCompList[newPc].Components, comp) + break + } + } + } + + log.Debugf("hierarchical merge: primary component %s has %d components", priCompList[newPc].BOMRef, len(*priCompList[newPc].Components)) + } + + m.out.Components = &priCompList + + priCompIds := lo.Map(priCompList, func(c cydx.Component, _ int) string { + return c.BOMRef + }) + depList = append(depList, cydx.Dependency{ + Ref: m.out.Metadata.Component.BOMRef, + Dependencies: &priCompIds, + }) + m.out.Dependencies = &depList + log.Debugf("hierarchical merge: final dependency list: %d", len(depList)) + } + + // Writes sbom to file or uploads + log.Debugf("writing sbom") + return m.processSBOM() +} + func (m *merge) initOutBom() { + //log := logger.FromContext(*m.settings.Ctx) m.out.SerialNumber = newSerialNumber() + m.out.Metadata = &cydx.Metadata{} m.out.Metadata.Timestamp = utcNowTime() @@ -67,8 +180,11 @@ func (m *merge) initOutBom() { } } + // Always add data sharing license. m.out.Metadata.Licenses = &cydx.Licenses{ - {License: &cydx.License{ID: "CC-BY-1.0"}}, + { + License: &cydx.License{ID: "CC-BY-1.0"}, + }, } if len(m.settings.App.Authors) > 0 { @@ -83,7 +199,6 @@ func (m *merge) initOutBom() { } func (m *merge) setupPrimaryComp() *cydx.Component { - log := logger.FromContext(*m.settings.Ctx) pc := cydx.Component{} pc.Name = m.settings.App.Name @@ -101,9 +216,7 @@ func (m *merge) setupPrimaryComp() *cydx.Component { pc.Licenses = &cydx.Licenses{ {License: &cydx.License{ID: m.settings.App.License.Id}}, } - } - - if m.settings.App.License.Expression != "" { + } else if m.settings.App.License.Expression != "" { pc.Licenses = &cydx.Licenses{ {Expression: m.settings.App.License.Expression}, } @@ -132,322 +245,86 @@ func (m *merge) setupPrimaryComp() *cydx.Component { } } - pc.BOMRef = newBomRef(pc) - log.Debugf("Primary component: %s", pc.BOMRef) - + pc.BOMRef = newBomRef() return &pc } -/* -Gatheres all the artifacts of the input BOMs into a single BOM. -as a flat list of components. -*/ -func (m *merge) flatMerge() error { - log := logger.FromContext(*m.settings.Ctx) - cs := newComponentService(*m.settings.Ctx) - - log.Debug("Merging BOMs into a flat list") - - priComps := lo.Map(m.in, func(bom *cydx.BOM, _ int) *cydx.Component { - if bom.Metadata != nil && bom.Metadata.Component != nil { - return cs.StoreAndCloneWithNewID(bom.Metadata.Component) - } - return &cydx.Component{} - }) - - comps := lo.Flatten(lo.Map(m.in, func(bom *cydx.BOM, _ int) []cydx.Component { - newComps := []cydx.Component{} - for _, comp := range lo.FromPtr(bom.Components) { - newComps = append(newComps, *cs.StoreAndCloneWithNewID(&comp)) - } - return newComps - })) - - deps := lo.Flatten(lo.Map(m.in, func(bom *cydx.BOM, _ int) []cydx.Dependency { - newDeps := []cydx.Dependency{} - for _, dep := range lo.FromPtr(bom.Dependencies) { - nd := cydx.Dependency{} - ref, found := cs.ResolveDepID(dep.Ref) - if !found { - log.Warnf("dependency %s not found", dep.Ref) - continue - } - - deps := cs.ResolveDepIDs(lo.FromPtr(dep.Dependencies)) - - nd.Ref = ref - nd.Dependencies = &deps - newDeps = append(newDeps, nd) - } - return newDeps - })) - - m.out.Metadata.Component = m.setupPrimaryComp() - - tools := getAllTools(m.in) - m.out.Metadata.Tools = &cydx.ToolsChoice{ - Components: &[]cydx.Component{}, - } - *m.out.Metadata.Tools.Components = append(*m.out.Metadata.Tools.Components, tools...) - - // Add the primary component to the list of components - for _, c := range priComps { - comps = append(comps, *c) - } - - // Add depedencies between new primary component and old primary components - priIds := lo.Map(priComps, func(c *cydx.Component, _ int) string { - return c.BOMRef - }) - - deps = append(deps, cydx.Dependency{ - Ref: m.out.Metadata.Component.BOMRef, - Dependencies: &priIds, - }) - - if m.settings.Assemble.IncludeComponents { - m.out.Components = &comps - } - - if m.settings.Assemble.IncludeDependencyGraph { - m.out.Dependencies = &deps - } - - return m.writeSBOM() -} +func (m *merge) processSBOM() error { + var output io.Writer + var sb strings.Builder -func (m *merge) assemblyMerge() error { log := logger.FromContext(*m.settings.Ctx) - cs := newComponentService(*m.settings.Ctx) - - log.Debug("Merging BOMs as an assembly") - - priComps := lo.Map(m.in, func(bom *cydx.BOM, _ int) *cydx.Component { - if bom.Metadata != nil && bom.Metadata.Component != nil { - pc := cs.StoreAndCloneWithNewID(bom.Metadata.Component) - - if pc.Components == nil { - pc.Components = &[]cydx.Component{} - } - for _, c := range lo.FromPtr(bom.Components) { - *pc.Components = append(*pc.Components, *cs.StoreAndCloneWithNewID(&c)) - } - return pc - } - return &cydx.Component{} - }) - - deps := lo.Flatten(lo.Map(m.in, func(bom *cydx.BOM, _ int) []cydx.Dependency { - newDeps := []cydx.Dependency{} - for _, dep := range lo.FromPtr(bom.Dependencies) { - nd := cydx.Dependency{} - ref, found := cs.ResolveDepID(dep.Ref) - if !found { - log.Warnf("dependency %s not found", dep.Ref) - continue - } - - deps := cs.ResolveDepIDs(lo.FromPtr(dep.Dependencies)) - - nd.Ref = ref - nd.Dependencies = &deps - newDeps = append(newDeps, nd) + if m.settings.Output.Upload { + output = &sb + } else if m.settings.Output.File == "" { + output = os.Stdout + } else { + f, err := os.Create(m.settings.Output.File) + if err != nil { + return err } - return newDeps - })) - - m.out.Metadata.Component = m.setupPrimaryComp() - - m.out.Metadata.Component.Components = &[]cydx.Component{} - for _, c := range priComps { - *m.out.Metadata.Component.Components = append(*m.out.Metadata.Component.Components, *c) + defer f.Close() + output = f } - tools := getAllTools(m.in) - m.out.Metadata.Tools = &cydx.ToolsChoice{ - Components: &[]cydx.Component{}, + var encoder cydx.BOMEncoder + switch m.settings.Output.FileFormat { + case "xml": + log.Debugf("writing sbom in xml format") + encoder = cydx.NewBOMEncoder(output, cydx.BOMFileFormatXML) + default: + log.Debugf("writing sbom in json format") + encoder = cydx.NewBOMEncoder(output, cydx.BOMFileFormatJSON) } - *m.out.Metadata.Tools.Components = append(*m.out.Metadata.Tools.Components, tools...) - if m.settings.Assemble.IncludeComponents { - m.out.Components = &[]cydx.Component{} - for _, c := range priComps { - *m.out.Components = append(*m.out.Components, *c) - } - } + encoder.SetPretty(true) + encoder.SetEscapeHTML(true) - if m.settings.Assemble.IncludeDependencyGraph { - m.out.Dependencies = &deps + var err error + if m.settings.Output.SpecVersion == "" { + err = encoder.Encode(m.out) + } else { + log.Debugf("writing sbom in version %s", m.settings.Output.SpecVersion) + outputVersion := specVersionMap[m.settings.Output.SpecVersion] + err = encoder.EncodeVersion(m.out, outputVersion) } - return m.writeSBOM() -} - -func (m *merge) hierarchicalMerge() error { - log := logger.FromContext(*m.settings.Ctx) - cs := newComponentService(*m.settings.Ctx) - - log.Debug("Merging BOMs hierarchically") - - priComps := lo.Map(m.in, func(bom *cydx.BOM, _ int) *cydx.Component { - if bom.Metadata != nil && bom.Metadata.Component != nil { - pc := cs.StoreAndCloneWithNewID(bom.Metadata.Component) - - if pc.Components == nil { - pc.Components = &[]cydx.Component{} - } - - for _, c := range lo.FromPtr(bom.Components) { - *pc.Components = append(*pc.Components, *cs.StoreAndCloneWithNewID(&c)) - } - return pc - } - return &cydx.Component{} - }) - - deps := lo.Flatten(lo.Map(m.in, func(bom *cydx.BOM, _ int) []cydx.Dependency { - newDeps := []cydx.Dependency{} - for _, dep := range lo.FromPtr(bom.Dependencies) { - nd := cydx.Dependency{} - ref, found := cs.ResolveDepID(dep.Ref) - if !found { - log.Warnf("dependency %s not found", dep.Ref) - continue - } - - deps := cs.ResolveDepIDs(lo.FromPtr(dep.Dependencies)) - - nd.Ref = ref - nd.Dependencies = &deps - newDeps = append(newDeps, nd) - } - return newDeps - })) - - m.out.Metadata.Component = m.setupPrimaryComp() - - tools := getAllTools(m.in) - m.out.Metadata.Tools = &cydx.ToolsChoice{ - Components: &[]cydx.Component{}, - } - *m.out.Metadata.Tools.Components = append(*m.out.Metadata.Tools.Components, tools...) - - // Add depedencies between new primary component and old primary components - priIds := lo.Map(priComps, func(c *cydx.Component, _ int) string { - return c.BOMRef - }) - - deps = append(deps, cydx.Dependency{ - Ref: m.out.Metadata.Component.BOMRef, - Dependencies: &priIds, - }) - - if m.settings.Assemble.IncludeComponents { - m.out.Components = &[]cydx.Component{} - for _, c := range priComps { - *m.out.Components = append(*m.out.Components, *c) - } + if err != nil { + return err } - if m.settings.Assemble.IncludeDependencyGraph { - m.out.Dependencies = &deps - } if m.settings.Output.Upload { - m.uploadSBOM() + return m.uploadToServer(sb.String()) } - return m.writeSBOM() + return nil } -func (m *merge) uploadSBOM() error { +func (m *merge) uploadToServer(bomContent string) error { log := logger.FromContext(*m.settings.Ctx) + + log.Debugf("uploading sbom to %s", m.settings.Output.Url) + dTrackClient, err := dtrack.NewClient(m.settings.Output.Url, dtrack.WithAPIKey(m.settings.Output.ApiKey), dtrack.WithDebug(false)) if err != nil { log.Fatalf("Failed to create Dependency-Track client: %s", err) + return err } - var sb strings.Builder - var encoder cydx.BOMEncoder - - switch m.settings.Output.FileFormat { - case "xml": - encoder = cydx.NewBOMEncoder(&sb, cydx.BOMFileFormatXML) - default: - encoder = cydx.NewBOMEncoder(&sb, cydx.BOMFileFormatJSON) - } - - encoder.SetPretty(true) - encoder.SetEscapeHTML(true) - - if m.settings.Output.SpecVersion == "" { - if err := encoder.Encode(m.out); err != nil { - return err - } - } else { - outputVersion := specVersionMap[m.settings.Output.SpecVersion] - if err := encoder.EncodeVersion(m.out, outputVersion); err != nil { - return err - } - } - - dtUpload := dtrack.BOMUploadRequest{ - BOM: sb.String(), - } - encodedBOM := base64.StdEncoding.EncodeToString([]byte(dtUpload.BOM)) - - var token dtrack.BOMUploadToken + encodedBOM := base64.StdEncoding.EncodeToString([]byte(bomContent)) bomUploadRequest := dtrack.BOMUploadRequest{ ProjectUUID: &m.settings.Output.UploadProjectID, BOM: encodedBOM, } - if token, err = dTrackClient.BOM.Upload(*m.settings.Ctx, bomUploadRequest); err != nil { + token, err := dTrackClient.BOM.Upload(*m.settings.Ctx, bomUploadRequest) + if err != nil { log.Fatalf("Failed to upload BOM: %s", err) return err } - log.Debugf("bom upload token: %v", token) - - return err -} - -func (m *merge) writeSBOM() error { - var f io.Writer - - if m.settings.Output.File == "" { - f = os.Stdout - } else { - var err error - f, err = os.Create(m.settings.Output.File) - if err != nil { - return err - } - } - - var encoder cydx.BOMEncoder - - switch m.settings.Output.FileFormat { - case "xml": - encoder = cydx.NewBOMEncoder(f, cydx.BOMFileFormatXML) - default: - encoder = cydx.NewBOMEncoder(f, cydx.BOMFileFormatJSON) - } - - encoder.SetPretty(true) - encoder.SetEscapeHTML(true) - - if m.settings.Output.SpecVersion == "" { - if err := encoder.Encode(m.out); err != nil { - return err - } - } else { - outputVersion := specVersionMap[m.settings.Output.SpecVersion] - - if err := encoder.EncodeVersion(m.out, outputVersion); err != nil { - return err - } - } + log.Debugf("bom upload token: %v", token) return nil } diff --git a/pkg/assemble/cdx/util.go b/pkg/assemble/cdx/util.go index c52c750..4397d6e 100644 --- a/pkg/assemble/cdx/util.go +++ b/pkg/assemble/cdx/util.go @@ -27,7 +27,7 @@ import ( "github.com/interlynk-io/sbomasm/pkg/detect" "github.com/interlynk-io/sbomasm/pkg/logger" "github.com/mitchellh/copystructure" - "github.com/mitchellh/hashstructure/v2" + "github.com/samber/lo" "sigs.k8s.io/release-utils/version" ) @@ -48,13 +48,10 @@ func newSerialNumber() string { return fmt.Sprintf("urn:uuid:%s", u) } -func newBomRef(obj interface{}) string { - f, _ := hashstructure.Hash(obj, hashstructure.FormatV2, &hashstructure.HashOptions{ - ZeroNil: true, - SlicesAsSets: true, - }) +func newBomRef() string { + u := uuid.New().String() - return fmt.Sprintf("%x", f) + return fmt.Sprintf("lynk:%s", u) } func cloneComp(c *cydx.Component) (*cydx.Component, error) { @@ -66,6 +63,15 @@ func cloneComp(c *cydx.Component) (*cydx.Component, error) { return compCopy.(*cydx.Component), nil } +func cloneService(s *cydx.Service) (*cydx.Service, error) { + serviceCopy, err := copystructure.Copy(s) + if err != nil { + return nil, err + } + + return serviceCopy.(*cydx.Service), nil +} + func loadBom(ctx context.Context, path string) (*cydx.BOM, error) { log := logger.FromContext(ctx) @@ -111,27 +117,6 @@ func utcNowTime() string { return locationTime.Format(time.RFC3339) } -func getAllTools(boms []*cydx.BOM) []cydx.Component { - tools := []cydx.Component{} - - tools = append(tools, *toolInfo("sbomasm", version.GetVersionInfo().GitVersion, "Assembler for your sboms", "Interlynk", "https://interlynk.io", "support@interlynk.io", "Apache-2.0")) - - for _, bom := range boms { - if bom.Metadata != nil && bom.Metadata.Tools != nil { - for _, tool := range *bom.Metadata.Tools.Tools { - tools = append(tools, *toolInfo(tool.Name, tool.Version, "", tool.Vendor, "", "", "")) - } - } - - if bom.Metadata != nil && bom.Metadata.Tools != nil && bom.Metadata.Tools.Components != nil { - for _, tool := range *bom.Metadata.Tools.Components { - tools = append(tools, *toolInfo(tool.Name, tool.Version, "", "", "", "", "")) - } - } - } - return tools -} - func toolInfo(name, version, desc, sName, sUrl, sEmail, sLicense string) *cydx.Component { return &cydx.Component{ Type: cydx.ComponentTypeApplication, @@ -152,3 +137,74 @@ func toolInfo(name, version, desc, sName, sUrl, sEmail, sLicense string) *cydx.C }, } } + +func buildToolList(in []*cydx.BOM) *cydx.ToolsChoice { + tools := cydx.ToolsChoice{} + + tools.Services = &[]cydx.Service{} + tools.Components = &[]cydx.Component{} + + *tools.Components = append(*tools.Components, *toolInfo("sbomasm", version.GetVersionInfo().GitVersion, "Assembler & Editor for your sboms", "Interlynk", "https://interlynk.io", "support@interlynk.io", "Apache-2.0")) + + for _, bom := range in { + if bom.Metadata != nil && bom.Metadata.Tools != nil { + for _, tool := range *bom.Metadata.Tools.Tools { + *tools.Components = append(*tools.Components, *toolInfo(tool.Name, tool.Version, "", tool.Vendor, "", "", "")) + } + } + + if bom.Metadata != nil && bom.Metadata.Tools != nil && bom.Metadata.Tools.Components != nil { + for _, tool := range *bom.Metadata.Tools.Components { + comp, _ := cloneComp(&tool) + *tools.Components = append(*tools.Components, *comp) + } + } + + if bom.Metadata != nil && bom.Metadata.Tools != nil && bom.Metadata.Tools.Services != nil { + for _, service := range *bom.Metadata.Tools.Services { + serv, _ := cloneService(&service) + *tools.Services = append(*tools.Services, *serv) + } + } + } + + return &tools +} + +func buildComponentList(in []*cydx.BOM, cs *ComponentService) []cydx.Component { + return lo.Flatten(lo.Map(in, func(bom *cydx.BOM, _ int) []cydx.Component { + newComps := []cydx.Component{} + for _, comp := range lo.FromPtr(bom.Components) { + newComps = append(newComps, *cs.StoreAndCloneWithNewID(&comp)) + } + return newComps + })) +} + +func buildPrimaryComponentList(in []*cydx.BOM, cs *ComponentService) []cydx.Component { + return lo.Map(in, func(bom *cydx.BOM, _ int) cydx.Component { + if bom.Metadata != nil && bom.Metadata.Component != nil { + return *cs.StoreAndCloneWithNewID(bom.Metadata.Component) + } + return cydx.Component{} + }) +} + +func buildDependencyList(in []*cydx.BOM, cs *ComponentService) []cydx.Dependency { + return lo.Flatten(lo.Map(in, func(bom *cydx.BOM, _ int) []cydx.Dependency { + newDeps := []cydx.Dependency{} + for _, dep := range lo.FromPtr(bom.Dependencies) { + nd := cydx.Dependency{} + ref, found := cs.ResolveDepID(dep.Ref) + if !found { + continue + } + + deps := cs.ResolveDepIDs(lo.FromPtr(dep.Dependencies)) + nd.Ref = ref + nd.Dependencies = &deps + newDeps = append(newDeps, nd) + } + return newDeps + })) +}