go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/resources/updates/mac_updates.go (about) 1 // Copyright (c) Mondoo, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package updates 5 6 import ( 7 "fmt" 8 "io" 9 "strings" 10 11 "go.mondoo.com/cnquery/providers/os/connection/shared" 12 "howett.net/plist" 13 ) 14 15 const ( 16 MacosUpdateFormat = "macos" 17 ) 18 19 type MacosUpdateManager struct { 20 conn shared.Connection 21 } 22 23 func (um *MacosUpdateManager) Name() string { 24 return "macOS Update Manager" 25 } 26 27 func (um *MacosUpdateManager) Format() string { 28 return MacosUpdateFormat 29 } 30 31 func (um *MacosUpdateManager) List() ([]OperatingSystemUpdate, error) { 32 f, err := um.conn.FileSystem().Open("/Library/Preferences/com.apple.SoftwareUpdate.plist") 33 defer f.Close() 34 if err != nil { 35 return nil, fmt.Errorf("could not read package list") 36 } 37 return ParseSoftwarePlistUpdates(f) 38 } 39 40 // parse macos system version property list 41 func ParseSoftwarePlistUpdates(input io.Reader) ([]OperatingSystemUpdate, error) { 42 var r io.ReadSeeker 43 r, ok := input.(io.ReadSeeker) 44 45 // if the read seaker is not implemented lets cache stdout in-memory 46 if !ok { 47 packageList, err := io.ReadAll(input) 48 if err != nil { 49 return nil, err 50 } 51 r = strings.NewReader(string(packageList)) 52 } 53 54 type recommendedUpdate struct { 55 Identifier string `plist:"Identifier"` 56 DisplayName string `plist:"Display Name"` 57 Version string `plist:"Display Version"` 58 MobileSoftwareUpdate bool `plist:"MobileSoftwareUpdate"` 59 ProductKey string `plist:"Product Key"` 60 } 61 62 type softwareUpdate struct { 63 RecommendedUpdates []recommendedUpdate `plist:"RecommendedUpdates"` 64 } 65 66 var data softwareUpdate 67 decoder := plist.NewDecoder(r) 68 err := decoder.Decode(&data) 69 if err != nil { 70 return nil, err 71 } 72 73 updates := make([]OperatingSystemUpdate, len(data.RecommendedUpdates)) 74 for i, entry := range data.RecommendedUpdates { 75 updates[i].ID = entry.ProductKey 76 updates[i].Name = entry.Identifier 77 updates[i].Description = entry.DisplayName 78 updates[i].Version = entry.Version 79 80 updates[i].Format = MacosUpdateFormat 81 } 82 83 return updates, nil 84 }