From f6f026af0b275048a6649ff2dba0e6c3fc638715 Mon Sep 17 00:00:00 2001 From: Graham Gilbert Date: Tue, 14 Dec 2021 17:17:15 -0800 Subject: [PATCH 1/2] Network quality table --- Makefile | 3 + README.md | 1 + main.go | 2 + tables/networkquality/networkquality.go | 90 +++++++++++++++++++++++++ 4 files changed, 96 insertions(+) create mode 100644 tables/networkquality/networkquality.go diff --git a/Makefile b/Makefile index f959fc4..7329adf 100644 --- a/Makefile +++ b/Makefile @@ -33,8 +33,11 @@ clean: build: .pre-build GOOS=darwin GOARCH=amd64 go build -o build/darwin/${APP_NAME}.amd64.ext -pkgdir ${PKGDIR_TMP} GOOS=darwin GOARCH=arm64 go build -o build/darwin/${APP_NAME}.arm64.ext -pkgdir ${PKGDIR_TMP} + /usr/bin/lipo -create -output build/darwin/${APP_NAME}.ext build/darwin/${APP_NAME}.amd64.ext build/darwin/${APP_NAME}.arm64.ext GOOS=linux go build -o build/linux/${APP_NAME}.ext -pkgdir ${PKGDIR_TMP} GOOS=windows go build -o build/windows/${APP_NAME}.ext.exe -pkgdir ${PKGDIR_TMP} + /bin/rm build/darwin/${APP_NAME}.amd64.ext + /bin/rm build/darwin/${APP_NAME}.arm64.ext osqueryi: build sleep 2 diff --git a/README.md b/README.md index 1dc9be3..19cd2d3 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ For production deployment, you should refer to the [osquery documentation](https | `mdm` | Information on the device's MDM enrollment | macOS | Code based on work by [Kolide](https://github.com/kolide/launcher) | | `munki_info` | Information from the last [Munki](https://github.com/munki/munki) run | macOS | Code based on work by [Kolide](https://github.com/kolide/launcher) | | `munki_installs` | Items [Munki](https://github.com/munki/munki) is managing | macOS | Code based on work by [Kolide](https://github.com/kolide/launcher) | +| `network_quality` | Output from the `networkQuality` binary | macOS | This binary is only present on macOS 12 | | `puppet_info` | Information on the last [Puppet](https://puppetlabs.com) run | Linux / macOS / Windows | | | `puppet_logs` | Logs from the last [Puppet](https://puppetlabs.com) run | Linux / macOS / Windows | | | `puppet_state` | State of every resource [Puppet](https://puppetlabs.com) is managing | Linux / macOS / Windows | | diff --git a/main.go b/main.go index 2d31854..08cbc99 100644 --- a/main.go +++ b/main.go @@ -14,6 +14,7 @@ import ( macosprofiles "github.com/macadmins/osquery-extension/tables/macos_profiles" "github.com/macadmins/osquery-extension/tables/mdm" "github.com/macadmins/osquery-extension/tables/munki" + "github.com/macadmins/osquery-extension/tables/networkquality" "github.com/macadmins/osquery-extension/tables/puppet" "github.com/macadmins/osquery-extension/tables/unifiedlog" ) @@ -61,6 +62,7 @@ func main() { plugins = append(plugins, table.NewPlugin("mdm", mdm.MDMInfoColumns(), mdm.MDMInfoGenerate)) plugins = append(plugins, table.NewPlugin("munki_info", munki.MunkiInfoColumns(), munki.MunkiInfoGenerate)) plugins = append(plugins, table.NewPlugin("munki_installs", munki.MunkiInstallsColumns(), munki.MunkiInstallsGenerate)) + plugins = append(plugins, table.NewPlugin("network_quality", networkquality.NetworkQualityColumns(), networkquality.NetworkQualityGenerate)) plugins = append(plugins, table.NewPlugin("unified_log", unifiedlog.UnifiedLogColumns(), unifiedlog.UnifiedLogGenerate)) } diff --git a/tables/networkquality/networkquality.go b/tables/networkquality/networkquality.go new file mode 100644 index 0000000..1823ce8 --- /dev/null +++ b/tables/networkquality/networkquality.go @@ -0,0 +1,90 @@ +package networkquality + +import ( + "context" + "encoding/json" + "fmt" + "os" + "os/exec" + "strconv" + + "github.com/kolide/osquery-go/plugin/table" + "github.com/pkg/errors" +) + +type NetworkQualityOutput struct { + DlFlows int `json:"dl_flows"` + DlThroughput int `json:"dl_throughput"` + LudForeignH2ReqResp []int `json:"lud_foreign_h2_req_resp"` + LudForeignTCPHandshake443 []int `json:"lud_foreign_tcp_handshake_443"` + LudSelfDlH2 []float64 `json:"lud_self_dl_h2"` + LudSelfUlH2 []float64 `json:"lud_self_ul_h2"` + Responsiveness int `json:"responsiveness"` + UlFlows int `json:"ul_flows"` + UlThroughput int `json:"ul_throughput"` +} + +func NetworkQualityColumns() []table.ColumnDefinition { + return []table.ColumnDefinition{ + table.IntegerColumn("dl_throughput_kbps"), + table.IntegerColumn("ul_throughput_kbps"), + table.TextColumn("dl_throughput_mbps"), + table.TextColumn("ul_throughput_mbps"), + } +} + +// Generate will be called whenever the table is queried. Since our data in these +// plugins is flat it will return a single row. +func NetworkQualityGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) { + var results []map[string]string + output, err := runNetworkQuality() + if err != nil { + fmt.Println(err) + return results, err + } + + results = append(results, map[string]string{ + "dl_throughput_kbps": strconv.Itoa(output.DlThroughput), + "ul_throughput_kbps": strconv.Itoa(output.UlThroughput), + "dl_throughput_mbps": fmt.Sprintf("%.2f", float64(output.DlThroughput)/1000000), + "ul_throughput_mbps": fmt.Sprintf("%.2f", float64(output.UlThroughput)/1000000), + }) + + return results, nil +} + +func runNetworkQuality() (NetworkQualityOutput, error) { + var output NetworkQualityOutput + + // Just return if the binary isn't present + _, err := os.Stat("/usr/bin/networkQuality") + if err != nil { + if errors.Is(err, os.ErrNotExist) { + return output, nil + } + return output, err + } + + out, err := exec.Command("/usr/bin/networkQuality", "-c").Output() + + if err != nil { + return output, errors.Wrap(err, "networkQuality -c") + } + if err := json.Unmarshal(out, &output); err != nil { + return output, errors.Wrap(err, "unmarshalling networkQuality output") + } + + return output, nil + +} + +func Exists(name string) (bool, error) { + _, err := os.Stat(name) + if err == nil { + return true, nil + } + if errors.Is(err, os.ErrNotExist) { + return false, nil + } + return false, err +} From 40a96feaf7aabee33606b0ea6c5b19ee08717a19 Mon Sep 17 00:00:00 2001 From: Graham Gilbert Date: Tue, 14 Dec 2021 17:17:59 -0800 Subject: [PATCH 2/2] Comment --- tables/networkquality/networkquality.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tables/networkquality/networkquality.go b/tables/networkquality/networkquality.go index 1823ce8..5947853 100644 --- a/tables/networkquality/networkquality.go +++ b/tables/networkquality/networkquality.go @@ -34,7 +34,7 @@ func NetworkQualityColumns() []table.ColumnDefinition { } // Generate will be called whenever the table is queried. Since our data in these -// plugins is flat it will return a single row. +// results is flat it will return a single row. func NetworkQualityGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) { var results []map[string]string output, err := runNetworkQuality()