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  }