From 75ed47c17d5e051185278bf6f7389ba84c7c5bf9 Mon Sep 17 00:00:00 2001 From: Aleksandr Maus Date: Mon, 9 Aug 2021 07:28:34 -0700 Subject: [PATCH] Osquerybeat: Add support for input/integration level osquery platform/version/discovery configuration (#27233) --- x-pack/osquerybeat/beater/config_plugin.go | 10 +- .../osquerybeat/beater/config_plugin_test.go | 100 +++++++++--------- x-pack/osquerybeat/internal/config/config.go | 3 + 3 files changed, 59 insertions(+), 54 deletions(-) diff --git a/x-pack/osquerybeat/beater/config_plugin.go b/x-pack/osquerybeat/beater/config_plugin.go index 6ccf8aac794..454fd41e962 100644 --- a/x-pack/osquerybeat/beater/config_plugin.go +++ b/x-pack/osquerybeat/beater/config_plugin.go @@ -110,7 +110,10 @@ type query struct { } type pack struct { - Queries map[string]query `json:"queries,omitempty"` + Discovery []string `json:"discovery,omitempty"` + Platform string `json:"platform,omitempty"` + Version string `json:"version,omitempty"` + Queries map[string]query `json:"queries,omitempty"` } type osqueryConfig struct { @@ -151,7 +154,10 @@ func (p *ConfigPlugin) set(inputs []config.InputConfig) error { p.packs = make(map[string]pack) for _, input := range inputs { pack := pack{ - Queries: make(map[string]query), + Queries: make(map[string]query), + Platform: input.Platform, + Version: input.Version, + Discovery: input.Discovery, } for _, stream := range input.Streams { id := "pack_" + input.Name + "_" + stream.ID diff --git a/x-pack/osquerybeat/beater/config_plugin_test.go b/x-pack/osquerybeat/beater/config_plugin_test.go index cdcee417efa..9a9783e639d 100644 --- a/x-pack/osquerybeat/beater/config_plugin_test.go +++ b/x-pack/osquerybeat/beater/config_plugin_test.go @@ -19,11 +19,14 @@ import ( "github.com/google/go-cmp/cmp" ) -func renderFullConfig(inputs []config.InputConfig) (map[string]string, error) { +func renderFullConfigJSON(inputs []config.InputConfig) (string, error) { packs := make(map[string]pack) for _, input := range inputs { pack := pack{ - Queries: make(map[string]query), + Platform: input.Platform, + Version: input.Version, + Discovery: input.Discovery, + Queries: make(map[string]query), } for _, stream := range input.Streams { query := query{ @@ -39,12 +42,10 @@ func renderFullConfig(inputs []config.InputConfig) (map[string]string, error) { } raw, err := newOsqueryConfig(packs).render() if err != nil { - return nil, err + return "", err } - return map[string]string{ - configName: string(raw), - }, nil + return string(raw), nil } func TestConfigPluginNew(t *testing.T) { @@ -241,23 +242,45 @@ func TestSet(t *testing.T) { "schedule_splay_percent": 10 } }` + oneInputConfig := []config.InputConfig{ + { + Name: "osquery-manager-1", + Type: "osquery", + Platform: "posix", + Version: "4.7.0", + Discovery: []string{ + "SELECT pid FROM processes WHERE name = 'foobar';", + "SELECT 1 FROM users WHERE username like 'www%';", + }, + Streams: []config.StreamConfig{ + { + ID: "users", + Query: "select * from users limit 2", + Interval: 60, + ECSMapping: map[string]interface{}{ + "user": map[string]interface{}{ + "custom": map[string]interface{}{ + "shoeSize": map[string]interface{}{ + "value": 45, + }, + }, + "id": map[string]interface{}{ + "field": "uid", + }, + "name": map[string]interface{}{ + "field": "username", + }, + }, + }, + }, + }, + }, + } - const oneInputConfig = `{ - "options": { - "schedule_splay_percent": 10 - }, - "packs": { - "osquery-manager-1": { - "queries": { - "users": { - "query": "select * from users limit 2", - "interval": 60, - "snapshot": true - } - } - } - } -}` + oneInputPackConfig, err := renderFullConfigJSON(oneInputConfig) + if err != nil { + t.Fatal(err) + } tests := []struct { name string @@ -276,36 +299,9 @@ func TestSet(t *testing.T) { scfg: noQueriesConfig, }, { - name: "one input", - inputs: []config.InputConfig{ - { - Name: "osquery-manager-1", - Type: "osquery", - Streams: []config.StreamConfig{ - { - ID: "users", - Query: "select * from users limit 2", - Interval: 60, - ECSMapping: map[string]interface{}{ - "user": map[string]interface{}{ - "custom": map[string]interface{}{ - "shoeSize": map[string]interface{}{ - "value": 45, - }, - }, - "id": map[string]interface{}{ - "field": "uid", - }, - "name": map[string]interface{}{ - "field": "username", - }, - }, - }, - }, - }, - }, - }, - scfg: oneInputConfig, + name: "one input", + inputs: oneInputConfig, + scfg: oneInputPackConfig, ecsm: ecs.Mapping{ "user.custom.shoeSize": ecs.MappingInfo{ Value: 45, diff --git a/x-pack/osquerybeat/internal/config/config.go b/x-pack/osquerybeat/internal/config/config.go index 53cfeabd396..04846655ec4 100644 --- a/x-pack/osquerybeat/internal/config/config.go +++ b/x-pack/osquerybeat/internal/config/config.go @@ -35,6 +35,9 @@ type InputConfig struct { Type string `config:"type"` Streams []StreamConfig `config:"streams"` Processors processors.PluginConfig `config:"processors"` + Platform string `config:"iplatform"` // restrict all queries to a given platform, default is 'all' platforms; you may use commas to set multiple platforms + Version string `config:"iversion"` // only run the queries with osquery versions greater than or equal-to this version string + Discovery []string `config:"discovery"` // a list of discovery queries https://osquery.readthedocs.io/en/stable/deployment/configuration/#discovery-queries } type Config struct {