go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/cli/sysinfo/sysinfo.go (about) 1 // Copyright (c) Mondoo, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package sysinfo 5 6 import ( 7 "errors" 8 9 "github.com/rs/zerolog/log" 10 "go.mondoo.com/cnquery/providers/os/resources/networkinterface" 11 12 "go.mondoo.com/cnquery" 13 "go.mondoo.com/cnquery/cli/execruntime" 14 "go.mondoo.com/cnquery/llx" 15 "go.mondoo.com/cnquery/mql" 16 "go.mondoo.com/cnquery/providers" 17 "go.mondoo.com/cnquery/providers-sdk/v1/inventory" 18 "go.mondoo.com/cnquery/providers-sdk/v1/plugin" 19 ) 20 21 type sysInfoConfig struct { 22 runtime *providers.Runtime 23 } 24 25 type SystemInfoOption func(t *sysInfoConfig) error 26 27 func WithRuntime(r *providers.Runtime) SystemInfoOption { 28 return func(c *sysInfoConfig) error { 29 c.runtime = r 30 return nil 31 } 32 } 33 34 type SystemInfo struct { 35 Version string `json:"version,omitempty"` 36 Build string `json:"build,omitempty"` 37 Platform *inventory.Platform `json:"platform,omitempty"` 38 IP string `json:"ip,omitempty"` 39 Hostname string `json:"platform_hostname,omitempty"` 40 Labels map[string]string `json:"labels,omitempty"` 41 PlatformId string `json:"platform_id,omitempty"` 42 } 43 44 func GatherSystemInfo(opts ...SystemInfoOption) (*SystemInfo, error) { 45 cfg := &sysInfoConfig{} 46 for _, opt := range opts { 47 opt(cfg) 48 } 49 50 log.Debug().Msg("Gathering system information") 51 if cfg.runtime == nil { 52 cfg.runtime = providers.Coordinator.NewRuntime() 53 54 // init runtime 55 if _, err := providers.EnsureProvider("local", "", true, nil); err != nil { 56 return nil, err 57 } 58 if err := cfg.runtime.UseProvider(providers.DefaultOsID); err != nil { 59 return nil, err 60 } 61 args, err := cfg.runtime.Provider.Instance.Plugin.ParseCLI(&plugin.ParseCLIReq{ 62 Connector: "local", 63 }) 64 if err != nil { 65 return nil, err 66 } 67 68 if err = cfg.runtime.Connect(&plugin.ConnectReq{ 69 Asset: args.Asset, 70 }); err != nil { 71 return nil, err 72 } 73 } 74 75 sysInfo := &SystemInfo{ 76 Version: cnquery.GetVersion(), 77 Build: cnquery.GetBuild(), 78 } 79 80 exec := mql.New(cfg.runtime, nil) 81 // TODO: it is not returning it as a MQL SingleValue, therefore we need to force it with return 82 raw, err := exec.Exec("return asset { name arch title family build version kind runtime labels ids }", nil) 83 if err != nil { 84 return sysInfo, err 85 } 86 87 if vals, ok := raw.Value.(map[string]interface{}); ok { 88 sysInfo.Platform = &inventory.Platform{ 89 Name: llx.TRaw2T[string](vals["name"]), 90 Arch: llx.TRaw2T[string](vals["arch"]), 91 Title: llx.TRaw2T[string](vals["title"]), 92 Family: llx.TRaw2TArr[string](vals["family"]), 93 Build: llx.TRaw2T[string](vals["build"]), 94 Version: llx.TRaw2T[string](vals["version"]), 95 Kind: llx.TRaw2T[string](vals["kind"]), 96 Runtime: llx.TRaw2T[string](vals["runtime"]), 97 Labels: llx.TRaw2TMap[string](vals["labels"]), 98 } 99 100 platformID := llx.TRaw2TArr[string](vals["ids"]) 101 if len(platformID) > 0 { 102 sysInfo.PlatformId = platformID[0] 103 } 104 } else { 105 return sysInfo, errors.New("returned asset detection type is incorrect") 106 } 107 108 // determine hostname 109 osRaw, err := exec.Exec("return os.hostname", nil) 110 if err != nil { 111 return sysInfo, err 112 } 113 114 if hostname, ok := osRaw.Value.(string); ok { 115 sysInfo.Hostname = hostname 116 } 117 118 // determine ip address 119 // TODO: move this to MQL and expose that information in the graph 120 ipAddr, err := networkinterface.GetOutboundIP() 121 if err == nil { 122 sysInfo.IP = ipAddr.String() 123 } 124 125 // detect the execution runtime 126 execEnv := execruntime.Detect() 127 sysInfo.Labels = map[string]string{ 128 "environment": execEnv.Id, 129 } 130 131 return sysInfo, nil 132 }