mirror of
https://github.com/empayre/fleet.git
synced 2024-11-06 08:55:24 +00:00
Update osquery service methods for distributed queries (#476)
This commit is contained in:
parent
b0e856c369
commit
9c38d6d19e
@ -6,6 +6,7 @@ import (
|
||||
"github.com/kolide/kolide-ose/server/config"
|
||||
"github.com/kolide/kolide-ose/server/datastore"
|
||||
"github.com/kolide/kolide-ose/server/kolide"
|
||||
"github.com/kolide/kolide-ose/server/pubsub"
|
||||
"github.com/kolide/kolide-ose/server/service"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/net/context"
|
||||
@ -82,7 +83,7 @@ To setup kolide infrastructure, use one of the available commands.
|
||||
Enabled: &enabled,
|
||||
Admin: &isAdmin,
|
||||
}
|
||||
svc, err := service.NewService(ds, kitlog.NewNopLogger(), config, nil, clock.C)
|
||||
svc, err := service.NewService(ds, pubsub.NewInmemQueryResults(), kitlog.NewNopLogger(), config, nil, clock.C)
|
||||
if err != nil {
|
||||
initFatal(err, "creating service")
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import (
|
||||
"github.com/kolide/kolide-ose/server/datastore"
|
||||
"github.com/kolide/kolide-ose/server/kolide"
|
||||
"github.com/kolide/kolide-ose/server/mail"
|
||||
"github.com/kolide/kolide-ose/server/pubsub"
|
||||
"github.com/kolide/kolide-ose/server/service"
|
||||
"github.com/kolide/kolide-ose/server/version"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
@ -84,7 +85,7 @@ the way that the kolide server works.
|
||||
}
|
||||
}
|
||||
|
||||
svc, err := service.NewService(ds, logger, config, mailService, clock.C)
|
||||
svc, err := service.NewService(ds, pubsub.NewInmemQueryResults(), logger, config, mailService, clock.C)
|
||||
if err != nil {
|
||||
initFatal(err, "initializing service")
|
||||
}
|
||||
@ -334,7 +335,7 @@ func createDevLabels(ds kolide.Datastore, config config.KolideConfig) {
|
||||
CreatedAt: time.Date(2016, time.October, 27, 8, 31, 16, 0, time.UTC),
|
||||
UpdatedAt: time.Date(2016, time.October, 27, 8, 31, 16, 0, time.UTC),
|
||||
Name: "dev_label_apache",
|
||||
Query: "select * from processes where nae like '%Apache%'",
|
||||
Query: "select * from processes where name like '%Apache%'",
|
||||
},
|
||||
{
|
||||
CreatedAt: time.Now().Add(-1 * time.Hour),
|
||||
|
@ -1,7 +1,6 @@
|
||||
package kolide
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
@ -101,9 +100,9 @@ const (
|
||||
)
|
||||
|
||||
type DistributedQueryResult struct {
|
||||
DistributedQueryCampaignID uint `json:"distributed_query_execution_id"`
|
||||
Host Host `json:"host"`
|
||||
ResultJSON json.RawMessage `json:"result_json"`
|
||||
DistributedQueryCampaignID uint `json:"distributed_query_execution_id"`
|
||||
Host Host `json:"host"`
|
||||
Rows []map[string]string `json:"rows"`
|
||||
}
|
||||
|
||||
type DistributedQueryExecution struct {
|
||||
|
@ -40,7 +40,12 @@ func (im *inmemQueryResults) WriteResult(result kolide.DistributedQueryResult) e
|
||||
return errors.New("no subscribers for channel")
|
||||
}
|
||||
|
||||
channel <- result
|
||||
select {
|
||||
case channel <- result:
|
||||
// intentionally do nothing
|
||||
default:
|
||||
return errors.New("no subscribers for channel")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package pubsub
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
@ -96,7 +95,7 @@ func testQueryResultsStoreErrors(t *testing.T, store kolide.QueryResultStore) {
|
||||
err := store.WriteResult(
|
||||
kolide.DistributedQueryResult{
|
||||
DistributedQueryCampaignID: 1,
|
||||
ResultJSON: json.RawMessage(`{"bing":"fds"}`),
|
||||
Rows: []map[string]string{{"bing": "fds"}},
|
||||
Host: kolide.Host{
|
||||
ID: 4,
|
||||
UpdatedAt: time.Now().UTC(),
|
||||
@ -118,7 +117,7 @@ func testQueryResultsStore(t *testing.T, store kolide.QueryResultStore) {
|
||||
expected1 := []kolide.DistributedQueryResult{
|
||||
kolide.DistributedQueryResult{
|
||||
DistributedQueryCampaignID: 1,
|
||||
ResultJSON: json.RawMessage(`{"foo":"bar"}`),
|
||||
Rows: []map[string]string{{"foo": "bar"}},
|
||||
Host: kolide.Host{
|
||||
ID: 1,
|
||||
// Note these times need to be set to avoid
|
||||
@ -130,7 +129,7 @@ func testQueryResultsStore(t *testing.T, store kolide.QueryResultStore) {
|
||||
},
|
||||
kolide.DistributedQueryResult{
|
||||
DistributedQueryCampaignID: 1,
|
||||
ResultJSON: json.RawMessage(`{"whoo":"wahh"}`),
|
||||
Rows: []map[string]string{{"whoo": "wahh"}},
|
||||
Host: kolide.Host{
|
||||
ID: 3,
|
||||
UpdatedAt: time.Now().UTC(),
|
||||
@ -139,7 +138,7 @@ func testQueryResultsStore(t *testing.T, store kolide.QueryResultStore) {
|
||||
},
|
||||
kolide.DistributedQueryResult{
|
||||
DistributedQueryCampaignID: 1,
|
||||
ResultJSON: json.RawMessage(`{"bing":"fds"}`),
|
||||
Rows: []map[string]string{{"bing": "fds"}},
|
||||
Host: kolide.Host{
|
||||
ID: 4,
|
||||
UpdatedAt: time.Now().UTC(),
|
||||
@ -157,7 +156,7 @@ func testQueryResultsStore(t *testing.T, store kolide.QueryResultStore) {
|
||||
expected2 := []kolide.DistributedQueryResult{
|
||||
kolide.DistributedQueryResult{
|
||||
DistributedQueryCampaignID: 2,
|
||||
ResultJSON: json.RawMessage(`{"tim":"tom"}`),
|
||||
Rows: []map[string]string{{"tim": "tom"}},
|
||||
Host: kolide.Host{
|
||||
ID: 1,
|
||||
UpdatedAt: time.Now().UTC(),
|
||||
@ -166,7 +165,7 @@ func testQueryResultsStore(t *testing.T, store kolide.QueryResultStore) {
|
||||
},
|
||||
kolide.DistributedQueryResult{
|
||||
DistributedQueryCampaignID: 2,
|
||||
ResultJSON: json.RawMessage(`{"slim":"slam"}`),
|
||||
Rows: []map[string]string{{"slim": "slam"}},
|
||||
Host: kolide.Host{
|
||||
ID: 3,
|
||||
UpdatedAt: time.Now().UTC(),
|
||||
|
@ -186,7 +186,7 @@ func TestGetNodeKey(t *testing.T) {
|
||||
func TestAuthenticatedHost(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
require.Nil(t, err)
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
require.Nil(t, err)
|
||||
|
||||
endpoint := authenticatedHost(
|
||||
|
@ -15,7 +15,7 @@ func TestAPIRoutes(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
assert.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
|
@ -24,7 +24,7 @@ import (
|
||||
|
||||
func TestLogin(t *testing.T) {
|
||||
ds, _ := datastore.New("inmem", "")
|
||||
svc, _ := newTestService(ds)
|
||||
svc, _ := newTestService(ds, nil)
|
||||
users := createTestUsers(t, ds)
|
||||
logger := kitlog.NewLogfmtLogger(os.Stdout)
|
||||
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
)
|
||||
|
||||
// NewService creates a new service from the config struct
|
||||
func NewService(ds kolide.Datastore, logger kitlog.Logger, kolideConfig config.KolideConfig, mailService kolide.MailService, c clock.Clock) (kolide.Service, error) {
|
||||
func NewService(ds kolide.Datastore, resultStore kolide.QueryResultStore, logger kitlog.Logger, kolideConfig config.KolideConfig, mailService kolide.MailService, c clock.Clock) (kolide.Service, error) {
|
||||
var svc kolide.Service
|
||||
|
||||
logFile := func(path string) io.Writer {
|
||||
@ -26,10 +26,11 @@ func NewService(ds kolide.Datastore, logger kitlog.Logger, kolideConfig config.K
|
||||
}
|
||||
|
||||
svc = service{
|
||||
ds: ds,
|
||||
logger: logger,
|
||||
config: kolideConfig,
|
||||
clock: c,
|
||||
ds: ds,
|
||||
resultStore: resultStore,
|
||||
logger: logger,
|
||||
config: kolideConfig,
|
||||
clock: c,
|
||||
|
||||
osqueryStatusLogWriter: logFile(kolideConfig.Osquery.StatusLogFile),
|
||||
osqueryResultLogWriter: logFile(kolideConfig.Osquery.ResultLogFile),
|
||||
@ -40,10 +41,11 @@ func NewService(ds kolide.Datastore, logger kitlog.Logger, kolideConfig config.K
|
||||
}
|
||||
|
||||
type service struct {
|
||||
ds kolide.Datastore
|
||||
logger kitlog.Logger
|
||||
config config.KolideConfig
|
||||
clock clock.Clock
|
||||
ds kolide.Datastore
|
||||
resultStore kolide.QueryResultStore
|
||||
logger kitlog.Logger
|
||||
config config.KolideConfig
|
||||
clock clock.Clock
|
||||
|
||||
osqueryStatusLogWriter io.Writer
|
||||
osqueryResultLogWriter io.Writer
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
func TestCreateAppConfig(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
require.Nil(t, err)
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
require.Nil(t, err)
|
||||
var appConfigTests = []struct {
|
||||
configPayload kolide.AppConfigPayload
|
||||
|
@ -13,7 +13,7 @@ func TestListHosts(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
assert.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
@ -36,7 +36,7 @@ func TestGetHost(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
assert.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
@ -57,7 +57,7 @@ func TestDeleteHost(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
assert.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
|
@ -13,7 +13,7 @@ func TestListLabels(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
assert.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
@ -38,7 +38,7 @@ func TestGetLabel(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
assert.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
@ -60,7 +60,7 @@ func TestNewLabel(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
assert.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
@ -85,7 +85,7 @@ func TestDeleteLabel(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
assert.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
|
@ -158,6 +158,10 @@ const hostLabelQueryPrefix = "kolide_label_query_"
|
||||
// provided as a detail query.
|
||||
const hostDetailQueryPrefix = "kolide_detail_query_"
|
||||
|
||||
// hostDistributedQueryPrefix is appended before the query name when a query is
|
||||
// run from a distributed query campaign
|
||||
const hostDistributedQueryPrefix = "kolide_distributed_query_"
|
||||
|
||||
// detailQueries defines the detail queries that should be run on the host, as
|
||||
// well as how the results of those queries should be ingested into the
|
||||
// kolide.Host data model. This map should not be modified at runtime.
|
||||
@ -295,7 +299,14 @@ func (svc service) GetDistributedQueries(ctx context.Context) (map[string]string
|
||||
queries[hostLabelQueryPrefix+name] = query
|
||||
}
|
||||
|
||||
// TODO: retrieve the active distributed queries for this host
|
||||
distributedQueries, err := svc.ds.DistributedQueriesForHost(&host)
|
||||
if err != nil {
|
||||
return nil, osqueryError{message: "retrieving query campaigns: " + err.Error()}
|
||||
}
|
||||
|
||||
for id, query := range distributedQueries {
|
||||
queries[hostDistributedQueryPrefix+strconv.Itoa(int(id))] = query
|
||||
}
|
||||
|
||||
return queries, nil
|
||||
}
|
||||
@ -327,6 +338,43 @@ func (svc service) ingestLabelQuery(host kolide.Host, query string, rows []map[s
|
||||
return nil
|
||||
}
|
||||
|
||||
// ingestDistributedQuery takes the results of a distributed query and modifies the
|
||||
// provided kolide.Host appropriately.
|
||||
func (svc service) ingestDistributedQuery(host kolide.Host, name string, rows []map[string]string) error {
|
||||
trimmedQuery := strings.TrimPrefix(name, hostDistributedQueryPrefix)
|
||||
|
||||
campaignID, err := strconv.Atoi(trimmedQuery)
|
||||
if err != nil {
|
||||
return osqueryError{message: "unable to parse campaign ID: " + trimmedQuery}
|
||||
}
|
||||
|
||||
// Write the results to the pubsub store
|
||||
res := kolide.DistributedQueryResult{
|
||||
DistributedQueryCampaignID: uint(campaignID),
|
||||
Host: host,
|
||||
Rows: rows,
|
||||
}
|
||||
|
||||
err = svc.resultStore.WriteResult(res)
|
||||
if err != nil {
|
||||
return osqueryError{message: "writing results: " + err.Error()}
|
||||
}
|
||||
|
||||
// Record execution of the query
|
||||
exec := kolide.DistributedQueryExecution{
|
||||
HostID: host.ID,
|
||||
DistributedQueryCampaignID: uint(campaignID),
|
||||
Status: kolide.ExecutionSucceeded,
|
||||
}
|
||||
|
||||
_, err = svc.ds.NewDistributedQueryExecution(exec)
|
||||
if err != nil {
|
||||
return osqueryError{message: "recording execution: " + err.Error()}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (svc service) SubmitDistributedQueryResults(ctx context.Context, results kolide.OsqueryDistributedQueryResults) error {
|
||||
host, ok := hostctx.FromContext(ctx)
|
||||
if !ok {
|
||||
@ -347,8 +395,11 @@ func (svc service) SubmitDistributedQueryResults(ctx context.Context, results ko
|
||||
case strings.HasPrefix(query, hostLabelQueryPrefix):
|
||||
err = svc.ingestLabelQuery(host, query, rows, labelResults)
|
||||
|
||||
case strings.HasPrefix(query, hostDistributedQueryPrefix):
|
||||
err = svc.ingestDistributedQuery(host, query, rows)
|
||||
|
||||
default:
|
||||
// TODO ingest regular distributed query results
|
||||
err = osqueryError{message: "unknown query prefix: " + query}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
@ -4,7 +4,9 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -14,6 +16,7 @@ import (
|
||||
hostctx "github.com/kolide/kolide-ose/server/contexts/host"
|
||||
"github.com/kolide/kolide-ose/server/datastore"
|
||||
"github.com/kolide/kolide-ose/server/kolide"
|
||||
"github.com/kolide/kolide-ose/server/pubsub"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@ -22,7 +25,7 @@ func TestEnrollAgent(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
assert.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
@ -44,7 +47,7 @@ func TestEnrollAgentIncorrectEnrollSecret(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
assert.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
@ -68,7 +71,7 @@ func TestSubmitStatusLogs(t *testing.T) {
|
||||
|
||||
mockClock := clock.NewMockClock()
|
||||
|
||||
svc, err := newTestServiceWithClock(ds, mockClock)
|
||||
svc, err := newTestServiceWithClock(ds, nil, mockClock)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
@ -140,7 +143,7 @@ func TestSubmitResultLogs(t *testing.T) {
|
||||
|
||||
mockClock := clock.NewMockClock()
|
||||
|
||||
svc, err := newTestServiceWithClock(ds, mockClock)
|
||||
svc, err := newTestServiceWithClock(ds, nil, mockClock)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
@ -241,7 +244,7 @@ func TestLabelQueries(t *testing.T) {
|
||||
|
||||
mockClock := clock.NewMockClock()
|
||||
|
||||
svc, err := newTestServiceWithClock(ds, mockClock)
|
||||
svc, err := newTestServiceWithClock(ds, nil, mockClock)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
@ -368,7 +371,7 @@ func TestGetClientConfig(t *testing.T) {
|
||||
|
||||
mockClock := clock.NewMockClock()
|
||||
|
||||
svc, err := newTestServiceWithClock(ds, mockClock)
|
||||
svc, err := newTestServiceWithClock(ds, nil, mockClock)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
@ -449,7 +452,7 @@ func TestDetailQueries(t *testing.T) {
|
||||
|
||||
mockClock := clock.NewMockClock()
|
||||
|
||||
svc, err := newTestServiceWithClock(ds, mockClock)
|
||||
svc, err := newTestServiceWithClock(ds, nil, mockClock)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
@ -584,3 +587,140 @@ func TestDetailQueries(t *testing.T) {
|
||||
assert.Nil(t, err)
|
||||
assert.Len(t, queries, len(detailQueries))
|
||||
}
|
||||
|
||||
func TestDistributedQueries(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
require.Nil(t, err)
|
||||
|
||||
mockClock := clock.NewMockClock()
|
||||
|
||||
rs := pubsub.NewInmemQueryResults()
|
||||
|
||||
svc, err := newTestServiceWithClock(ds, rs, mockClock)
|
||||
require.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
nodeKey, err := svc.EnrollAgent(ctx, "", "host123")
|
||||
require.Nil(t, err)
|
||||
|
||||
host, err := ds.AuthenticateHost(nodeKey)
|
||||
require.Nil(t, err)
|
||||
|
||||
ctx = hostctx.NewContext(ctx, *host)
|
||||
|
||||
// Create label
|
||||
n := "foo"
|
||||
q := "select * from foo;"
|
||||
label, err := svc.NewLabel(ctx, kolide.LabelPayload{
|
||||
Name: &n,
|
||||
Query: &q,
|
||||
})
|
||||
require.Nil(t, err)
|
||||
labelId := strconv.Itoa(int(label.ID))
|
||||
|
||||
// Record match with label
|
||||
err = ds.RecordLabelQueryExecutions(host, map[string]bool{labelId: true}, mockClock.Now())
|
||||
require.Nil(t, err)
|
||||
|
||||
// Create query
|
||||
n = "time"
|
||||
q = "select year, month, day, hour, minutes, seconds from time"
|
||||
query, err := svc.NewQuery(ctx, kolide.QueryPayload{
|
||||
Name: &n,
|
||||
Query: &q,
|
||||
})
|
||||
require.Nil(t, err)
|
||||
|
||||
// Create query campaign
|
||||
c1 := kolide.DistributedQueryCampaign{
|
||||
QueryID: query.ID,
|
||||
Status: kolide.QueryRunning,
|
||||
}
|
||||
// TODO use service method
|
||||
c1, err = ds.NewDistributedQueryCampaign(c1)
|
||||
require.Nil(t, err)
|
||||
|
||||
// Add a target to the campaign (targeting the matching label)
|
||||
target := kolide.DistributedQueryCampaignTarget{
|
||||
Type: kolide.TargetLabel,
|
||||
DistributedQueryCampaignID: c1.ID,
|
||||
TargetID: label.ID,
|
||||
}
|
||||
// TODO use service method
|
||||
target, err = ds.NewDistributedQueryCampaignTarget(target)
|
||||
require.Nil(t, err)
|
||||
|
||||
queryKey := fmt.Sprintf("%s%d", hostDistributedQueryPrefix, c1.ID)
|
||||
|
||||
// Now we should get the active distributed query
|
||||
queries, err := svc.GetDistributedQueries(ctx)
|
||||
require.Nil(t, err)
|
||||
assert.Len(t, queries, len(detailQueries)+1)
|
||||
assert.Equal(t, q, queries[queryKey])
|
||||
|
||||
expectedRows := []map[string]string{
|
||||
{
|
||||
"year": "2016",
|
||||
"month": "11",
|
||||
"day": "11",
|
||||
"hour": "6",
|
||||
"minutes": "12",
|
||||
"seconds": "10",
|
||||
},
|
||||
}
|
||||
results := map[string][]map[string]string{
|
||||
queryKey: expectedRows,
|
||||
}
|
||||
|
||||
// Submit results (should error because no one is listening)
|
||||
err = svc.SubmitDistributedQueryResults(ctx, results)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
// TODO use service method
|
||||
readChan, err := rs.ReadChannel(ctx, c1)
|
||||
require.Nil(t, err)
|
||||
|
||||
// We need to listen for the result in a separate thread to prevent the
|
||||
// write to the result channel from failing
|
||||
var waitSetup, waitComplete sync.WaitGroup
|
||||
waitSetup.Add(1)
|
||||
waitComplete.Add(1)
|
||||
go func() {
|
||||
waitSetup.Done()
|
||||
select {
|
||||
case val := <-readChan:
|
||||
if res, ok := val.(kolide.DistributedQueryResult); ok {
|
||||
assert.Equal(t, c1.ID, res.DistributedQueryCampaignID)
|
||||
assert.Equal(t, expectedRows, res.Rows)
|
||||
assert.Equal(t, *host, res.Host)
|
||||
} else {
|
||||
t.Error("Wrong result type")
|
||||
}
|
||||
assert.NotNil(t, val)
|
||||
|
||||
case <-time.After(1 * time.Second):
|
||||
t.Error("No result received")
|
||||
}
|
||||
waitComplete.Done()
|
||||
}()
|
||||
|
||||
waitSetup.Wait()
|
||||
// Sleep a short time to ensure that the above goroutine is blocking on
|
||||
// the channel read (the waitSetup.Wait() is not necessarily sufficient
|
||||
// if there is a context switch immediately after waitSetup.Done() is
|
||||
// called). This should be a small price to pay to prevent flakiness in
|
||||
// this test.
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
err = svc.SubmitDistributedQueryResults(ctx, results)
|
||||
require.Nil(t, err)
|
||||
|
||||
// Now the distributed query should be completed and not returned
|
||||
queries, err = svc.GetDistributedQueries(ctx)
|
||||
require.Nil(t, err)
|
||||
assert.Len(t, queries, len(detailQueries))
|
||||
assert.NotContains(t, queries, queryKey)
|
||||
|
||||
waitComplete.Wait()
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ func TestListPacks(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
assert.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
@ -36,7 +36,7 @@ func TestGetPack(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
assert.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
@ -58,7 +58,7 @@ func TestNewPack(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
assert.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
@ -79,7 +79,7 @@ func TestModifyPack(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
assert.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
@ -105,7 +105,7 @@ func TestDeletePack(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
assert.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
@ -130,7 +130,7 @@ func TestAddQueryToPack(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
assert.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
@ -166,7 +166,7 @@ func TestGetQueriesInPack(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
assert.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
@ -198,7 +198,7 @@ func TestRemoveQueryFromPack(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
assert.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
|
@ -13,7 +13,7 @@ func TestListQueries(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
assert.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
@ -37,7 +37,7 @@ func TestGetQuery(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
assert.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
@ -60,7 +60,7 @@ func TestNewQuery(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
assert.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
@ -83,7 +83,7 @@ func TestModifyQuery(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
assert.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
@ -110,7 +110,7 @@ func TestDeleteQuery(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
assert.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
|
@ -16,7 +16,7 @@ const bcryptCost = 6
|
||||
func TestAuthenticate(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
require.Nil(t, err)
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
require.Nil(t, err)
|
||||
users := createTestUsers(t, ds)
|
||||
|
||||
|
@ -16,7 +16,7 @@ func TestSearchTargets(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
require.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
require.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
@ -47,7 +47,7 @@ func TestCountHostsInTargets(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
require.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
require.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
@ -143,7 +143,7 @@ func TestSearchWithOmit(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
require.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
require.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
@ -195,7 +195,7 @@ func TestSearchHostsInLabels(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
require.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
require.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
@ -248,7 +248,7 @@ func TestSearchResultsLimit(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
require.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
require.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
|
@ -19,7 +19,7 @@ func TestAuthenticatedUser(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
assert.Nil(t, err)
|
||||
createTestUsers(t, ds)
|
||||
svc, err := newTestService(ds)
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
admin1, err := ds.User("admin1")
|
||||
assert.Nil(t, err)
|
||||
@ -113,7 +113,7 @@ func TestRequestPasswordReset(t *testing.T) {
|
||||
|
||||
func TestCreateUser(t *testing.T) {
|
||||
ds, _ := datastore.New("inmem", "")
|
||||
svc, _ := newTestService(ds)
|
||||
svc, _ := newTestService(ds, nil)
|
||||
invites := setupInvites(t, ds, []string{"admin2@example.com"})
|
||||
ctx := context.Background()
|
||||
|
||||
@ -236,7 +236,7 @@ func setupInvites(t *testing.T, ds kolide.Datastore, emails []string) map[string
|
||||
|
||||
func TestChangeUserPassword(t *testing.T) {
|
||||
ds, _ := datastore.New("inmem", "")
|
||||
svc, _ := newTestService(ds)
|
||||
svc, _ := newTestService(ds, nil)
|
||||
createTestUsers(t, ds)
|
||||
var passwordChangeTests = []struct {
|
||||
token string
|
||||
|
@ -10,12 +10,12 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func newTestService(ds kolide.Datastore) (kolide.Service, error) {
|
||||
return NewService(ds, kitlog.NewNopLogger(), config.TestConfig(), nil, clock.C)
|
||||
func newTestService(ds kolide.Datastore, rs kolide.QueryResultStore) (kolide.Service, error) {
|
||||
return NewService(ds, rs, kitlog.NewNopLogger(), config.TestConfig(), nil, clock.C)
|
||||
}
|
||||
|
||||
func newTestServiceWithClock(ds kolide.Datastore, c clock.Clock) (kolide.Service, error) {
|
||||
return NewService(ds, kitlog.NewNopLogger(), config.TestConfig(), nil, c)
|
||||
func newTestServiceWithClock(ds kolide.Datastore, rs kolide.QueryResultStore, c clock.Clock) (kolide.Service, error) {
|
||||
return NewService(ds, rs, kitlog.NewNopLogger(), config.TestConfig(), nil, c)
|
||||
}
|
||||
|
||||
func createTestUsers(t *testing.T, ds kolide.Datastore) map[string]kolide.User {
|
||||
|
@ -2,13 +2,13 @@
|
||||
"options": {
|
||||
"disable_distributed": "false",
|
||||
"distributed_plugin": "tls",
|
||||
"distributed_interval": 30,
|
||||
"distributed_interval": 10,
|
||||
"distributed_tls_max_attempts": 3,
|
||||
"distributed_tls_read_endpoint": "/api/v1/osquery/distributed/read",
|
||||
"distributed_tls_write_endpoint": "/api/v1/osquery/distributed/write",
|
||||
"logger_plugin": "tls",
|
||||
"logger_tls_endpoint": "/api/v1/osquery/log",
|
||||
"logger_tls_period": 5
|
||||
"logger_tls_period": 60
|
||||
},
|
||||
|
||||
"schedule": {
|
||||
@ -17,7 +17,7 @@
|
||||
// The exact query to run.
|
||||
"query": "SELECT hostname, cpu_brand, physical_memory FROM system_info;",
|
||||
// The interval in seconds to run this query, not an exact interval.
|
||||
"interval": 5
|
||||
"interval": 60
|
||||
}
|
||||
},
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user