Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🐛 fix logjn #1965

Merged
merged 3 commits into from
Sep 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,15 @@
"args": [
"go", "./providers/os/resources/os.lr", "--dist", "./providers/os/dist",
],
},
{
"name": "cnquery-status",
"type": "go",
"request": "launch",
"program": "${workspaceRoot}/apps/cnquery/cnquery.go",
"args": [
"status",
],
}
]
}
5 changes: 4 additions & 1 deletion apps/cnquery/cmd/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,10 @@ func (s Status) RenderCliStatus() {
if len(s.Upstream.Features) > 0 {
log.Info().Msg("Features:\t" + strings.Join(s.Upstream.Features, ","))
}
log.Info().Msg("Owner:\t" + s.Client.ParentMrn)

if s.Client.ParentMrn == "" {
log.Info().Msg("Owner:\t" + s.Client.ParentMrn)
}

if s.Client.Registered {
log.Info().Msg("Client:\t" + s.Client.Mrn)
Expand Down
50 changes: 36 additions & 14 deletions cli/sysinfo/sysinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ package sysinfo
import (
"errors"

"github.com/rs/zerolog/log"
"go.mondoo.com/cnquery/providers/os/resources/networkinterface"

"go.mondoo.com/cnquery"
"go.mondoo.com/cnquery/cli/execruntime"
"go.mondoo.com/cnquery/llx"
Expand Down Expand Up @@ -44,20 +47,27 @@ func GatherSystemInfo(opts ...SystemInfoOption) (*SystemInfo, error) {
opt(cfg)
}

log.Debug().Msg("Gathering system information")
if cfg.runtime == nil {

cfg.runtime = providers.Coordinator.NewRuntime()

// TODO: we need to ensure that the os provider is available here

// init runtime
if err := cfg.runtime.UseProvider(providers.DefaultOsID); err != nil {
return nil, err
}

args, err := cfg.runtime.Provider.Instance.Plugin.ParseCLI(&plugin.ParseCLIReq{
Connector: "local",
})
if err != nil {
return nil, err
}

if err = cfg.runtime.Connect(&plugin.ConnectReq{Asset: args.Asset}); err != nil {
if err = cfg.runtime.Connect(&plugin.ConnectReq{
Asset: args.Asset,
}); err != nil {
return nil, err
}
}
Expand All @@ -68,7 +78,8 @@ func GatherSystemInfo(opts ...SystemInfoOption) (*SystemInfo, error) {
}

exec := mql.New(cfg.runtime, nil)
raw, err := exec.Exec("asset{*}", nil)
// TODO: it is not returning it as a MQL SingleValue, therefore we need to force it with return
raw, err := exec.Exec("return asset { name arch title family build version kind runtime labels ids }", nil)
if err != nil {
return sysInfo, err
}
Expand All @@ -82,23 +93,34 @@ func GatherSystemInfo(opts ...SystemInfoOption) (*SystemInfo, error) {
Build: llx.TRaw2T[string](vals["build"]),
Version: llx.TRaw2T[string](vals["version"]),
Kind: llx.TRaw2T[string](vals["kind"]),
Runtime: llx.TRaw2T[string](vals["Runtime"]),
Runtime: llx.TRaw2T[string](vals["runtime"]),
Labels: llx.TRaw2TMap[string](vals["labels"]),
}

platformID := llx.TRaw2TArr[string](vals["ids"])
if len(platformID) > 0 {
sysInfo.PlatformId = platformID[0]
}
} else {
return sysInfo, errors.New("returned asset detection type is incorrect")
}

// TODO: platform IDs
// idDetector := providers.HostnameDetector
// if pi.IsFamily(platform.FAMILY_WINDOWS) {
// idDetector = providers.MachineIdDetector
// }
// sysInfo.PlatformId = info.IDs[0]
// TODO: outbound ip
// sysInfo.IP = ip
// TODO: hostname
// sysInfo.Hostname = hn
// determine hostname
osRaw, err := exec.Exec("return os.hostname", nil)
if err != nil {
return sysInfo, err
}

if hostname, ok := osRaw.Value.(string); ok {
sysInfo.Hostname = hostname
}

// determine ip address
// TODO: move this to MQL and expose that information in the graph
ipAddr, err := networkinterface.GetOutboundIP()
if err == nil {
sysInfo.IP = ipAddr.String()
}

// detect the execution runtime
execEnv := execruntime.Detect()
Expand Down
2 changes: 1 addition & 1 deletion providers/os/connection/mock/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ func (c *Connection) ID() uint32 {
}

func (c *Connection) Type() shared.ConnectionType {
return "local"
return "mock"
}

func (c *Connection) Asset() *inventory.Asset {
Expand Down
109 changes: 109 additions & 0 deletions providers/os/resources/networkinterface/hostip.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Copyright (c) Mondoo, Inc.
// SPDX-License-Identifier: BUSL-1.1

package networkinterface

import (
"fmt"
"net"
"sort"

"github.com/cockroachdb/errors"
"github.com/rs/zerolog/log"
)

func filterNetworkInterface(interfaces []Interface, flagFilter func(flags net.Flags) bool) []Interface {
i := []Interface{}
for _, v := range interfaces {
if flagFilter(v.Flags) {
i = append(i, v)
}
}
return i
}

// byIfaceIndex Interface by its index
type byIfaceIndex []Interface

func (iface byIfaceIndex) Len() int { return len(iface) }
func (iface byIfaceIndex) Less(i, j int) bool { return iface[i].Index < iface[j].Index }
func (iface byIfaceIndex) Swap(i, j int) { iface[i], iface[j] = iface[j], iface[i] }

// HostIP extracts the best-guess for the IP of the host
// It will search ip v4 first and fallback to v6
func HostIP(interfaces []Interface) (ip string, err error) {
log.Debug().Int("interfaces", len(interfaces)).Msg("search ip")
// filter interfaces that are not up or a loopback/p2p interface
interfaces = filterNetworkInterface(interfaces, func(flags net.Flags) bool {
if (flags&net.FlagUp != 0) &&
(flags&net.FlagLoopback == 0) &&
(flags&net.FlagPointToPoint == 0) {
return true
}
return false
})

// sort interfaces by its index
sort.Sort(byIfaceIndex(interfaces))

var foundIPv4 net.IP
foundIPsv6 := []net.IP{}

// search for IPv4
for _, i := range interfaces {
addrs := i.Addrs
for _, addr := range addrs {
var foundIPv6 net.IP
switch v := addr.(type) {
case *net.IPAddr:
foundIPv4 = v.IP.To4()
foundIPv6 = v.IP.To16()
case *net.IPNet:
foundIPv4 = v.IP.To4()
foundIPv6 = v.IP.To16()
case *ipAddr:
foundIPv4 = v.IP.To4()
foundIPv6 = v.IP.To16()
}

if foundIPv4 != nil {
return foundIPv4.String(), nil
}
if foundIPv6 != nil {
foundIPsv6 = append(foundIPsv6, foundIPv6)
}
}
}

// search for IPv6
if len(foundIPsv6) > 0 {
return foundIPsv6[0].String(), nil
}

return "", fmt.Errorf("no IP address found")
}

// GetOutboundIP returns the local IP that is used for outbound connections
// It does not establish a real connection and the destination does not need to valid.
// Since its using udp protocol (unlike TCP) a handshake nor connection is required,
// / then it gets the local up address if it would connect to that target
// conn.LocalAddr().String() returns the local ip and port
//
// # NOTE be aware that this code does not work on remote targets
//
// @see this approach is derived from https://stackoverflow.com/a/37382208
func GetOutboundIP() (net.IP, error) {
conn, err := net.Dial("udp", "1.1.1.1:80")
if err != nil {
return nil, errors.Wrap(err, "could not determine outbound ip")
}
defer conn.Close()

localAddr := conn.LocalAddr().(*net.UDPAddr)

if localAddr == nil {
return nil, errors.New("could not determine outbound ip")
}

return localAddr.IP, nil
}
Loading
Loading