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  }