github.com/nextlinux/gosbom@v0.81.1-0.20230627115839-1ff50c281391/gosbom/formats/common/cyclonedxhelpers/external_references.go (about) 1 package cyclonedxhelpers 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/CycloneDX/cyclonedx-go" 8 gosbomFile "github.com/nextlinux/gosbom/gosbom/file" 9 "github.com/nextlinux/gosbom/gosbom/pkg" 10 ) 11 12 //nolint:gocognit 13 func encodeExternalReferences(p pkg.Package) *[]cyclonedx.ExternalReference { 14 var refs []cyclonedx.ExternalReference 15 if hasMetadata(p) { 16 switch metadata := p.Metadata.(type) { 17 case pkg.ApkMetadata: 18 if metadata.URL != "" { 19 refs = append(refs, cyclonedx.ExternalReference{ 20 URL: metadata.URL, 21 Type: cyclonedx.ERTypeDistribution, 22 }) 23 } 24 case pkg.CargoPackageMetadata: 25 if metadata.Source != "" { 26 refs = append(refs, cyclonedx.ExternalReference{ 27 URL: metadata.Source, 28 Type: cyclonedx.ERTypeDistribution, 29 }) 30 } 31 case pkg.NpmPackageJSONMetadata: 32 if metadata.URL != "" { 33 refs = append(refs, cyclonedx.ExternalReference{ 34 URL: metadata.URL, 35 Type: cyclonedx.ERTypeDistribution, 36 }) 37 } 38 if metadata.Homepage != "" { 39 refs = append(refs, cyclonedx.ExternalReference{ 40 URL: metadata.Homepage, 41 Type: cyclonedx.ERTypeWebsite, 42 }) 43 } 44 case pkg.GemMetadata: 45 if metadata.Homepage != "" { 46 refs = append(refs, cyclonedx.ExternalReference{ 47 URL: metadata.Homepage, 48 Type: cyclonedx.ERTypeWebsite, 49 }) 50 } 51 case pkg.JavaMetadata: 52 if len(metadata.ArchiveDigests) > 0 { 53 for _, digest := range metadata.ArchiveDigests { 54 refs = append(refs, cyclonedx.ExternalReference{ 55 URL: "", 56 Type: cyclonedx.ERTypeBuildMeta, 57 Hashes: &[]cyclonedx.Hash{{ 58 Algorithm: toCycloneDXAlgorithm(digest.Algorithm), 59 Value: digest.Value, 60 }}, 61 }) 62 } 63 } 64 case pkg.PythonPackageMetadata: 65 if metadata.DirectURLOrigin != nil && metadata.DirectURLOrigin.URL != "" { 66 ref := cyclonedx.ExternalReference{ 67 URL: metadata.DirectURLOrigin.URL, 68 Type: cyclonedx.ERTypeVCS, 69 } 70 if metadata.DirectURLOrigin.CommitID != "" { 71 ref.Comment = fmt.Sprintf("commit: %s", metadata.DirectURLOrigin.CommitID) 72 } 73 refs = append(refs, ref) 74 } 75 } 76 } 77 if len(refs) > 0 { 78 return &refs 79 } 80 return nil 81 } 82 83 // supported algorithm in cycloneDX as of 1.4 84 // "MD5", "SHA-1", "SHA-256", "SHA-384", "SHA-512", 85 // "SHA3-256", "SHA3-384", "SHA3-512", "BLAKE2b-256", "BLAKE2b-384", "BLAKE2b-512", "BLAKE3" 86 // gosbom supported digests: cmd/gosbom/cli/eventloop/tasks.go 87 // MD5, SHA1, SHA256 88 func toCycloneDXAlgorithm(algorithm string) cyclonedx.HashAlgorithm { 89 validMap := map[string]cyclonedx.HashAlgorithm{ 90 "sha1": cyclonedx.HashAlgorithm("SHA-1"), 91 "md5": cyclonedx.HashAlgorithm("MD5"), 92 "sha256": cyclonedx.HashAlgorithm("SHA-256"), 93 } 94 95 return validMap[algorithm] 96 } 97 98 func decodeExternalReferences(c *cyclonedx.Component, metadata interface{}) { 99 if c.ExternalReferences == nil { 100 return 101 } 102 switch meta := metadata.(type) { 103 case *pkg.ApkMetadata: 104 meta.URL = refURL(c, cyclonedx.ERTypeDistribution) 105 case *pkg.CargoPackageMetadata: 106 meta.Source = refURL(c, cyclonedx.ERTypeDistribution) 107 case *pkg.NpmPackageJSONMetadata: 108 meta.URL = refURL(c, cyclonedx.ERTypeDistribution) 109 meta.Homepage = refURL(c, cyclonedx.ERTypeWebsite) 110 case *pkg.GemMetadata: 111 meta.Homepage = refURL(c, cyclonedx.ERTypeWebsite) 112 case *pkg.JavaMetadata: 113 var digests []gosbomFile.Digest 114 if ref := findExternalRef(c, cyclonedx.ERTypeBuildMeta); ref != nil { 115 if ref.Hashes != nil { 116 for _, hash := range *ref.Hashes { 117 digests = append(digests, gosbomFile.Digest{ 118 Algorithm: gosbomFile.CleanDigestAlgorithmName(string(hash.Algorithm)), 119 Value: hash.Value, 120 }) 121 } 122 } 123 } 124 125 meta.ArchiveDigests = digests 126 case *pkg.PythonPackageMetadata: 127 if meta.DirectURLOrigin == nil { 128 meta.DirectURLOrigin = &pkg.PythonDirectURLOriginInfo{} 129 } 130 meta.DirectURLOrigin.URL = refURL(c, cyclonedx.ERTypeVCS) 131 meta.DirectURLOrigin.CommitID = strings.TrimPrefix(refComment(c, cyclonedx.ERTypeVCS), "commit: ") 132 } 133 } 134 135 func findExternalRef(c *cyclonedx.Component, typ cyclonedx.ExternalReferenceType) *cyclonedx.ExternalReference { 136 if c.ExternalReferences != nil { 137 for _, r := range *c.ExternalReferences { 138 if r.Type == typ { 139 return &r 140 } 141 } 142 } 143 return nil 144 } 145 146 func refURL(c *cyclonedx.Component, typ cyclonedx.ExternalReferenceType) string { 147 if r := findExternalRef(c, typ); r != nil { 148 return r.URL 149 } 150 return "" 151 } 152 153 func refComment(c *cyclonedx.Component, typ cyclonedx.ExternalReferenceType) string { 154 if r := findExternalRef(c, typ); r != nil { 155 return r.Comment 156 } 157 return "" 158 }