github.com/google/osv-scalibr@v0.4.1/binary/proto/inventory.go (about) 1 // Copyright 2025 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package proto 16 17 import ( 18 "fmt" 19 20 "github.com/google/osv-scalibr/extractor" 21 "github.com/google/osv-scalibr/inventory" 22 "github.com/google/osv-scalibr/log" 23 24 spb "github.com/google/osv-scalibr/binary/proto/scan_result_go_proto" 25 ) 26 27 // --- Struct to Proto 28 29 // InventoryToProto converts a Inventory go struct into the equivalent proto. 30 func InventoryToProto(inv *inventory.Inventory) (*spb.Inventory, error) { 31 if inv == nil { 32 return nil, nil 33 } 34 35 packages := make([]*spb.Package, 0, len(inv.Packages)) 36 pkgToID := make(map[*extractor.Package]string) 37 for _, pkg := range inv.Packages { 38 pkgProto, err := PackageToProto(pkg) 39 if err != nil { 40 return nil, err 41 } 42 packages = append(packages, pkgProto) 43 if pkgProto.Id == "" { 44 return nil, fmt.Errorf("package %v has no ID", pkg) 45 } 46 pkgToID[pkg] = pkgProto.Id 47 } 48 49 pkgVulns := make([]*spb.PackageVuln, 0, len(inv.PackageVulns)) 50 for _, v := range inv.PackageVulns { 51 p, err := PackageVulnToProto(v, pkgToID) 52 if err != nil { 53 return nil, err 54 } 55 pkgVulns = append(pkgVulns, p) 56 } 57 58 genericFindings := make([]*spb.GenericFinding, 0, len(inv.GenericFindings)) 59 for _, f := range inv.GenericFindings { 60 p, err := GenericFindingToProto(f) 61 if err != nil { 62 return nil, err 63 } 64 genericFindings = append(genericFindings, p) 65 } 66 67 secrets := make([]*spb.Secret, 0, len(inv.Secrets)) 68 for _, s := range inv.Secrets { 69 p, err := SecretToProto(s) 70 if err != nil { 71 return nil, err 72 } 73 secrets = append(secrets, p) 74 } 75 76 var containerImageMetadata []*spb.ContainerImageMetadata 77 for _, cim := range inv.ContainerImageMetadata { 78 containerImageMetadata = append(containerImageMetadata, containerImageMetadataToProto(cim)) 79 } 80 81 return &spb.Inventory{ 82 Packages: packages, 83 PackageVulns: pkgVulns, 84 GenericFindings: genericFindings, 85 Secrets: secrets, 86 ContainerImageMetadata: containerImageMetadata, 87 }, nil 88 } 89 90 // --- Proto to Struct 91 92 // InventoryToStruct converts a ScanResult proto into the equivalent go struct. 93 func InventoryToStruct(invProto *spb.Inventory) *inventory.Inventory { 94 if invProto == nil { 95 return nil 96 } 97 98 var packages []*extractor.Package 99 idToPkg := make(map[string]*extractor.Package) 100 for _, pProto := range invProto.GetPackages() { 101 p, err := PackageToStruct(pProto) 102 if err != nil { 103 log.Errorf("Failed to convert Package to struct: %v", err) 104 continue 105 } 106 packages = append(packages, p) 107 if idToPkg[pProto.Id] != nil { 108 log.Errorf("Duplicate package ID %q for %q", pProto.Id, pProto.Name) 109 continue 110 } 111 idToPkg[pProto.Id] = p 112 } 113 114 var pkgVulns []*inventory.PackageVuln 115 for _, pkgVulnProto := range invProto.GetPackageVulns() { 116 pkgVuln, err := PackageVulnToStruct(pkgVulnProto, idToPkg) 117 if err != nil { 118 log.Errorf("Failed to convert PackageVuln to struct: %v", err) 119 continue 120 } 121 pkgVulns = append(pkgVulns, pkgVuln) 122 } 123 124 var genericFindings []*inventory.GenericFinding 125 for _, fProto := range invProto.GetGenericFindings() { 126 f, err := GenericFindingToStruct(fProto) 127 if err != nil { 128 log.Errorf("Failed to convert GenericFinding to struct: %v", err) 129 continue 130 } 131 genericFindings = append(genericFindings, f) 132 } 133 134 var secrets []*inventory.Secret 135 for _, sProto := range invProto.GetSecrets() { 136 s, err := SecretToStruct(sProto) 137 if err != nil { 138 log.Errorf("Failed to convert Secret to struct: %v", err) 139 continue 140 } 141 secrets = append(secrets, s) 142 } 143 144 var containerImageMetadata []*extractor.ContainerImageMetadata 145 for _, cimProto := range invProto.GetContainerImageMetadata() { 146 cim := containerImageMetadataToStruct(cimProto) 147 containerImageMetadata = append(containerImageMetadata, cim) 148 for _, lm := range cim.LayerMetadata { 149 lm.ParentContainer = cim 150 } 151 } 152 153 for i, p := range packages { 154 pProto := invProto.GetPackages()[i] 155 cii := pProto.GetContainerImageMetadataIndexes() 156 157 if cii != nil && 158 int(cii.ContainerImageIndex) < len(containerImageMetadata) { 159 cim := containerImageMetadata[cii.ContainerImageIndex] 160 if int(cii.LayerIndex) < len(cim.LayerMetadata) { 161 p.LayerMetadata = cim.LayerMetadata[cii.LayerIndex] 162 } 163 } 164 } 165 166 return &inventory.Inventory{ 167 Packages: packages, 168 PackageVulns: pkgVulns, 169 GenericFindings: genericFindings, 170 Secrets: secrets, 171 ContainerImageMetadata: containerImageMetadata, 172 } 173 }