go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/resources/packages/rpm_updates.go (about)

     1  // Copyright (c) Mondoo, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package packages
     5  
     6  import (
     7  	"bufio"
     8  	"encoding/json"
     9  	"encoding/xml"
    10  	"io"
    11  )
    12  
    13  func ParseRpmUpdates(input io.Reader) (map[string]PackageUpdate, error) {
    14  	pkgs := map[string]PackageUpdate{}
    15  	scanner := bufio.NewScanner(input)
    16  	for scanner.Scan() {
    17  		line := scanner.Bytes()
    18  
    19  		// we try to parse the content into the struct
    20  		var pkg PackageUpdate
    21  		err := json.Unmarshal(line, &pkg)
    22  		if err != nil {
    23  			// there are string lines that cannot be parsed
    24  			continue
    25  		}
    26  		pkgs[pkg.Name] = pkg
    27  	}
    28  	return pkgs, nil
    29  }
    30  
    31  type zypperUpdate struct {
    32  	Name        string `xml:"name,attr"`
    33  	Kind        string `xml:"kind,attr"`
    34  	Arch        string `xml:"arch,attr"`
    35  	Edition     string `xml:"edition,attr"`
    36  	OldEdition  string `xml:"edition-old,attr"`
    37  	Status      string `xml:"status,attr"`
    38  	Category    string `xml:"category,attr"`
    39  	Severity    string `xml:"severity,attr"`
    40  	PkgManager  string `xml:"pkgmanager,attr"`
    41  	Restart     string `xml:"restart,attr"`
    42  	Interactive string `xml:"interactive,attr"`
    43  
    44  	Summary     string `xml:"summary"`
    45  	Description string `xml:"description"`
    46  }
    47  
    48  type zypper struct {
    49  	XMLNode xml.Name       `xml:"stream"`
    50  	Updates []zypperUpdate `xml:"update-status>update-list>update"`
    51  	Blocked []zypperUpdate `xml:"update-status>blocked-update-list>update"`
    52  }
    53  
    54  // for Suse, updates are package updates
    55  // parses the output of `zypper -n --xmlout list-updates`
    56  func ParseZypperUpdates(input io.Reader) (map[string]PackageUpdate, error) {
    57  	pkgs := map[string]PackageUpdate{}
    58  	zypper, err := ParseZypper(input)
    59  	if err != nil {
    60  		return nil, err
    61  	}
    62  
    63  	for _, u := range zypper.Updates {
    64  		// filter for kind package
    65  		if u.Kind != "package" {
    66  			continue
    67  		}
    68  		pkgs[u.Name] = PackageUpdate{
    69  			Name:      u.Name,
    70  			Version:   u.OldEdition,
    71  			Arch:      u.Arch,
    72  			Available: u.Edition,
    73  		}
    74  	}
    75  	return pkgs, nil
    76  }
    77  
    78  func ParseZypper(input io.Reader) (*zypper, error) {
    79  	content, err := io.ReadAll(input)
    80  	if err != nil {
    81  		return nil, err
    82  	}
    83  	var patches zypper
    84  	err = xml.Unmarshal(content, &patches)
    85  	if err != nil {
    86  		return nil, err
    87  	}
    88  	return &patches, nil
    89  }