diff --git a/Makefile b/Makefile index 66b2705024..64c0f85056 100644 --- a/Makefile +++ b/Makefile @@ -235,6 +235,13 @@ binary-bundle: xp-fleet xp-fleetctl cd build/binary-bundle && cp windows/fleetctl.exe . && zip fleetctl.exe.zip fleetctl.exe cd build/binary-bundle && shasum -a 256 fleet.zip fleetctl.exe.zip fleetctl-macos.tar.gz fleetctl-windows.tar.gz fleetctl-linux.tar.gz +# Build orbit/fleetd fleetd_tables extension +fleetd-tables-windows: + GOOS=windows GOARCH=amd64 go build -o fleetd_tables_windows.ext ./orbit/cmd/fleetd_tables +fleetd-tables-linux: + GOOS=linux GOARCH=amd64 go build -o fleetd_tables_linux.ext ./orbit/cmd/fleetd_tables +fleetd-tables-darwin: + GOOS=darwin GOARCH=amd64 go build -o fleetd_tables_darwin.ext ./orbit/cmd/fleetd_tables .pre-binary-arch: ifndef GOOS diff --git a/orbit/cmd/fleetd_tables/README.md b/orbit/cmd/fleetd_tables/README.md new file mode 100644 index 0000000000..07acc2a7fd --- /dev/null +++ b/orbit/cmd/fleetd_tables/README.md @@ -0,0 +1,56 @@ +# Fleet osquery extensions without fleetd + +If you are interested in getting some of the `fleetd` tables but cannot run `fleetd` natively then its possible +to utilize this "fleetd_tables" extension with standalone `osqueryd`. + +### Building the extension + +First run (note `.ext` is required for osquery): +```shell +go build -o fleetd_tables.ext fleetd_tables.go +``` + +or using the Makefile +```shell +make fleetd-tables-linux +``` + +Then move it somewhere `osqueryd` can load it: +```shell +sudo cp fleetd_tables.ext /usr/local/osquery_extensions +``` + +And tell `osqueryd` to autoload your extension +```shell +echo "/usr/local/osquery_extensions/fleetd_tables.ext" > /tmp/extensions.load +``` + +Finally, launch `osqueryd` +```shell +sudo osqueryd --extensions_autoload=/tmp/extensions.load +``` + +### Local testing + +Obtain the extensions_socket +```shell +osqueryi --nodisable_extensions +osquery> select value from osquery_flags where name = 'extensions_socket'; ++-----------------------------------+ +| value | ++-----------------------------------+ +| /Users/USERNAME/.osquery/shell.em | ++-----------------------------------+ +``` + +Then run the app +```shell +go run ./fleetd_tables.go --socket /Users/USERNAME/.osquery/shell.em +``` + +Or you can build the app and have `osqueryi` load it +```shell +go build -o fleetd_tables.ext fleetd_tables.go +osqueryi --extension /path/to/fleetd_tables.ext +``` + diff --git a/orbit/cmd/fleetd_tables/fleetd_tables.go b/orbit/cmd/fleetd_tables/fleetd_tables.go new file mode 100644 index 0000000000..037a60b8f4 --- /dev/null +++ b/orbit/cmd/fleetd_tables/fleetd_tables.go @@ -0,0 +1,57 @@ +package main + +import ( + "flag" + "fmt" + "log" + "os" + "time" + + "github.com/cenkalti/backoff/v4" + orbittable "github.com/fleetdm/fleet/v4/orbit/pkg/table" + "github.com/osquery/osquery-go" +) + +var ( + socket = flag.String("socket", "", "Path to the extensions UNIX domain socket") + timeout = flag.Int("timeout", 3, "Seconds to wait for autoloaded extensions") + interval = flag.Int("interval", 3, "Seconds delay between connectivity checks") +) + +func main() { + flag.Parse() + + if *socket == "" { + log.Fatalf(`Usage: %s -socket SOCKET_PATH`, os.Args[0]) + } + + serverTimeout := osquery.ServerTimeout( + time.Second * time.Duration(*timeout), + ) + serverPingInterval := osquery.ServerPingInterval( + time.Second * time.Duration(*interval), + ) + + var server *osquery.ExtensionManagerServer + backOff := backoff.WithMaxRetries(backoff.NewConstantBackOff(time.Millisecond*200), 25) // retry once per 200ms for 25 times == 5 seconds + op := func() error { + s, err := osquery.NewExtensionManagerServer("com.fleetdm.fleetd_tables.osquery_extension.v1", *socket, serverTimeout, serverPingInterval) + if err != nil { + return fmt.Errorf("error creating extension: %w", err) + } + server = s + return nil + } + + err := backoff.Retry(op, backOff) + if err != nil { + log.Fatalln(err) + } + + plugins := orbittable.OrbitDefaultTables() + plugins = append(plugins, orbittable.PlatformTables()...) + server.RegisterPlugin(plugins...) + if err := server.Run(); err != nil { + log.Fatalln(err) + } +} diff --git a/orbit/pkg/table/extension.go b/orbit/pkg/table/extension.go index 2a2f749586..bb7a888dc8 100644 --- a/orbit/pkg/table/extension.go +++ b/orbit/pkg/table/extension.go @@ -93,18 +93,9 @@ func (r *Runner) Execute() error { } } - plugins := []osquery.OsqueryPlugin{ - // MacAdmins extensions. - table.NewPlugin("puppet_info", puppet.PuppetInfoColumns(), puppet.PuppetInfoGenerate), - table.NewPlugin("puppet_logs", puppet.PuppetLogsColumns(), puppet.PuppetLogsGenerate), - table.NewPlugin("puppet_state", puppet.PuppetStateColumns(), puppet.PuppetStateGenerate), - table.NewPlugin("google_chrome_profiles", chromeuserprofiles.GoogleChromeProfilesColumns(), chromeuserprofiles.GoogleChromeProfilesGenerate), - table.NewPlugin("file_lines", fileline.FileLineColumns(), fileline.FileLineGenerate), + plugins := OrbitDefaultTables() - // Orbit extensions. - table.NewPlugin("sntp_request", sntp_request.Columns(), sntp_request.GenerateFunc), - } - plugins = append(plugins, platformTables()...) + plugins = append(plugins, PlatformTables()...) for _, t := range r.tableExtensions { plugins = append(plugins, table.NewPlugin( t.Name(), @@ -121,6 +112,21 @@ func (r *Runner) Execute() error { return nil } +func OrbitDefaultTables() []osquery.OsqueryPlugin { + plugins := []osquery.OsqueryPlugin{ + // MacAdmins extensions. + table.NewPlugin("puppet_info", puppet.PuppetInfoColumns(), puppet.PuppetInfoGenerate), + table.NewPlugin("puppet_logs", puppet.PuppetLogsColumns(), puppet.PuppetLogsGenerate), + table.NewPlugin("puppet_state", puppet.PuppetStateColumns(), puppet.PuppetStateGenerate), + table.NewPlugin("google_chrome_profiles", chromeuserprofiles.GoogleChromeProfilesColumns(), chromeuserprofiles.GoogleChromeProfilesGenerate), + table.NewPlugin("file_lines", fileline.FileLineColumns(), fileline.FileLineGenerate), + + // Orbit extensions. + table.NewPlugin("sntp_request", sntp_request.Columns(), sntp_request.GenerateFunc), + } + return plugins +} + // Interrupt shuts down the osquery manager server. func (r *Runner) Interrupt(err error) { log.Debug().Err(err).Msg("interrupt osquery extension") diff --git a/orbit/pkg/table/extension_darwin.go b/orbit/pkg/table/extension_darwin.go index e4eb0fc057..5f1ccb1eed 100644 --- a/orbit/pkg/table/extension_darwin.go +++ b/orbit/pkg/table/extension_darwin.go @@ -25,7 +25,7 @@ import ( "github.com/osquery/osquery-go/plugin/table" ) -func platformTables() []osquery.OsqueryPlugin { +func PlatformTables() []osquery.OsqueryPlugin { return []osquery.OsqueryPlugin{ // Fleet tables table.NewPlugin("icloud_private_relay", privaterelay.Columns(), privaterelay.Generate), diff --git a/orbit/pkg/table/extension_stub.go b/orbit/pkg/table/extension_stub.go index ef6191e4cf..e204ddd49c 100644 --- a/orbit/pkg/table/extension_stub.go +++ b/orbit/pkg/table/extension_stub.go @@ -4,4 +4,4 @@ package table import "github.com/osquery/osquery-go" -func platformTables() []osquery.OsqueryPlugin { return nil } +func PlatformTables() []osquery.OsqueryPlugin { return nil } diff --git a/orbit/pkg/table/extension_windows.go b/orbit/pkg/table/extension_windows.go index 22f22ff550..74d5a2d748 100644 --- a/orbit/pkg/table/extension_windows.go +++ b/orbit/pkg/table/extension_windows.go @@ -8,7 +8,7 @@ import ( "github.com/osquery/osquery-go/plugin/table" ) -func platformTables() []osquery.OsqueryPlugin { +func PlatformTables() []osquery.OsqueryPlugin { return []osquery.OsqueryPlugin{ // Fleet tables table.NewPlugin("mdm_bridge", mdmbridge.Columns(), mdmbridge.Generate),