Prevent empty logging_type when creating and editing queries (#14575)

#14551

- ~[ ] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.~
- ~[ ] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)~
- ~[ ] Documented any permissions changes (docs/Using
Fleet/manage-access.md)~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [x] Manual QA for all new/changed functionality
  - ~For Orbit and Fleet Desktop changes:~
- ~[ ] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.~
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
This commit is contained in:
Lucas Manuel Rodriguez 2023-10-16 19:33:39 -03:00 committed by GitHub
parent 37cacac1d8
commit e58e72fb77
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 420 additions and 125 deletions

View File

@ -0,0 +1,27 @@
package tables
import (
"database/sql"
"fmt"
"github.com/fleetdm/fleet/v4/server/fleet"
)
func init() {
MigrationClient.AddMigration(Up_20231016091915, Down_20231016091915)
}
func Up_20231016091915(tx *sql.Tx) error {
_, err := tx.Exec(`
UPDATE queries SET logging_type = ? WHERE logging_type = '';
`, fleet.LoggingSnapshot)
if err != nil {
return fmt.Errorf("failed to update queries logging_type: %w", err)
}
return nil
}
func Down_20231016091915(tx *sql.Tx) error {
return nil
}

View File

@ -0,0 +1,39 @@
package tables
import (
"testing"
"github.com/fleetdm/fleet/v4/server/fleet"
"github.com/stretchr/testify/require"
)
func TestUp_20231016091915(t *testing.T) {
db := applyUpToPrev(t)
insertStmt := `INSERT INTO queries (
name, description, query, logging_type
) VALUES (?, ?, ?, ?), (?, ?, ?, ?), (?, ?, ?, ?)`
_, err := db.Exec(insertStmt,
"foobar", "logging_type set to something else", "SELECT 1;", fleet.LoggingDifferential,
"zoobar", "logging_type unset", "SELECT 2;", "",
"boobar", "logging_type set to snapshot already", "SELECT 3;", fleet.LoggingSnapshot,
)
require.NoError(t, err)
// Apply current migration.
applyNext(t, db)
var foobarLogging string
err = db.Get(&foobarLogging, "SELECT logging_type FROM queries WHERE name = ?", "foobar")
require.NoError(t, err)
require.Equal(t, fleet.LoggingDifferential, foobarLogging)
var zoobarLogging string
err = db.Get(&zoobarLogging, "SELECT logging_type FROM queries WHERE name = ?", "zoobar")
require.NoError(t, err)
require.Equal(t, fleet.LoggingSnapshot, zoobarLogging)
var boobarLogging string
err = db.Get(&boobarLogging, "SELECT logging_type FROM queries WHERE name = ?", "boobar")
require.NoError(t, err)
require.Equal(t, fleet.LoggingSnapshot, boobarLogging)
}

View File

@ -141,12 +141,12 @@ func testPacksList(t *testing.T, ds *Datastore) {
func setupPackSpecsTest(t *testing.T, ds fleet.Datastore) []*fleet.PackSpec {
zwass := test.NewUser(t, ds, "Zach", "zwass@example.com", true)
queries := []*fleet.Query{
{Name: "foo", Description: "get the foos", Query: "select * from foo"},
{Name: "bar", Description: "do some bars", Query: "select baz from bar"},
{Name: "foo", Description: "get the foos", Query: "select * from foo", Logging: fleet.LoggingSnapshot},
{Name: "bar", Description: "do some bars", Query: "select baz from bar", Logging: fleet.LoggingSnapshot},
}
// Zach creates some queries
err := ds.ApplyQueries(context.Background(), zwass.ID, queries, nil)
require.Nil(t, err)
require.NoError(t, err)
labels := []*fleet.LabelSpec{
{

View File

@ -69,6 +69,7 @@ func testPoliciesNewGlobalPolicyLegacy(t *testing.T, ds *Datastore) {
Description: "query1 desc",
Query: "select 1;",
Saved: true,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
p, err := ds.NewGlobalPolicy(context.Background(), &user1.ID, fleet.PolicyPayload{
@ -87,6 +88,7 @@ func testPoliciesNewGlobalPolicyLegacy(t *testing.T, ds *Datastore) {
Description: "query2 desc",
Query: "select 42;",
Saved: true,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
_, err = ds.NewGlobalPolicy(context.Background(), &user1.ID, fleet.PolicyPayload{
@ -233,6 +235,7 @@ func testPoliciesMembershipView(deferred bool, t *testing.T, ds *Datastore) {
Description: "query1 desc",
Query: "select 1;",
Saved: true,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
p, err := ds.NewGlobalPolicy(ctx, &user1.ID, fleet.PolicyPayload{
@ -251,6 +254,7 @@ func testPoliciesMembershipView(deferred bool, t *testing.T, ds *Datastore) {
Description: "query2 desc",
Query: "select 42;",
Saved: true,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
p2, err := ds.NewGlobalPolicy(ctx, &user1.ID, fleet.PolicyPayload{
@ -390,6 +394,7 @@ func testTeamPolicyLegacy(t *testing.T, ds *Datastore) {
Description: "query1 desc",
Query: "select 1;",
Saved: true,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
@ -401,6 +406,7 @@ func testTeamPolicyLegacy(t *testing.T, ds *Datastore) {
Description: "query2 desc",
Query: "select 1;",
Saved: true,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
@ -918,6 +924,7 @@ func testPolicyQueriesForHost(t *testing.T, ds *Datastore) {
Description: "query1 desc",
Query: "select 1;",
Saved: true,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
gp, err := ds.NewGlobalPolicy(context.Background(), &user1.ID, fleet.PolicyPayload{
@ -931,6 +938,7 @@ func testPolicyQueriesForHost(t *testing.T, ds *Datastore) {
Description: "query2 desc",
Query: "select 42;",
Saved: true,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
tp, err := ds.NewTeamPolicy(context.Background(), team1.ID, &user1.ID, fleet.PolicyPayload{
@ -1066,6 +1074,7 @@ func testTeamPolicyTransfer(t *testing.T, ds *Datastore) {
Description: "query1 desc",
Query: "select 1;",
Saved: true,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
team1Policy, err := ds.NewTeamPolicy(ctx, team1.ID, &user1.ID, fleet.PolicyPayload{
@ -1078,6 +1087,7 @@ func testTeamPolicyTransfer(t *testing.T, ds *Datastore) {
Description: "query2 desc",
Query: "select 2;",
Saved: true,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
globalPolicy, err := ds.NewGlobalPolicy(ctx, &user1.ID, fleet.PolicyPayload{

View File

@ -175,6 +175,9 @@ func (ds *Datastore) NewQuery(
query *fleet.Query,
opts ...fleet.OptionalArg,
) (*fleet.Query, error) {
if err := query.Verify(); err != nil {
return nil, ctxerr.Wrap(ctx, err)
}
sqlStatement := `
INSERT INTO queries (
name,
@ -226,6 +229,10 @@ func (ds *Datastore) NewQuery(
// SaveQuery saves changes to a Query.
func (ds *Datastore) SaveQuery(ctx context.Context, q *fleet.Query, shouldDiscardResults bool) (err error) {
if err := q.Verify(); err != nil {
return ctxerr.Wrap(ctx, err)
}
tx, err := ds.writer(ctx).BeginTxx(ctx, nil)
if err != nil {
return ctxerr.Wrap(ctx, err, "begin SaveQuery transaction")
@ -549,7 +556,15 @@ func (ds *Datastore) ListScheduledQueriesForAgents(ctx context.Context, teamID *
q.discard_data
FROM queries q
WHERE q.saved = true
AND (q.schedule_interval > 0 AND %s AND (q.automations_enabled OR (NOT q.discard_data AND NOT ?)))
AND (
q.schedule_interval > 0 AND
%s AND
(
q.automations_enabled
OR
(NOT q.discard_data AND NOT ? AND q.logging_type = ?)
)
)
`
args := []interface{}{}
@ -559,7 +574,7 @@ func (ds *Datastore) ListScheduledQueriesForAgents(ctx context.Context, teamID *
teamSQL = " team_id = ?"
}
sqlStmt = fmt.Sprintf(sqlStmt, teamSQL)
args = append(args, queryReportsDisabled)
args = append(args, queryReportsDisabled, fleet.LoggingSnapshot)
results := []*fleet.Query{}
if err := sqlx.SelectContext(ctx, ds.reader(ctx), &results, sqlStmt, args...); err != nil {

View File

@ -58,13 +58,14 @@ func testQueriesApply(t *testing.T, ds *Datastore) {
Platform: "darwin",
MinOsqueryVersion: "5.2.1",
AutomationsEnabled: true,
Logging: "differential",
Logging: fleet.LoggingDifferential,
DiscardData: true,
},
{
Name: "bar",
Description: "do some bars",
Query: "select baz from bar",
Logging: fleet.LoggingSnapshot,
DiscardData: true,
},
}
@ -114,6 +115,7 @@ func testQueriesApply(t *testing.T, ds *Datastore) {
Description: "Look out!",
Query: "select * from time",
DiscardData: true,
Logging: fleet.LoggingDifferential,
},
)
err = ds.ApplyQueries(context.Background(), zwass.ID, []*fleet.Query{expectedQueries[2]}, nil)
@ -150,7 +152,7 @@ func testQueriesApply(t *testing.T, ds *Datastore) {
Platform: "not valid",
MinOsqueryVersion: "5.2.1",
AutomationsEnabled: true,
Logging: "differential",
Logging: fleet.LoggingDifferential,
},
}
err = ds.ApplyQueries(context.Background(), zwass.ID, invalidQueries, nil)
@ -164,6 +166,7 @@ func testQueriesDelete(t *testing.T, ds *Datastore) {
Name: "foo",
Query: "bar",
AuthorID: &user.ID,
Logging: fleet.LoggingDifferential,
}
query, err := ds.NewQuery(context.Background(), query)
require.NoError(t, err)
@ -259,6 +262,7 @@ func testQueriesSave(t *testing.T, ds *Datastore) {
Name: "foo",
Query: "bar",
AuthorID: &user.ID,
Logging: fleet.LoggingSnapshot,
}
query, err := ds.NewQuery(context.Background(), query)
require.NoError(t, err)
@ -275,10 +279,10 @@ func testQueriesSave(t *testing.T, ds *Datastore) {
query.ObserverCanRun = true
query.TeamID = &team.ID
query.Interval = 10
query.Platform = "macos"
query.Platform = "darwin"
query.MinOsqueryVersion = "5.2.1"
query.AutomationsEnabled = true
query.Logging = "differential"
query.Logging = fleet.LoggingDifferential
query.DiscardData = true
err = ds.SaveQuery(context.Background(), query, true)
@ -305,6 +309,7 @@ func testQueriesList(t *testing.T, ds *Datastore) {
Saved: true,
AuthorID: &user.ID,
DiscardData: true,
Logging: fleet.LoggingSnapshot,
})
require.Nil(t, err)
}
@ -315,6 +320,7 @@ func testQueriesList(t *testing.T, ds *Datastore) {
Query: "select * from time",
Saved: false,
AuthorID: &user.ID,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
@ -354,8 +360,8 @@ func testQueriesList(t *testing.T, ds *Datastore) {
func testQueriesLoadPacksForQueries(t *testing.T, ds *Datastore) {
zwass := test.NewUser(t, ds, "Zach", "zwass@fleet.co", true)
queries := []*fleet.Query{
{Name: "q1", Query: "select * from time"},
{Name: "q2", Query: "select * from osquery_info"},
{Name: "q1", Query: "select * from time", Logging: fleet.LoggingSnapshot},
{Name: "q2", Query: "select * from osquery_info", Logging: fleet.LoggingDifferential},
}
err := ds.ApplyQueries(context.Background(), zwass.ID, queries, nil)
require.NoError(t, err)
@ -483,12 +489,14 @@ func testQueriesDuplicateNew(t *testing.T, ds *Datastore) {
Name: "foo",
Query: "select * from time;",
AuthorID: &user.ID,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
require.NotZero(t, globalQ1.ID)
_, err = ds.NewQuery(context.Background(), &fleet.Query{
Name: "foo",
Query: "select * from osquery_info;",
Name: "foo",
Query: "select * from osquery_info;",
Logging: fleet.LoggingSnapshot,
})
require.Contains(t, err.Error(), "already exists")
@ -500,31 +508,35 @@ func testQueriesDuplicateNew(t *testing.T, ds *Datastore) {
require.NoError(t, err)
_, err = ds.NewQuery(context.Background(), &fleet.Query{
Name: "foo",
Query: "select * from osquery_info;",
TeamID: &team.ID,
Name: "foo",
Query: "select * from osquery_info;",
TeamID: &team.ID,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
_, err = ds.NewQuery(context.Background(), &fleet.Query{
Name: "foo",
Query: "select * from osquery_info;",
TeamID: &team.ID,
Name: "foo",
Query: "select * from osquery_info;",
TeamID: &team.ID,
Logging: fleet.LoggingSnapshot,
})
require.Contains(t, err.Error(), "already exists")
}
func testQueriesListFiltersObservers(t *testing.T, ds *Datastore) {
_, err := ds.NewQuery(context.Background(), &fleet.Query{
Name: "query1",
Query: "select 1;",
Saved: true,
Name: "query1",
Query: "select 1;",
Saved: true,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
_, err = ds.NewQuery(context.Background(), &fleet.Query{
Name: "query2",
Query: "select 1;",
Saved: true,
Name: "query2",
Query: "select 1;",
Saved: true,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
query3, err := ds.NewQuery(context.Background(), &fleet.Query{
@ -532,6 +544,7 @@ func testQueriesListFiltersObservers(t *testing.T, ds *Datastore) {
Query: "select 1;",
Saved: true,
ObserverCanRun: true,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
@ -553,6 +566,7 @@ func testObserverCanRunQuery(t *testing.T, ds *Datastore) {
Name: "canRunTrue",
Query: "select 1;",
ObserverCanRun: true,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
@ -560,12 +574,14 @@ func testObserverCanRunQuery(t *testing.T, ds *Datastore) {
Name: "canRunFalse",
Query: "select 1;",
ObserverCanRun: false,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
_, err = ds.NewQuery(context.Background(), &fleet.Query{
Name: "canRunOmitted",
Query: "select 1;",
Name: "canRunOmitted",
Query: "select 1;",
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
@ -581,21 +597,24 @@ func testObserverCanRunQuery(t *testing.T, ds *Datastore) {
func testListQueriesFiltersByTeamID(t *testing.T, ds *Datastore) {
globalQ1, err := ds.NewQuery(context.Background(), &fleet.Query{
Name: "query1",
Query: "select 1;",
Saved: true,
Name: "query1",
Query: "select 1;",
Saved: true,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
globalQ2, err := ds.NewQuery(context.Background(), &fleet.Query{
Name: "query2",
Query: "select 1;",
Saved: true,
Name: "query2",
Query: "select 1;",
Saved: true,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
globalQ3, err := ds.NewQuery(context.Background(), &fleet.Query{
Name: "query3",
Query: "select 1;",
Saved: true,
Name: "query3",
Query: "select 1;",
Saved: true,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
@ -610,24 +629,27 @@ func testListQueriesFiltersByTeamID(t *testing.T, ds *Datastore) {
require.NoError(t, err)
teamQ1, err := ds.NewQuery(context.Background(), &fleet.Query{
Name: "query1",
Query: "select 1;",
Saved: true,
TeamID: &team.ID,
Name: "query1",
Query: "select 1;",
Saved: true,
TeamID: &team.ID,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
teamQ2, err := ds.NewQuery(context.Background(), &fleet.Query{
Name: "query2",
Query: "select 1;",
Saved: true,
TeamID: &team.ID,
Name: "query2",
Query: "select 1;",
Saved: true,
TeamID: &team.ID,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
teamQ3, err := ds.NewQuery(context.Background(), &fleet.Query{
Name: "query3",
Query: "select 1;",
Saved: true,
TeamID: &team.ID,
Name: "query3",
Query: "select 1;",
Saved: true,
TeamID: &team.ID,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
@ -647,6 +669,7 @@ func testListQueriesFiltersByIsScheduled(t *testing.T, ds *Datastore) {
Query: "select 1;",
Saved: true,
Interval: 0,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
q2, err := ds.NewQuery(context.Background(), &fleet.Query{
@ -655,6 +678,7 @@ func testListQueriesFiltersByIsScheduled(t *testing.T, ds *Datastore) {
Saved: true,
Interval: 10,
AutomationsEnabled: false,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
q3, err := ds.NewQuery(context.Background(), &fleet.Query{
@ -663,6 +687,7 @@ func testListQueriesFiltersByIsScheduled(t *testing.T, ds *Datastore) {
Saved: true,
Interval: 20,
AutomationsEnabled: true,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
@ -718,10 +743,11 @@ func testListScheduledQueriesForAgents(t *testing.T, ds *Datastore) {
AutomationsEnabled: false,
TeamID: teamID,
DiscardData: true,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
// Interval=0, AutomationsEnabled=0, DiscardData=0
// Interval=0, AutomationsEnabled=0, DiscardData=0, Snapshot=0
_, err := ds.NewQuery(context.Background(), &fleet.Query{
Name: fmt.Sprintf("%s query2", teamIDStr),
Query: "select 1;",
@ -730,90 +756,202 @@ func testListScheduledQueriesForAgents(t *testing.T, ds *Datastore) {
TeamID: teamID,
AutomationsEnabled: false,
DiscardData: false,
Logging: fleet.LoggingDifferential,
})
require.NoError(t, err)
// Interval=0, AutomationsEnabled=0, DiscardData=1
// Interval=0, AutomationsEnabled=0, DiscardData=0, Snapshot=1
_, err = ds.NewQuery(context.Background(), &fleet.Query{
Name: fmt.Sprintf("%s query3", teamIDStr),
Query: "select 1;",
Saved: true,
Interval: 0,
AutomationsEnabled: false,
TeamID: teamID,
DiscardData: true,
AutomationsEnabled: false,
DiscardData: false,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
// Interval=0, AutomationsEnabled=1, DiscardData=0
// Interval=0, AutomationsEnabled=0, DiscardData=1, Snapshot=0
_, err = ds.NewQuery(context.Background(), &fleet.Query{
Name: fmt.Sprintf("%s query4", teamIDStr),
Query: "select 1;",
Saved: true,
Interval: 0,
AutomationsEnabled: true,
AutomationsEnabled: false,
TeamID: teamID,
DiscardData: false,
DiscardData: true,
Logging: fleet.LoggingDifferential,
})
require.NoError(t, err)
// Interval=0, AutomationsEnabled=1, DiscardData=1
// Interval=0, AutomationsEnabled=0, DiscardData=1, Snapshot=1
_, err = ds.NewQuery(context.Background(), &fleet.Query{
Name: fmt.Sprintf("%s query5", teamIDStr),
Query: "select 1;",
Saved: true,
Interval: 0,
AutomationsEnabled: false,
TeamID: teamID,
DiscardData: true,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
// Interval=0, AutomationsEnabled=1, DiscardData=0, Snapshot=0
_, err = ds.NewQuery(context.Background(), &fleet.Query{
Name: fmt.Sprintf("%s query6", teamIDStr),
Query: "select 1;",
Saved: true,
Interval: 0,
AutomationsEnabled: true,
TeamID: teamID,
DiscardData: false,
Logging: fleet.LoggingDifferential,
})
require.NoError(t, err)
// Interval=0, AutomationsEnabled=1, DiscardData=0, Snapshot=1
_, err = ds.NewQuery(context.Background(), &fleet.Query{
Name: fmt.Sprintf("%s query7", teamIDStr),
Query: "select 1;",
Saved: true,
Interval: 0,
AutomationsEnabled: true,
TeamID: teamID,
DiscardData: false,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
// Interval=0, AutomationsEnabled=1, DiscardData=1, Snapshot=0
_, err = ds.NewQuery(context.Background(), &fleet.Query{
Name: fmt.Sprintf("%s query8", teamIDStr),
Query: "select 1;",
Saved: true,
Interval: 0,
AutomationsEnabled: true,
TeamID: teamID,
DiscardData: true,
Logging: fleet.LoggingDifferential,
})
require.NoError(t, err)
// Interval=1, AutomationsEnabled=0, DiscardData=0
q6, err := ds.NewQuery(context.Background(), &fleet.Query{
Name: fmt.Sprintf("%s query6", teamIDStr),
Query: "select 1;",
Saved: true,
Interval: 10,
AutomationsEnabled: false,
TeamID: teamID,
DiscardData: false,
})
require.NoError(t, err)
// Interval=1, AutomationsEnabled=0, DiscardData=1
// Interval=0, AutomationsEnabled=1, DiscardData=1, Snapshot=1
_, err = ds.NewQuery(context.Background(), &fleet.Query{
Name: fmt.Sprintf("%s query7", teamIDStr),
Query: "select 1;",
Saved: true,
Interval: 10,
AutomationsEnabled: false,
TeamID: teamID,
DiscardData: true,
})
require.NoError(t, err)
// Interval=1, AutomationsEnabled=1, DiscardData=0
q8, err := ds.NewQuery(context.Background(), &fleet.Query{
Name: fmt.Sprintf("%s query8", teamIDStr),
Query: "select 1;",
Saved: true,
Interval: 10,
AutomationsEnabled: true,
TeamID: teamID,
DiscardData: false,
})
require.NoError(t, err)
// Interval=1, AutomationsEnabled=1, DiscardData=1
q9, err := ds.NewQuery(context.Background(), &fleet.Query{
Name: fmt.Sprintf("%s query9", teamIDStr),
Query: "select 1;",
Saved: true,
Interval: 0,
AutomationsEnabled: true,
TeamID: teamID,
DiscardData: true,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
// Interval=1, AutomationsEnabled=0, DiscardData=0, Snapshot=0
_, err = ds.NewQuery(context.Background(), &fleet.Query{
Name: fmt.Sprintf("%s query10", teamIDStr),
Query: "select 1;",
Saved: true,
Interval: 10,
AutomationsEnabled: false,
TeamID: teamID,
DiscardData: false,
Logging: fleet.LoggingDifferentialIgnoreRemovals,
})
require.NoError(t, err)
// Interval=1, AutomationsEnabled=0, DiscardData=0, Snapshot=1
q11, err := ds.NewQuery(context.Background(), &fleet.Query{
Name: fmt.Sprintf("%s query11", teamIDStr),
Query: "select 1;",
Saved: true,
Interval: 10,
AutomationsEnabled: false,
TeamID: teamID,
DiscardData: false,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
// Interval=1, AutomationsEnabled=0, DiscardData=1, Snapshot=0
_, err = ds.NewQuery(context.Background(), &fleet.Query{
Name: fmt.Sprintf("%s query12", teamIDStr),
Query: "select 1;",
Saved: true,
Interval: 10,
AutomationsEnabled: false,
TeamID: teamID,
DiscardData: true,
Logging: fleet.LoggingDifferentialIgnoreRemovals,
})
require.NoError(t, err)
// Interval=1, AutomationsEnabled=0, DiscardData=1, Snapshot=1
_, err = ds.NewQuery(context.Background(), &fleet.Query{
Name: fmt.Sprintf("%s query13", teamIDStr),
Query: "select 1;",
Saved: true,
Interval: 10,
AutomationsEnabled: false,
TeamID: teamID,
DiscardData: true,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
// Interval=1, AutomationsEnabled=1, DiscardData=0, Snapshot=0
q14, err := ds.NewQuery(context.Background(), &fleet.Query{
Name: fmt.Sprintf("%s query14", teamIDStr),
Query: "select 1;",
Saved: true,
Interval: 10,
AutomationsEnabled: true,
TeamID: teamID,
DiscardData: false,
Logging: fleet.LoggingDifferential,
})
require.NoError(t, err)
// Interval=1, AutomationsEnabled=1, DiscardData=0, Snapshot=1
q15, err := ds.NewQuery(context.Background(), &fleet.Query{
Name: fmt.Sprintf("%s query15", teamIDStr),
Query: "select 1;",
Saved: true,
Interval: 10,
AutomationsEnabled: true,
TeamID: teamID,
DiscardData: false,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
// Interval=1, AutomationsEnabled=1, DiscardData=1, Snapshot=0
q16, err := ds.NewQuery(context.Background(), &fleet.Query{
Name: fmt.Sprintf("%s query16", teamIDStr),
Query: "select 1;",
Saved: true,
Interval: 10,
AutomationsEnabled: true,
TeamID: teamID,
DiscardData: true,
Logging: fleet.LoggingDifferential,
})
require.NoError(t, err)
// Interval=1, AutomationsEnabled=1, DiscardData=1, Snapshot=1
q17, err := ds.NewQuery(context.Background(), &fleet.Query{
Name: fmt.Sprintf("%s query17", teamIDStr),
Query: "select 1;",
Saved: true,
Interval: 10,
AutomationsEnabled: true,
TeamID: teamID,
DiscardData: true,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
@ -823,7 +961,7 @@ func testListScheduledQueriesForAgents(t *testing.T, ds *Datastore) {
sort.Slice(result, func(i, j int) bool {
return result[i].ID < result[j].ID
})
test.QueryElementsMatch(t, result, []*fleet.Query{q6, q8, q9}, i)
test.QueryElementsMatch(t, result, []*fleet.Query{q11, q14, q15, q16, q17}, i)
queryReportsDisabled = true
result, err = ds.ListScheduledQueriesForAgents(ctx, teamID, queryReportsDisabled)
@ -831,6 +969,6 @@ func testListScheduledQueriesForAgents(t *testing.T, ds *Datastore) {
sort.Slice(result, func(i, j int) bool {
return result[i].ID < result[j].ID
})
test.QueryElementsMatch(t, result, []*fleet.Query{q8, q9}, i)
test.QueryElementsMatch(t, result, []*fleet.Query{q14, q15, q16, q17}, i)
}
}

View File

@ -41,8 +41,8 @@ func TestScheduledQueries(t *testing.T) {
func testScheduledQueriesListInPackWithStats(t *testing.T, ds *Datastore) {
zwass := test.NewUser(t, ds, "Zach", "zwass@fleet.co", true)
queries := []*fleet.Query{
{Name: "foo", Description: "get the foos", Query: "select * from foo"},
{Name: "bar", Description: "do some bars", Query: "select baz from bar"},
{Name: "foo", Description: "get the foos", Query: "select * from foo", Logging: fleet.LoggingSnapshot},
{Name: "bar", Description: "do some bars", Query: "select baz from bar", Logging: fleet.LoggingDifferential},
}
err := ds.ApplyQueries(context.Background(), zwass.ID, queries, nil)
require.NoError(t, err)
@ -131,8 +131,8 @@ func testScheduledQueriesListInPackWithStats(t *testing.T, ds *Datastore) {
func testScheduledQueriesListInPack(t *testing.T, ds *Datastore) {
zwass := test.NewUser(t, ds, "Zach", "zwass@fleet.co", true)
queries := []*fleet.Query{
{Name: "foo", Description: "get the foos", Query: "select * from foo"},
{Name: "bar", Description: "do some bars", Query: "select baz from bar"},
{Name: "foo", Description: "get the foos", Query: "select * from foo", Logging: fleet.LoggingSnapshot},
{Name: "bar", Description: "do some bars", Query: "select baz from bar", Logging: fleet.LoggingSnapshot},
}
err := ds.ApplyQueries(context.Background(), zwass.ID, queries, nil)
require.NoError(t, err)
@ -324,8 +324,8 @@ func testScheduledQueriesDelete(t *testing.T, ds *Datastore) {
func testScheduledQueriesCascadingDelete(t *testing.T, ds *Datastore) {
zwass := test.NewUser(t, ds, "Zach", "zwass@fleet.co", true)
queries := []*fleet.Query{
{Name: "foo", Description: "get the foos", Query: "select * from foo"},
{Name: "bar", Description: "do some bars", Query: "select baz from bar"},
{Name: "foo", Description: "get the foos", Query: "select * from foo", Logging: fleet.LoggingSnapshot},
{Name: "bar", Description: "do some bars", Query: "select baz from bar", Logging: fleet.LoggingSnapshot},
}
err := ds.ApplyQueries(context.Background(), zwass.ID, queries, nil)
require.Nil(t, err)
@ -374,10 +374,10 @@ func testScheduledQueriesIDsByName(t *testing.T, ds *Datastore) {
ctx := context.Background()
user := test.NewUser(t, ds, "User", "user@example.com", true)
queries := []*fleet.Query{
{Name: "foo", Description: "get the foos", Query: "select * from foo"},
{Name: "bar", Description: "do some bars", Query: "select * from bar"},
{Name: "foo2", Description: "get the foos", Query: "select * from foo2"},
{Name: "bar2", Description: "do some bars", Query: "select * from bar2"},
{Name: "foo", Description: "get the foos", Query: "select * from foo", Logging: fleet.LoggingSnapshot},
{Name: "bar", Description: "do some bars", Query: "select * from bar", Logging: fleet.LoggingSnapshot},
{Name: "foo2", Description: "get the foos", Query: "select * from foo2", Logging: fleet.LoggingSnapshot},
{Name: "bar2", Description: "do some bars", Query: "select * from bar2", Logging: fleet.LoggingSnapshot},
}
err := ds.ApplyQueries(ctx, user.ID, queries, nil)
require.NoError(t, err)

File diff suppressed because one or more lines are too long

View File

@ -236,8 +236,7 @@ func verifyQuerySQL(query string) error {
}
func verifyLogging(logging string) error {
// Empty string means snapshot.
if logging != "" && logging != LoggingSnapshot && logging != LoggingDifferential && logging != LoggingDifferentialIgnoreRemovals {
if logging != LoggingSnapshot && logging != LoggingDifferential && logging != LoggingDifferentialIgnoreRemovals {
return errInvalidLogging
}
return nil

View File

@ -181,7 +181,7 @@ func ScheduledQueryFromQuery(query *Query) *ScheduledQuery {
}
func ScheduledQueryToQueryPayloadForNewQuery(originalQuery *Query, scheduledQuery *ScheduledQuery) QueryPayload {
var logging *string
logging := ptr.String(LoggingSnapshot) // default is snapshot.
if scheduledQuery.Snapshot != nil && scheduledQuery.Removed != nil {
if *scheduledQuery.Snapshot {
logging = ptr.String(LoggingSnapshot)

View File

@ -72,6 +72,8 @@ func (svc *Service) NewDistributedQueryCampaign(ctx context.Context, queryString
Query: queryString,
Saved: false,
AuthorID: ptr.Uint(vc.UserID()),
// We must set a valid value for this field, even if unused by live queries.
Logging: fleet.LoggingSnapshot,
}
if err := query.Verify(); err != nil {
return nil, ctxerr.Wrap(ctx, &fleet.BadRequestError{

View File

@ -559,6 +559,7 @@ func (s *integrationTestSuite) TestGlobalSchedule() {
Query: "select * from osquery;",
ObserverCanRun: true,
Saved: true,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
@ -788,6 +789,7 @@ func (s *integrationTestSuite) TestGlobalPolicies() {
Description: "Some description",
Query: "select * from osquery;",
ObserverCanRun: true,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
@ -1795,6 +1797,7 @@ func (s *integrationTestSuite) TestGlobalPoliciesProprietary() {
Description: "Some description",
Query: "select * from osquery;",
ObserverCanRun: true,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
// Cannot set both QueryID and Query.
@ -4478,6 +4481,7 @@ func (s *integrationTestSuite) TestQueriesBadRequests() {
name string
query string
platform string
logging string
}{
{
tname: "empty name",
@ -4518,12 +4522,19 @@ func (s *integrationTestSuite) TestQueriesBadRequests() {
query: "select 1",
platform: "windows darwin",
},
{
tname: "invalid logging value",
name: "bad query",
query: "select 1",
logging: "foobar",
},
} {
t.Run(tc.tname, func(t *testing.T) {
reqQuery := &fleet.QueryPayload{
Name: ptr.String(tc.name),
Query: ptr.String(tc.query),
Platform: ptr.String(tc.platform),
Logging: ptr.String(tc.logging),
}
createQueryResp := createQueryResponse{}
s.DoJSON("POST", "/api/latest/fleet/queries", reqQuery, http.StatusBadRequest, &createQueryResp)
@ -4533,6 +4544,7 @@ func (s *integrationTestSuite) TestQueriesBadRequests() {
Name: ptr.String(tc.name),
Query: ptr.String(tc.query),
Platform: ptr.String(tc.platform),
Logging: ptr.String(tc.logging),
}
mResp := modifyQueryResponse{}
s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/queries/%d", existingQueryID), &payload, http.StatusBadRequest, &mResp)
@ -6729,6 +6741,7 @@ func (s *integrationTestSuite) TestAPIVersion_v1_2022_04() {
Query: "select * from osquery;",
ObserverCanRun: true,
Saved: true,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
@ -7069,7 +7082,7 @@ func (s *integrationTestSuite) TestDirectIngestScheduledQueryStats() {
Interval: 10,
Platform: "darwin",
AutomationsEnabled: true,
Logging: "snapshot",
Logging: fleet.LoggingSnapshot,
Description: "foobar",
Query: "SELECT * from time;",
Saved: true,
@ -7081,7 +7094,7 @@ func (s *integrationTestSuite) TestDirectIngestScheduledQueryStats() {
Interval: 0,
Platform: "darwin",
AutomationsEnabled: false,
Logging: "snapshot",
Logging: fleet.LoggingSnapshot,
Description: "foobar",
Query: "SELECT * from osquery_info;",
Saved: true,
@ -7093,7 +7106,7 @@ func (s *integrationTestSuite) TestDirectIngestScheduledQueryStats() {
Interval: 20,
Platform: "",
AutomationsEnabled: true,
Logging: "snapshot",
Logging: fleet.LoggingSnapshot,
Description: "foobar",
Query: "SELECT * from other;",
Saved: true,
@ -7105,7 +7118,7 @@ func (s *integrationTestSuite) TestDirectIngestScheduledQueryStats() {
Interval: 90,
Platform: "",
AutomationsEnabled: true,
Logging: "snapshot",
Logging: fleet.LoggingSnapshot,
Description: "foobar",
Query: "SELECT * from other;",
Saved: true,
@ -7133,7 +7146,7 @@ func (s *integrationTestSuite) TestDirectIngestScheduledQueryStats() {
Interval: 40,
Platform: "",
AutomationsEnabled: true,
Logging: "snapshot",
Logging: fleet.LoggingSnapshot,
Description: "foobar",
Query: "SELECT * from other;",
Saved: true,

View File

@ -481,6 +481,7 @@ func (s *integrationEnterpriseTestSuite) TestTeamSchedule() {
Query: "select * from osquery;",
ObserverCanRun: true,
Saved: true,
Logging: fleet.LoggingSnapshot,
},
)
require.NoError(t, err)
@ -568,7 +569,13 @@ func (s *integrationEnterpriseTestSuite) TestTeamPolicies() {
require.NoError(t, err)
}()
qr, err := s.ds.NewQuery(context.Background(), &fleet.Query{Name: "TestQuery2", Description: "Some description", Query: "select * from osquery;", ObserverCanRun: true})
qr, err := s.ds.NewQuery(context.Background(), &fleet.Query{
Name: "TestQuery2",
Description: "Some description",
Query: "select * from osquery;",
ObserverCanRun: true,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
tpParams := teamPolicyRequest{
@ -1846,6 +1853,7 @@ func (s *integrationEnterpriseTestSuite) TestListDevicePolicies() {
Description: "Some description",
Query: "select * from osquery;",
ObserverCanRun: true,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
@ -3010,8 +3018,9 @@ func (s *integrationEnterpriseTestSuite) TestGitOpsUserActions() {
s.DoJSON("GET", "/api/latest/fleet/config", nil, http.StatusOK, &acr)
require.False(t, acr.WebhookSettings.VulnerabilitiesWebhook.Enable)
q1, err := s.ds.NewQuery(ctx, &fleet.Query{
Name: "Foo",
Query: "SELECT * from time;",
Name: "Foo",
Query: "SELECT * from time;",
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
ggsr := getGlobalScheduleResponse{}

View File

@ -83,7 +83,12 @@ func (s *liveQueriesTestSuite) TestLiveQueriesRestOneHostOneQuery() {
host := s.hosts[0]
q1, err := s.ds.NewQuery(context.Background(), &fleet.Query{Query: "select 1 from osquery;", Description: "desc1", Name: t.Name() + "query1"})
q1, err := s.ds.NewQuery(context.Background(), &fleet.Query{
Query: "select 1 from osquery;",
Description: "desc1",
Name: t.Name() + "query1",
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
s.lq.On("QueriesForHost", uint(1)).Return(map[string]string{fmt.Sprint(q1.ID): "select 1 from osquery;"}, nil)
@ -142,10 +147,20 @@ func (s *liveQueriesTestSuite) TestLiveQueriesRestOneHostMultipleQuery() {
host := s.hosts[0]
q1, err := s.ds.NewQuery(context.Background(), &fleet.Query{Query: "select 1 from osquery;", Description: "desc1", Name: t.Name() + "query1"})
q1, err := s.ds.NewQuery(context.Background(), &fleet.Query{
Query: "select 1 from osquery;",
Description: "desc1",
Name: t.Name() + "query1",
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
q2, err := s.ds.NewQuery(context.Background(), &fleet.Query{Query: "select 2 from osquery;", Description: "desc2", Name: t.Name() + "query2"})
q2, err := s.ds.NewQuery(context.Background(), &fleet.Query{
Query: "select 2 from osquery;",
Description: "desc2",
Name: t.Name() + "query2",
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
s.lq.On("QueriesForHost", host.ID).Return(map[string]string{
@ -237,10 +252,20 @@ func (s *liveQueriesTestSuite) TestLiveQueriesRestMultipleHostMultipleQuery() {
h1 := s.hosts[0]
h2 := s.hosts[1]
q1, err := s.ds.NewQuery(context.Background(), &fleet.Query{Query: "select 1 from osquery;", Description: "desc1", Name: t.Name() + "query1"})
q1, err := s.ds.NewQuery(context.Background(), &fleet.Query{
Query: "select 1 from osquery;",
Description: "desc1",
Name: t.Name() + "query1",
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
q2, err := s.ds.NewQuery(context.Background(), &fleet.Query{Query: "select 2 from osquery;", Description: "desc2", Name: t.Name() + "query2"})
q2, err := s.ds.NewQuery(context.Background(), &fleet.Query{
Query: "select 2 from osquery;",
Description: "desc2",
Name: t.Name() + "query2",
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
s.lq.On("QueriesForHost", h1.ID).Return(map[string]string{
@ -344,7 +369,12 @@ func (s *liveQueriesTestSuite) TestLiveQueriesRestFailsOnSomeHost() {
h1 := s.hosts[0]
h2 := s.hosts[1]
q1, err := s.ds.NewQuery(context.Background(), &fleet.Query{Query: "select 1 from osquery;", Description: "desc1", Name: t.Name() + "query1"})
q1, err := s.ds.NewQuery(context.Background(), &fleet.Query{
Query: "select 1 from osquery;",
Description: "desc1",
Name: t.Name() + "query1",
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)
s.lq.On("QueriesForHost", h1.ID).Return(map[string]string{fmt.Sprint(q1.ID): "select 1 from osquery;"}, nil)

View File

@ -209,6 +209,10 @@ func (svc *Service) NewQuery(ctx context.Context, p fleet.QueryPayload) (*fleet.
return nil, err
}
if p.Logging == nil || (p.Logging != nil && *p.Logging == "") {
p.Logging = ptr.String(fleet.LoggingSnapshot)
}
if err := p.Verify(); err != nil {
return nil, ctxerr.Wrap(ctx, &fleet.BadRequestError{
Message: fmt.Sprintf("query payload verification: %s", err),
@ -317,6 +321,10 @@ func (svc *Service) ModifyQuery(ctx context.Context, id uint, p fleet.QueryPaylo
return nil, err
}
if p.Logging != nil && *p.Logging == "" {
p.Logging = ptr.String(fleet.LoggingSnapshot)
}
if err := p.Verify(); err != nil {
return nil, ctxerr.Wrap(ctx, &fleet.BadRequestError{
Message: fmt.Sprintf("query payload verification: %s", err),
@ -640,6 +648,10 @@ func (svc *Service) queryFromSpec(ctx context.Context, spec *fleet.QuerySpec) (*
}
teamID = &team.ID
}
logging := spec.Logging
if logging == "" {
logging = fleet.LoggingSnapshot
}
return &fleet.Query{
Name: spec.Name,
Description: spec.Description,
@ -651,7 +663,7 @@ func (svc *Service) queryFromSpec(ctx context.Context, spec *fleet.QuerySpec) (*
Platform: spec.Platform,
MinOsqueryVersion: spec.MinOsqueryVersion,
AutomationsEnabled: spec.AutomationsEnabled,
Logging: spec.Logging,
Logging: logging,
DiscardData: spec.DiscardData,
}, nil
}

View File

@ -25,6 +25,7 @@ func NewQueryWithSchedule(t *testing.T, ds fleet.Datastore, teamID *uint, name,
TeamID: teamID,
Interval: interval,
AutomationsEnabled: automationsEnabled,
Logging: fleet.LoggingSnapshot,
})
require.NoError(t, err)