mirror of
https://github.com/empayre/fleet.git
synced 2024-11-06 00:45:19 +00:00
Calendar config updates -- policy table now has calendar_events_enabled (#17645)
# Checklist for submitter - [ ] 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. - [x] Added/updated tests - [x] If database migrations are included, checked table schema to confirm autoupdate - For database migrations: - [x] Checked schema for all modified table for columns that will auto-update timestamps during migration. - [x] Confirmed that updating the timestamps is acceptable, and will not cause unwanted side effects. - [x] Manual QA for all new/changed functionality
This commit is contained in:
parent
d3e1716572
commit
63e9d49dfc
@ -452,20 +452,6 @@ spec:
|
||||
)
|
||||
|
||||
// Apply calendar integration
|
||||
validPolicyID := uint(10)
|
||||
validPolicyName := "validPolicy"
|
||||
ds.PoliciesByNameFunc = func(ctx context.Context, names []string, teamID uint) (map[string]*fleet.Policy, error) {
|
||||
var policies = make(map[string]*fleet.Policy)
|
||||
for _, name := range names {
|
||||
if name != validPolicyName {
|
||||
return nil, ¬FoundError{}
|
||||
}
|
||||
policies[name] = &fleet.Policy{
|
||||
PolicyData: fleet.PolicyData{ID: validPolicyID, TeamID: &teamsByName["team1"].ID, Name: validPolicyName},
|
||||
}
|
||||
}
|
||||
return policies, nil
|
||||
}
|
||||
filename = writeTmpYml(
|
||||
t, `
|
||||
apiVersion: v1
|
||||
@ -477,8 +463,6 @@ spec:
|
||||
google_calendar:
|
||||
email: `+googleCalEmail+`
|
||||
enable_calendar_events: true
|
||||
policies:
|
||||
- name: `+validPolicyName+`
|
||||
webhook_url: https://example.com/webhook
|
||||
`,
|
||||
)
|
||||
@ -488,7 +472,6 @@ spec:
|
||||
t, fleet.TeamGoogleCalendarIntegration{
|
||||
Email: googleCalEmail,
|
||||
Enable: true,
|
||||
Policies: []*fleet.PolicyRef{{Name: validPolicyName, ID: validPolicyID}},
|
||||
WebhookURL: "https://example.com/webhook",
|
||||
}, *teamsByName["team1"].Config.Integrations.GoogleCalendar,
|
||||
)
|
||||
@ -505,8 +488,6 @@ spec:
|
||||
google_calendar:
|
||||
email: not_present_globally@example.com
|
||||
enable_calendar_events: true
|
||||
policies:
|
||||
- name: `+validPolicyName+`
|
||||
webhook_url: https://example.com/webhook
|
||||
`,
|
||||
)
|
||||
@ -514,26 +495,6 @@ spec:
|
||||
_, err = runAppNoChecks([]string{"apply", "-f", filename})
|
||||
assert.ErrorContains(t, err, "email must match a global Google Calendar integration email")
|
||||
|
||||
// Apply calendar integration -- invalid policy name
|
||||
filename = writeTmpYml(
|
||||
t, `
|
||||
apiVersion: v1
|
||||
kind: team
|
||||
spec:
|
||||
team:
|
||||
name: team1
|
||||
integrations:
|
||||
google_calendar:
|
||||
email: `+googleCalEmail+`
|
||||
enable_calendar_events: true
|
||||
policies:
|
||||
- name: invalidPolicy
|
||||
webhook_url: https://example.com/webhook
|
||||
`,
|
||||
)
|
||||
_, err = runAppNoChecks([]string{"apply", "-f", filename})
|
||||
assert.ErrorContains(t, err, "name is invalid")
|
||||
|
||||
// Apply calendar integration -- invalid webhook destination
|
||||
filename = writeTmpYml(
|
||||
t, `
|
||||
@ -546,8 +507,6 @@ spec:
|
||||
google_calendar:
|
||||
email: `+googleCalEmail+`
|
||||
enable_calendar_events: true
|
||||
policies:
|
||||
- name: `+validPolicyName+`
|
||||
webhook_url: bozo
|
||||
`,
|
||||
)
|
||||
|
@ -331,29 +331,31 @@ func TestGetHosts(t *testing.T) {
|
||||
return []*fleet.HostPolicy{
|
||||
{
|
||||
PolicyData: fleet.PolicyData{
|
||||
ID: 1,
|
||||
Name: "query1",
|
||||
Query: defaultPolicyQuery,
|
||||
Description: "Some description",
|
||||
AuthorID: ptr.Uint(1),
|
||||
AuthorName: "Alice",
|
||||
AuthorEmail: "alice@example.com",
|
||||
Resolution: ptr.String("Some resolution"),
|
||||
TeamID: ptr.Uint(1),
|
||||
ID: 1,
|
||||
Name: "query1",
|
||||
Query: defaultPolicyQuery,
|
||||
Description: "Some description",
|
||||
AuthorID: ptr.Uint(1),
|
||||
AuthorName: "Alice",
|
||||
AuthorEmail: "alice@example.com",
|
||||
Resolution: ptr.String("Some resolution"),
|
||||
TeamID: ptr.Uint(1),
|
||||
CalendarEventsEnabled: true,
|
||||
},
|
||||
Response: "passes",
|
||||
},
|
||||
{
|
||||
PolicyData: fleet.PolicyData{
|
||||
ID: 2,
|
||||
Name: "query2",
|
||||
Query: defaultPolicyQuery,
|
||||
Description: "",
|
||||
AuthorID: ptr.Uint(1),
|
||||
AuthorName: "Alice",
|
||||
AuthorEmail: "alice@example.com",
|
||||
Resolution: nil,
|
||||
TeamID: nil,
|
||||
ID: 2,
|
||||
Name: "query2",
|
||||
Query: defaultPolicyQuery,
|
||||
Description: "",
|
||||
AuthorID: ptr.Uint(1),
|
||||
AuthorName: "Alice",
|
||||
AuthorEmail: "alice@example.com",
|
||||
Resolution: nil,
|
||||
TeamID: nil,
|
||||
CalendarEventsEnabled: false,
|
||||
},
|
||||
Response: "fails",
|
||||
},
|
||||
|
@ -466,12 +466,6 @@ func TestFullTeamGitOps(t *testing.T) {
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
ds.PoliciesByNameFunc = func(ctx context.Context, names []string, teamID uint) (map[string]*fleet.Policy, error) {
|
||||
if slices.Contains(names, "policy1") && slices.Contains(names, "policy2") {
|
||||
return map[string]*fleet.Policy{"policy1": &policy, "policy2": &policy}, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
ds.DeleteTeamPoliciesFunc = func(ctx context.Context, teamID uint, IDs []uint) ([]uint, error) {
|
||||
policyDeleted = true
|
||||
assert.Equal(t, []uint{policy.ID}, IDs)
|
||||
@ -554,7 +548,6 @@ func TestFullTeamGitOps(t *testing.T) {
|
||||
require.NotNil(t, savedTeam.Config.Integrations.GoogleCalendar)
|
||||
assert.Equal(t, "service@example.com", savedTeam.Config.Integrations.GoogleCalendar.Email)
|
||||
assert.True(t, savedTeam.Config.Integrations.GoogleCalendar.Enable)
|
||||
assert.Len(t, savedTeam.Config.Integrations.GoogleCalendar.Policies, 2)
|
||||
|
||||
// Now clear the settings
|
||||
tmpFile, err := os.CreateTemp(t.TempDir(), "*.yml")
|
||||
|
@ -76,7 +76,8 @@
|
||||
"team_id": 1,
|
||||
"updated_at": "0001-01-01T00:00:00Z",
|
||||
"created_at": "0001-01-01T00:00:00Z",
|
||||
"critical": false
|
||||
"critical": false,
|
||||
"calendar_events_enabled": true
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
@ -91,7 +92,8 @@
|
||||
"team_id": null,
|
||||
"updated_at": "0001-01-01T00:00:00Z",
|
||||
"created_at": "0001-01-01T00:00:00Z",
|
||||
"critical": false
|
||||
"critical": false,
|
||||
"calendar_events_enabled": false
|
||||
}
|
||||
],
|
||||
"status": "offline",
|
||||
|
@ -62,6 +62,7 @@ spec:
|
||||
created_at: "0001-01-01T00:00:00Z"
|
||||
updated_at: "0001-01-01T00:00:00Z"
|
||||
critical: false
|
||||
calendar_events_enabled: true
|
||||
- author_email: "alice@example.com"
|
||||
author_id: 1
|
||||
author_name: Alice
|
||||
@ -75,6 +76,7 @@ spec:
|
||||
created_at: "0001-01-01T00:00:00Z"
|
||||
updated_at: "0001-01-01T00:00:00Z"
|
||||
critical: false
|
||||
calendar_events_enabled: false
|
||||
policy_updated_at: "0001-01-01T00:00:00Z"
|
||||
public_ip: ""
|
||||
primary_ip: ""
|
||||
|
@ -19,9 +19,6 @@ team_settings:
|
||||
google_calendar:
|
||||
email: service@example.com
|
||||
enable_calendar_events: true
|
||||
policies:
|
||||
- name: policy1
|
||||
- name: policy2
|
||||
webhook_url: https://example.com/google_calendar_webhook
|
||||
agent_options:
|
||||
command_line_flags:
|
||||
@ -97,6 +94,7 @@ policies:
|
||||
description: This policy should always fail.
|
||||
resolution: There is no resolution for this policy.
|
||||
query: SELECT 1 FROM osquery_info WHERE start_time < 0;
|
||||
calendar_events_enabled: true
|
||||
- name: Passing policy
|
||||
platform: linux,windows,darwin,chrome
|
||||
description: This policy should always pass.
|
||||
|
@ -197,19 +197,21 @@ func (svc *Service) ModifyTeam(ctx context.Context, teamID uint, payload fleet.T
|
||||
}
|
||||
|
||||
if payload.Integrations != nil {
|
||||
// the team integrations must reference an existing global config integration.
|
||||
if _, err := payload.Integrations.MatchWithIntegrations(appCfg.Integrations); err != nil {
|
||||
return nil, fleet.NewInvalidArgumentError("integrations", err.Error())
|
||||
}
|
||||
if payload.Integrations.Jira != nil || payload.Integrations.Zendesk != nil {
|
||||
// the team integrations must reference an existing global config integration.
|
||||
if _, err := payload.Integrations.MatchWithIntegrations(appCfg.Integrations); err != nil {
|
||||
return nil, fleet.NewInvalidArgumentError("integrations", err.Error())
|
||||
}
|
||||
|
||||
// integrations must be unique
|
||||
if err := payload.Integrations.Validate(); err != nil {
|
||||
return nil, fleet.NewInvalidArgumentError("integrations", err.Error())
|
||||
}
|
||||
// integrations must be unique
|
||||
if err := payload.Integrations.Validate(); err != nil {
|
||||
return nil, fleet.NewInvalidArgumentError("integrations", err.Error())
|
||||
}
|
||||
|
||||
team.Config.Integrations.Jira = payload.Integrations.Jira
|
||||
team.Config.Integrations.Zendesk = payload.Integrations.Zendesk
|
||||
// Only update the google calendar integration if it's not nil
|
||||
team.Config.Integrations.Jira = payload.Integrations.Jira
|
||||
team.Config.Integrations.Zendesk = payload.Integrations.Zendesk
|
||||
}
|
||||
// Only update the calendar integration if it's not nil
|
||||
if payload.Integrations.GoogleCalendar != nil {
|
||||
invalid := &fleet.InvalidArgumentError{}
|
||||
_ = svc.validateTeamCalendarIntegrations(ctx, team, payload.Integrations.GoogleCalendar, appCfg, invalid)
|
||||
@ -1179,35 +1181,6 @@ func (svc *Service) validateTeamCalendarIntegrations(
|
||||
} else if u.Scheme != "https" && u.Scheme != "http" {
|
||||
invalid.Append("integrations.google_calendar.webhook_url", "webhook_url must be https or http")
|
||||
}
|
||||
// Validate policy ids
|
||||
if len(calendarIntegration.Policies) == 0 {
|
||||
invalid.Append("integrations.google_calendar.policies", "policies are required")
|
||||
}
|
||||
if len(calendarIntegration.Policies) > 0 {
|
||||
for _, policy := range calendarIntegration.Policies {
|
||||
policy.Name = strings.TrimSpace(policy.Name)
|
||||
}
|
||||
calendarIntegration.Policies = server.RemoveDuplicatesFromSlice(calendarIntegration.Policies)
|
||||
policyNames := make([]string, 0, len(calendarIntegration.Policies))
|
||||
for _, policy := range calendarIntegration.Policies {
|
||||
policyNames = append(policyNames, policy.Name)
|
||||
}
|
||||
// Policies must be team policies. Global policies are not allowed.
|
||||
policyMap, err := svc.ds.PoliciesByName(ctx, policyNames, team.ID)
|
||||
if err != nil {
|
||||
level.Error(svc.logger).Log("msg", "error getting policies by name", "names", policyNames, "err", err)
|
||||
if fleet.IsNotFound(err) {
|
||||
invalid.Append("integrations.google_calendar.policies[].name", "name is invalid")
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// PoliciesByName guarantees that all policies are present
|
||||
for _, policy := range calendarIntegration.Policies {
|
||||
policy.ID = policyMap[policy.Name].ID
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,22 @@
|
||||
package tables
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func init() {
|
||||
MigrationClient.AddMigration(Up_20240314151747, Down_20240314151747)
|
||||
}
|
||||
|
||||
func Up_20240314151747(tx *sql.Tx) error {
|
||||
_, err := tx.Exec(`ALTER TABLE policies ADD COLUMN calendar_events_enabled TINYINT(1) UNSIGNED NOT NULL DEFAULT '0'`)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to add calendar_events_enabled to policies: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Down_20240314151747(_ *sql.Tx) error {
|
||||
return nil
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package tables
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestUp_20240314151747(t *testing.T) {
|
||||
db := applyUpToPrev(t)
|
||||
|
||||
policy1 := execNoErrLastID(
|
||||
t, db, "INSERT INTO policies (name, query, description, checksum) VALUES (?,?,?,?)", "policy", "", "", "checksum",
|
||||
)
|
||||
|
||||
// Apply current migration.
|
||||
applyNext(t, db)
|
||||
|
||||
var policyCheck []struct {
|
||||
ID int64 `db:"id"`
|
||||
CalEnabled bool `db:"calendar_events_enabled"`
|
||||
}
|
||||
err := db.SelectContext(context.Background(), &policyCheck, `SELECT id, calendar_events_enabled FROM policies ORDER BY id`)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, policyCheck, 1)
|
||||
assert.Equal(t, policy1, policyCheck[0].ID)
|
||||
assert.Equal(t, false, policyCheck[0].CalEnabled)
|
||||
|
||||
policy2 := execNoErrLastID(
|
||||
t, db, "INSERT INTO policies (name, query, description, checksum, calendar_events_enabled) VALUES (?,?,?,?,?)", "policy2", "", "",
|
||||
"checksum2", 1,
|
||||
)
|
||||
|
||||
policyCheck = nil
|
||||
err = db.SelectContext(context.Background(), &policyCheck, `SELECT id, calendar_events_enabled FROM policies WHERE id = ?`, policy2)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, policyCheck, 1)
|
||||
assert.Equal(t, policy2, policyCheck[0].ID)
|
||||
assert.Equal(t, true, policyCheck[0].CalEnabled)
|
||||
|
||||
}
|
@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"golang.org/x/text/unicode/norm"
|
||||
"sort"
|
||||
@ -20,7 +19,7 @@ import (
|
||||
|
||||
const policyCols = `
|
||||
p.id, p.team_id, p.resolution, p.name, p.query, p.description,
|
||||
p.author_id, p.platforms, p.created_at, p.updated_at, p.critical
|
||||
p.author_id, p.platforms, p.created_at, p.updated_at, p.critical, p.calendar_events_enabled
|
||||
`
|
||||
|
||||
var policySearchColumns = []string{"p.name"}
|
||||
@ -116,10 +115,12 @@ func (ds *Datastore) SavePolicy(ctx context.Context, p *fleet.Policy, shouldRemo
|
||||
p.Name = norm.NFC.String(p.Name)
|
||||
sql := `
|
||||
UPDATE policies
|
||||
SET name = ?, query = ?, description = ?, resolution = ?, platforms = ?, critical = ?, checksum = ` + policiesChecksumComputedColumn() + `
|
||||
SET name = ?, query = ?, description = ?, resolution = ?, platforms = ?, critical = ?, calendar_events_enabled = ?, checksum = ` + policiesChecksumComputedColumn() + `
|
||||
WHERE id = ?
|
||||
`
|
||||
result, err := ds.writer(ctx).ExecContext(ctx, sql, p.Name, p.Query, p.Description, p.Resolution, p.Platform, p.Critical, p.ID)
|
||||
result, err := ds.writer(ctx).ExecContext(
|
||||
ctx, sql, p.Name, p.Query, p.Description, p.Resolution, p.Platform, p.Critical, p.CalendarEventsEnabled, p.ID,
|
||||
)
|
||||
if err != nil {
|
||||
return ctxerr.Wrap(ctx, err, "updating policy")
|
||||
}
|
||||
@ -445,42 +446,6 @@ func (ds *Datastore) PoliciesByID(ctx context.Context, ids []uint) (map[uint]*fl
|
||||
return policiesByID, nil
|
||||
}
|
||||
|
||||
func (ds *Datastore) PoliciesByName(ctx context.Context, names []string, teamID uint) (map[string]*fleet.Policy, error) {
|
||||
sqlQuery := `SELECT ` + policyCols + `
|
||||
FROM policies p
|
||||
WHERE p.team_id = ? AND p.name IN (?)`
|
||||
query, args, err := sqlx.In(sqlQuery, teamID, names)
|
||||
if err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, err, "building query to get policies by name")
|
||||
}
|
||||
|
||||
var policies []*fleet.Policy
|
||||
err = sqlx.SelectContext(
|
||||
ctx,
|
||||
ds.reader(ctx),
|
||||
&policies,
|
||||
query, args...,
|
||||
)
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, ctxerr.Wrap(ctx, notFound("Policy").WithName(fmt.Sprintf("%v", names)))
|
||||
}
|
||||
return nil, ctxerr.Wrap(ctx, err, "getting policies by name")
|
||||
}
|
||||
|
||||
policiesByName := make(map[string]*fleet.Policy, len(names))
|
||||
for _, p := range policies {
|
||||
policiesByName[p.Name] = p
|
||||
}
|
||||
for _, name := range names {
|
||||
if policiesByName[name] == nil {
|
||||
return nil, ctxerr.Wrap(ctx, notFound("Policy").WithName(name))
|
||||
}
|
||||
}
|
||||
|
||||
return policiesByName, nil
|
||||
}
|
||||
|
||||
func (ds *Datastore) DeleteGlobalPolicies(ctx context.Context, ids []uint) ([]uint, error) {
|
||||
return deletePolicyDB(ctx, ds.writer(ctx), ids, nil)
|
||||
}
|
||||
@ -562,10 +527,11 @@ func (ds *Datastore) NewTeamPolicy(ctx context.Context, teamID uint, authorID *u
|
||||
nameUnicode := norm.NFC.String(args.Name)
|
||||
res, err := ds.writer(ctx).ExecContext(ctx,
|
||||
fmt.Sprintf(
|
||||
`INSERT INTO policies (name, query, description, team_id, resolution, author_id, platforms, critical, checksum) VALUES (?, ?, ?, ?, ?, ?, ?, ?, %s)`,
|
||||
`INSERT INTO policies (name, query, description, team_id, resolution, author_id, platforms, critical, calendar_events_enabled, checksum) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, %s)`,
|
||||
policiesChecksumComputedColumn(),
|
||||
),
|
||||
nameUnicode, args.Query, args.Description, teamID, args.Resolution, authorID, args.Platform, args.Critical,
|
||||
args.CalendarEventsEnabled,
|
||||
)
|
||||
switch {
|
||||
case err == nil:
|
||||
@ -623,15 +589,17 @@ func (ds *Datastore) ApplyPolicySpecs(ctx context.Context, authorID uint, specs
|
||||
team_id,
|
||||
platforms,
|
||||
critical,
|
||||
calendar_events_enabled,
|
||||
checksum
|
||||
) VALUES ( ?, ?, ?, ?, ?, (SELECT IFNULL(MIN(id), NULL) FROM teams WHERE name = ?), ?, ?, %s)
|
||||
) VALUES ( ?, ?, ?, ?, ?, (SELECT IFNULL(MIN(id), NULL) FROM teams WHERE name = ?), ?, ?, ?, %s)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
query = VALUES(query),
|
||||
description = VALUES(description),
|
||||
author_id = VALUES(author_id),
|
||||
resolution = VALUES(resolution),
|
||||
platforms = VALUES(platforms),
|
||||
critical = VALUES(critical)
|
||||
critical = VALUES(critical),
|
||||
calendar_events_enabled = VALUES(calendar_events_enabled)
|
||||
`, policiesChecksumComputedColumn(),
|
||||
)
|
||||
for _, spec := range specs {
|
||||
@ -640,6 +608,7 @@ func (ds *Datastore) ApplyPolicySpecs(ctx context.Context, authorID uint, specs
|
||||
spec.Name = norm.NFC.String(spec.Name)
|
||||
res, err := tx.ExecContext(ctx,
|
||||
query, spec.Name, spec.Query, spec.Description, authorID, spec.Resolution, spec.Team, spec.Platform, spec.Critical,
|
||||
spec.CalendarEventsEnabled,
|
||||
)
|
||||
if err != nil {
|
||||
return ctxerr.Wrap(ctx, err, "exec ApplyPolicySpecs insert")
|
||||
|
@ -38,7 +38,6 @@ func TestPolicies(t *testing.T) {
|
||||
{"PolicyQueriesForHost", testPolicyQueriesForHost},
|
||||
{"PolicyQueriesForHostPlatforms", testPolicyQueriesForHostPlatforms},
|
||||
{"PoliciesByID", testPoliciesByID},
|
||||
{"PoliciesByName", testPoliciesByName},
|
||||
{"TeamPolicyTransfer", testTeamPolicyTransfer},
|
||||
{"ApplyPolicySpec", testApplyPolicySpec},
|
||||
{"Save", testPoliciesSave},
|
||||
@ -583,10 +582,11 @@ func testTeamPolicyProprietary(t *testing.T, ds *Datastore) {
|
||||
require.Error(t, err)
|
||||
|
||||
p, err := ds.NewTeamPolicy(ctx, team1.ID, &user1.ID, fleet.PolicyPayload{
|
||||
Name: "query1",
|
||||
Query: "select 1;",
|
||||
Description: "query1 desc",
|
||||
Resolution: "query1 resolution",
|
||||
Name: "query1",
|
||||
Query: "select 1;",
|
||||
Description: "query1 desc",
|
||||
Resolution: "query1 resolution",
|
||||
CalendarEventsEnabled: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
@ -616,6 +616,7 @@ func testTeamPolicyProprietary(t *testing.T, ds *Datastore) {
|
||||
assert.Equal(t, "query1 resolution", *p.Resolution)
|
||||
require.NotNil(t, p.AuthorID)
|
||||
assert.Equal(t, user1.ID, *p.AuthorID)
|
||||
assert.True(t, p.CalendarEventsEnabled)
|
||||
|
||||
globalPolicies, err := ds.ListGlobalPolicies(ctx, fleet.ListOptions{})
|
||||
require.NoError(t, err)
|
||||
@ -1115,47 +1116,6 @@ func testPoliciesByID(t *testing.T, ds *Datastore) {
|
||||
require.ErrorAs(t, err, &nfe)
|
||||
}
|
||||
|
||||
func testPoliciesByName(t *testing.T, ds *Datastore) {
|
||||
ctx := context.Background()
|
||||
user1 := test.NewUser(t, ds, "Alice", "alice@example.com", true)
|
||||
policyName1 := "policy1"
|
||||
policyName2 := "policy2"
|
||||
_ = newTestPolicy(t, ds, user1, policyName1, "darwin", nil)
|
||||
_ = newTestPolicy(t, ds, user1, policyName2, "darwin", nil)
|
||||
team1, err := ds.NewTeam(ctx, &fleet.Team{Name: t.Name() + "team1"})
|
||||
require.NoError(t, err)
|
||||
|
||||
// No names provided
|
||||
_, err = ds.PoliciesByName(context.Background(), []string{}, team1.ID)
|
||||
require.Error(t, err)
|
||||
|
||||
// Policies don't belong to a team
|
||||
_, err = ds.PoliciesByName(context.Background(), []string{policyName1, policyName2}, team1.ID)
|
||||
require.Error(t, err)
|
||||
var nfe fleet.NotFoundError
|
||||
require.ErrorAs(t, err, &nfe)
|
||||
|
||||
policy1 := newTestPolicy(t, ds, user1, policyName1, "darwin", &team1.ID)
|
||||
policy2 := newTestPolicy(t, ds, user1, policyName2, "darwin", &team1.ID)
|
||||
|
||||
policiesByName, err := ds.PoliciesByName(context.Background(), []string{policyName1, policyName2}, team1.ID)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, policiesByName, 2)
|
||||
assert.Equal(t, policiesByName[policyName1].ID, policy1.ID)
|
||||
assert.Equal(t, policiesByName[policyName2].ID, policy2.ID)
|
||||
assert.Equal(t, policiesByName[policyName1].Name, policy1.Name)
|
||||
assert.Equal(t, policiesByName[policyName2].Name, policy2.Name)
|
||||
|
||||
// Policy does not exist
|
||||
_, err = ds.PoliciesByName(context.Background(), []string{"doesn't exist"}, team1.ID)
|
||||
assert.ErrorAs(t, err, &nfe)
|
||||
|
||||
// One exists and one doesn't
|
||||
_, err = ds.PoliciesByName(context.Background(), []string{policyName1, "doesn't exist"}, team1.ID)
|
||||
assert.ErrorAs(t, err, &nfe)
|
||||
|
||||
}
|
||||
|
||||
func testTeamPolicyTransfer(t *testing.T, ds *Datastore) {
|
||||
ctx := context.Background()
|
||||
user1 := test.NewUser(t, ds, "Alice", "alice@example.com", true)
|
||||
@ -1286,12 +1246,13 @@ func testApplyPolicySpec(t *testing.T, ds *Datastore) {
|
||||
Platform: "",
|
||||
},
|
||||
{
|
||||
Name: "query2",
|
||||
Query: "select 2;",
|
||||
Description: "query2 desc",
|
||||
Resolution: "some other resolution",
|
||||
Team: "team1",
|
||||
Platform: "darwin",
|
||||
Name: "query2",
|
||||
Query: "select 2;",
|
||||
Description: "query2 desc",
|
||||
Resolution: "some other resolution",
|
||||
Team: "team1",
|
||||
Platform: "darwin",
|
||||
CalendarEventsEnabled: true,
|
||||
},
|
||||
{
|
||||
Name: "query3",
|
||||
@ -1326,6 +1287,7 @@ func testApplyPolicySpec(t *testing.T, ds *Datastore) {
|
||||
require.NotNil(t, teamPolicies[0].Resolution)
|
||||
assert.Equal(t, "some other resolution", *teamPolicies[0].Resolution)
|
||||
assert.Equal(t, "darwin", teamPolicies[0].Platform)
|
||||
assert.True(t, teamPolicies[0].CalendarEventsEnabled)
|
||||
|
||||
assert.Equal(t, "query3", teamPolicies[1].Name)
|
||||
assert.Equal(t, "select 3;", teamPolicies[1].Query)
|
||||
@ -1335,6 +1297,7 @@ func testApplyPolicySpec(t *testing.T, ds *Datastore) {
|
||||
require.NotNil(t, teamPolicies[1].Resolution)
|
||||
assert.Equal(t, "some other good resolution", *teamPolicies[1].Resolution)
|
||||
assert.Equal(t, "windows,linux", teamPolicies[1].Platform)
|
||||
assert.False(t, teamPolicies[1].CalendarEventsEnabled)
|
||||
|
||||
// Make sure apply is idempotent
|
||||
require.NoError(t, ds.ApplyPolicySpecs(ctx, user1.ID, []*fleet.PolicySpec{
|
||||
@ -1347,12 +1310,13 @@ func testApplyPolicySpec(t *testing.T, ds *Datastore) {
|
||||
Platform: "",
|
||||
},
|
||||
{
|
||||
Name: "query2",
|
||||
Query: "select 2;",
|
||||
Description: "query2 desc",
|
||||
Resolution: "some other resolution",
|
||||
Team: "team1",
|
||||
Platform: "darwin",
|
||||
Name: "query2",
|
||||
Query: "select 2;",
|
||||
Description: "query2 desc",
|
||||
Resolution: "some other resolution",
|
||||
Team: "team1",
|
||||
Platform: "darwin",
|
||||
CalendarEventsEnabled: true,
|
||||
},
|
||||
{
|
||||
Name: "query3",
|
||||
@ -1382,12 +1346,13 @@ func testApplyPolicySpec(t *testing.T, ds *Datastore) {
|
||||
Platform: "",
|
||||
},
|
||||
{
|
||||
Name: "query2",
|
||||
Query: "select 2 from updated;",
|
||||
Description: "query2 desc updated",
|
||||
Resolution: "some other resolution updated",
|
||||
Team: "team1", // No error, team did not change
|
||||
Platform: "windows",
|
||||
Name: "query2",
|
||||
Query: "select 2 from updated;",
|
||||
Description: "query2 desc updated",
|
||||
Resolution: "some other resolution updated",
|
||||
Team: "team1", // No error, team did not change
|
||||
Platform: "windows",
|
||||
CalendarEventsEnabled: false,
|
||||
},
|
||||
}))
|
||||
policies, err = ds.ListGlobalPolicies(ctx, fleet.ListOptions{})
|
||||
@ -1402,6 +1367,7 @@ func testApplyPolicySpec(t *testing.T, ds *Datastore) {
|
||||
require.NotNil(t, policies[0].Resolution)
|
||||
assert.Equal(t, "some resolution updated", *policies[0].Resolution)
|
||||
assert.Equal(t, "", policies[0].Platform)
|
||||
assert.False(t, policies[0].CalendarEventsEnabled)
|
||||
|
||||
teamPolicies, _, err = ds.ListTeamPolicies(ctx, team1.ID, fleet.ListOptions{}, fleet.ListOptions{})
|
||||
require.NoError(t, err)
|
||||
@ -1481,11 +1447,12 @@ func testPoliciesSave(t *testing.T, ds *Datastore) {
|
||||
assert.Equal(t, computeChecksum(*gp), hex.EncodeToString(globalChecksum))
|
||||
|
||||
payload = fleet.PolicyPayload{
|
||||
Name: "team1 query",
|
||||
Query: "select 2;",
|
||||
Description: "team1 query desc",
|
||||
Resolution: "team1 query resolution",
|
||||
Critical: true,
|
||||
Name: "team1 query",
|
||||
Query: "select 2;",
|
||||
Description: "team1 query desc",
|
||||
Resolution: "team1 query resolution",
|
||||
Critical: true,
|
||||
CalendarEventsEnabled: true,
|
||||
}
|
||||
tp1, err := ds.NewTeamPolicy(ctx, team1.ID, &user1.ID, payload)
|
||||
require.NoError(t, err)
|
||||
@ -1494,6 +1461,7 @@ func testPoliciesSave(t *testing.T, ds *Datastore) {
|
||||
require.Equal(t, tp1.Description, payload.Description)
|
||||
require.Equal(t, *tp1.Resolution, payload.Resolution)
|
||||
require.Equal(t, tp1.Critical, payload.Critical)
|
||||
assert.Equal(t, tp1.CalendarEventsEnabled, payload.CalendarEventsEnabled)
|
||||
var teamChecksum []uint8
|
||||
err = ds.writer(context.Background()).Get(&teamChecksum, `SELECT checksum FROM policies WHERE id = ?`, tp1.ID)
|
||||
require.NoError(t, err)
|
||||
@ -1522,6 +1490,7 @@ func testPoliciesSave(t *testing.T, ds *Datastore) {
|
||||
tp2.Description = "team1 query desc updated"
|
||||
tp2.Resolution = ptr.String("team1 query resolution updated")
|
||||
tp2.Critical = false
|
||||
tp2.CalendarEventsEnabled = false
|
||||
err = ds.SavePolicy(ctx, &tp2, true)
|
||||
require.NoError(t, err)
|
||||
tp1, err = ds.Policy(ctx, tp1.ID)
|
||||
|
@ -588,7 +588,6 @@ type Datastore interface {
|
||||
|
||||
ListGlobalPolicies(ctx context.Context, opts ListOptions) ([]*Policy, error)
|
||||
PoliciesByID(ctx context.Context, ids []uint) (map[uint]*Policy, error)
|
||||
PoliciesByName(ctx context.Context, names []string, teamID uint) (map[string]*Policy, error)
|
||||
DeleteGlobalPolicies(ctx context.Context, ids []uint) ([]uint, error)
|
||||
CountPolicies(ctx context.Context, teamID *uint, matchQuery string) (int, error)
|
||||
UpdateHostPolicyCounts(ctx context.Context) error
|
||||
|
@ -112,14 +112,9 @@ func (z TeamZendeskIntegration) UniqueKey() string {
|
||||
}
|
||||
|
||||
type TeamGoogleCalendarIntegration struct {
|
||||
Email string `json:"email"`
|
||||
Enable bool `json:"enable_calendar_events"`
|
||||
Policies []*PolicyRef `json:"policies"`
|
||||
WebhookURL string `json:"webhook_url"`
|
||||
}
|
||||
type PolicyRef struct {
|
||||
Name string `json:"name"`
|
||||
ID uint `json:"id"`
|
||||
Email string `json:"email"`
|
||||
Enable bool `json:"enable_calendar_events"`
|
||||
WebhookURL string `json:"webhook_url"`
|
||||
}
|
||||
|
||||
// JiraIntegration configures an instance of an integration with the Jira
|
||||
@ -380,7 +375,7 @@ func ValidateEnabledHostStatusIntegrations(webhook HostStatusWebhookSettings, in
|
||||
|
||||
func ValidateGoogleCalendarIntegrations(intgs []*GoogleCalendarIntegration, invalid *InvalidArgumentError) {
|
||||
if len(intgs) > 1 {
|
||||
invalid.Append("integrations.google_calendar", "only one Google Calendar integration is allowed at this time")
|
||||
invalid.Append("integrations.google_calendar", "integrating with >1 Google Workspace service account is not yet supported.")
|
||||
}
|
||||
for _, intg := range intgs {
|
||||
intg.Email = strings.TrimSpace(intg.Email)
|
||||
|
@ -30,6 +30,8 @@ type PolicyPayload struct {
|
||||
//
|
||||
// Empty string targets all platforms.
|
||||
Platform string
|
||||
// CalendarEventsEnabled indicates whether calendar events are enabled for the policy. Only applies to team policies.
|
||||
CalendarEventsEnabled bool
|
||||
}
|
||||
|
||||
var (
|
||||
@ -107,6 +109,8 @@ type ModifyPolicyPayload struct {
|
||||
Platform *string `json:"platform"`
|
||||
// Critical marks the policy as high impact.
|
||||
Critical *bool `json:"critical" premium:"true"`
|
||||
// CalendarEventsEnabled indicates whether calendar events are enabled for the policy. Only applies to team policies.
|
||||
CalendarEventsEnabled *bool `json:"calendar_events_enabled" premium:"true"`
|
||||
}
|
||||
|
||||
// Verify verifies the policy payload is valid.
|
||||
@ -159,6 +163,8 @@ type PolicyData struct {
|
||||
// Empty string targets all platforms.
|
||||
Platform string `json:"platform" db:"platforms"`
|
||||
|
||||
CalendarEventsEnabled bool `json:"calendar_events_enabled" db:"calendar_events_enabled"`
|
||||
|
||||
UpdateCreateTimestamps
|
||||
}
|
||||
|
||||
@ -212,6 +218,8 @@ type PolicySpec struct {
|
||||
//
|
||||
// Empty string targets all platforms.
|
||||
Platform string `json:"platform,omitempty"`
|
||||
// CalendarEventsEnabled indicates whether calendar events are enabled for the policy. Only applies to team policies.
|
||||
CalendarEventsEnabled bool `json:"calendar_events_enabled"`
|
||||
}
|
||||
|
||||
// Verify verifies the policy data is valid.
|
||||
|
@ -451,6 +451,11 @@ func TeamSpecFromTeam(t *Team) (*TeamSpec, error) {
|
||||
webhookSettings.HostStatusWebhook = t.Config.WebhookSettings.HostStatusWebhook
|
||||
}
|
||||
|
||||
var integrations TeamSpecIntegrations
|
||||
if t.Config.Integrations.GoogleCalendar != nil {
|
||||
integrations.GoogleCalendar = t.Config.Integrations.GoogleCalendar
|
||||
}
|
||||
|
||||
return &TeamSpec{
|
||||
Name: t.Name,
|
||||
AgentOptions: agentOptions,
|
||||
@ -459,5 +464,6 @@ func TeamSpecFromTeam(t *Team) (*TeamSpec, error) {
|
||||
MDM: mdmSpec,
|
||||
HostExpirySettings: &t.Config.HostExpirySettings,
|
||||
WebhookSettings: webhookSettings,
|
||||
Integrations: integrations,
|
||||
}, nil
|
||||
}
|
||||
|
@ -432,8 +432,6 @@ type ListGlobalPoliciesFunc func(ctx context.Context, opts fleet.ListOptions) ([
|
||||
|
||||
type PoliciesByIDFunc func(ctx context.Context, ids []uint) (map[uint]*fleet.Policy, error)
|
||||
|
||||
type PoliciesByNameFunc func(ctx context.Context, names []string, teamID uint) (map[string]*fleet.Policy, error)
|
||||
|
||||
type DeleteGlobalPoliciesFunc func(ctx context.Context, ids []uint) ([]uint, error)
|
||||
|
||||
type CountPoliciesFunc func(ctx context.Context, teamID *uint, matchQuery string) (int, error)
|
||||
@ -1482,9 +1480,6 @@ type DataStore struct {
|
||||
PoliciesByIDFunc PoliciesByIDFunc
|
||||
PoliciesByIDFuncInvoked bool
|
||||
|
||||
PoliciesByNameFunc PoliciesByNameFunc
|
||||
PoliciesByNameFuncInvoked bool
|
||||
|
||||
DeleteGlobalPoliciesFunc DeleteGlobalPoliciesFunc
|
||||
DeleteGlobalPoliciesFuncInvoked bool
|
||||
|
||||
@ -3576,13 +3571,6 @@ func (s *DataStore) PoliciesByID(ctx context.Context, ids []uint) (map[uint]*fle
|
||||
return s.PoliciesByIDFunc(ctx, ids)
|
||||
}
|
||||
|
||||
func (s *DataStore) PoliciesByName(ctx context.Context, names []string, teamID uint) (map[string]*fleet.Policy, error) {
|
||||
s.mu.Lock()
|
||||
s.PoliciesByNameFuncInvoked = true
|
||||
s.mu.Unlock()
|
||||
return s.PoliciesByNameFunc(ctx, names, teamID)
|
||||
}
|
||||
|
||||
func (s *DataStore) DeleteGlobalPolicies(ctx context.Context, ids []uint) ([]uint, error) {
|
||||
s.mu.Lock()
|
||||
s.DeleteGlobalPoliciesFuncInvoked = true
|
||||
|
@ -880,7 +880,6 @@ func (c *Client) DoGitOps(
|
||||
}
|
||||
var mdmAppConfig map[string]interface{}
|
||||
var team map[string]interface{}
|
||||
var teamCalendarIntegration map[string]interface{}
|
||||
if config.TeamName == nil {
|
||||
group.AppConfig = config.OrgSettings
|
||||
group.EnrollSecret = &fleet.EnrollSecretSpec{Secrets: config.OrgSettings["secrets"].([]*fleet.EnrollSecret)}
|
||||
@ -968,20 +967,14 @@ func (c *Client) DoGitOps(
|
||||
if !ok {
|
||||
return errors.New("team_settings.integrations config is not a map")
|
||||
}
|
||||
if calendar, ok := integrations.(map[string]interface{})["google_calendar"]; ok {
|
||||
if calendar == nil {
|
||||
calendar = map[string]interface{}{}
|
||||
integrations.(map[string]interface{})["google_calendar"] = calendar
|
||||
}
|
||||
teamCalendarIntegration, ok = calendar.(map[string]interface{})
|
||||
if googleCal, ok := integrations.(map[string]interface{})["google_calendar"]; !ok || googleCal == nil {
|
||||
integrations.(map[string]interface{})["google_calendar"] = map[string]interface{}{}
|
||||
} else {
|
||||
_, ok = googleCal.(map[string]interface{})
|
||||
if !ok {
|
||||
return errors.New("team_settings.integrations.google_calendar config is not a map")
|
||||
}
|
||||
}
|
||||
// We clear the calendar integration and re-apply it after updating policies.
|
||||
// This is needed because the calendar integration may be referencing policies that need to be
|
||||
// created/updated.
|
||||
integrations.(map[string]interface{})["google_calendar"] = map[string]interface{}{}
|
||||
|
||||
team["mdm"] = map[string]interface{}{}
|
||||
mdmAppConfig = team["mdm"].(map[string]interface{})
|
||||
@ -1087,23 +1080,6 @@ func (c *Client) DoGitOps(
|
||||
return err
|
||||
}
|
||||
|
||||
// Apply calendar integration
|
||||
if len(teamCalendarIntegration) > 0 {
|
||||
group = spec.Group{}
|
||||
team = make(map[string]interface{})
|
||||
team["name"] = *config.TeamName
|
||||
team["integrations"] = map[string]interface{}{"google_calendar": teamCalendarIntegration}
|
||||
rawTeam, err := json.Marshal(team)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error marshalling team spec: %w", err)
|
||||
}
|
||||
group.Teams = []json.RawMessage{rawTeam}
|
||||
_, err = c.ApplyGroup(ctx, &group, baseDir, logf, fleet.ApplySpecOptions{DryRun: dryRun})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = c.doGitOpsQueries(config, logFn, dryRun)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -199,12 +199,7 @@ func (s *integrationEnterpriseTestSuite) TestTeamSpecs() {
|
||||
"google_calendar": map[string]any{
|
||||
"email": calendarEmail,
|
||||
"enable_calendar_events": true,
|
||||
"policies": []any{
|
||||
map[string]any{
|
||||
"name": teamPolicy.Name,
|
||||
},
|
||||
},
|
||||
"webhook_url": calendarWebhookUrl,
|
||||
"webhook_url": calendarWebhookUrl,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -218,8 +213,6 @@ func (s *integrationEnterpriseTestSuite) TestTeamSpecs() {
|
||||
assert.Equal(t, calendarEmail, team.Config.Integrations.GoogleCalendar.Email)
|
||||
assert.Equal(t, calendarWebhookUrl, team.Config.Integrations.GoogleCalendar.WebhookURL)
|
||||
assert.True(t, team.Config.Integrations.GoogleCalendar.Enable)
|
||||
require.Len(t, team.Config.Integrations.GoogleCalendar.Policies, 1)
|
||||
assert.Equal(t, teamPolicy.ID, team.Config.Integrations.GoogleCalendar.Policies[0].ID)
|
||||
|
||||
// dry-run with invalid windows updates
|
||||
teamSpecs = map[string]any{
|
||||
@ -3686,7 +3679,7 @@ func (s *integrationEnterpriseTestSuite) TestGlobalPolicyCreateReadPatch() {
|
||||
}
|
||||
|
||||
func (s *integrationEnterpriseTestSuite) TestTeamPolicyCreateReadPatch() {
|
||||
fields := []string{"Query", "Name", "Description", "Resolution", "Platform", "Critical"}
|
||||
fields := []string{"Query", "Name", "Description", "Resolution", "Platform", "Critical", "CalendarEventsEnabled"}
|
||||
|
||||
team1, err := s.ds.NewTeam(context.Background(), &fleet.Team{
|
||||
ID: 42,
|
||||
@ -3697,24 +3690,26 @@ func (s *integrationEnterpriseTestSuite) TestTeamPolicyCreateReadPatch() {
|
||||
|
||||
createPol1 := &teamPolicyResponse{}
|
||||
createPol1Req := &teamPolicyRequest{
|
||||
Query: "query",
|
||||
Name: "name1",
|
||||
Description: "description",
|
||||
Resolution: "resolution",
|
||||
Platform: "linux",
|
||||
Critical: true,
|
||||
Query: "query",
|
||||
Name: "name1",
|
||||
Description: "description",
|
||||
Resolution: "resolution",
|
||||
Platform: "linux",
|
||||
Critical: true,
|
||||
CalendarEventsEnabled: true,
|
||||
}
|
||||
s.DoJSON("POST", fmt.Sprintf("/api/latest/fleet/teams/%d/policies", team1.ID), createPol1Req, http.StatusOK, &createPol1)
|
||||
allEqual(s.T(), createPol1Req, createPol1.Policy, fields...)
|
||||
|
||||
createPol2 := &teamPolicyResponse{}
|
||||
createPol2Req := &teamPolicyRequest{
|
||||
Query: "query",
|
||||
Name: "name2",
|
||||
Description: "description",
|
||||
Resolution: "resolution",
|
||||
Platform: "linux",
|
||||
Critical: false,
|
||||
Query: "query",
|
||||
Name: "name2",
|
||||
Description: "description",
|
||||
Resolution: "resolution",
|
||||
Platform: "linux",
|
||||
Critical: false,
|
||||
CalendarEventsEnabled: false,
|
||||
}
|
||||
s.DoJSON("POST", fmt.Sprintf("/api/latest/fleet/teams/%d/policies", team1.ID), createPol2Req, http.StatusOK, &createPol2)
|
||||
allEqual(s.T(), createPol2Req, createPol2.Policy, fields...)
|
||||
@ -3730,12 +3725,13 @@ func (s *integrationEnterpriseTestSuite) TestTeamPolicyCreateReadPatch() {
|
||||
|
||||
patchPol1Req := &modifyTeamPolicyRequest{
|
||||
ModifyPolicyPayload: fleet.ModifyPolicyPayload{
|
||||
Name: ptr.String("newName1"),
|
||||
Query: ptr.String("newQuery"),
|
||||
Description: ptr.String("newDescription"),
|
||||
Resolution: ptr.String("newResolution"),
|
||||
Platform: ptr.String("windows"),
|
||||
Critical: ptr.Bool(false),
|
||||
Name: ptr.String("newName1"),
|
||||
Query: ptr.String("newQuery"),
|
||||
Description: ptr.String("newDescription"),
|
||||
Resolution: ptr.String("newResolution"),
|
||||
Platform: ptr.String("windows"),
|
||||
Critical: ptr.Bool(false),
|
||||
CalendarEventsEnabled: ptr.Bool(false),
|
||||
},
|
||||
}
|
||||
patchPol1 := &modifyTeamPolicyResponse{}
|
||||
@ -3744,12 +3740,13 @@ func (s *integrationEnterpriseTestSuite) TestTeamPolicyCreateReadPatch() {
|
||||
|
||||
patchPol2Req := &modifyTeamPolicyRequest{
|
||||
ModifyPolicyPayload: fleet.ModifyPolicyPayload{
|
||||
Name: ptr.String("newName2"),
|
||||
Query: ptr.String("newQuery"),
|
||||
Description: ptr.String("newDescription"),
|
||||
Resolution: ptr.String("newResolution"),
|
||||
Platform: ptr.String("windows"),
|
||||
Critical: ptr.Bool(true),
|
||||
Name: ptr.String("newName2"),
|
||||
Query: ptr.String("newQuery"),
|
||||
Description: ptr.String("newDescription"),
|
||||
Resolution: ptr.String("newResolution"),
|
||||
Platform: ptr.String("windows"),
|
||||
Critical: ptr.Bool(true),
|
||||
CalendarEventsEnabled: ptr.Bool(true),
|
||||
},
|
||||
}
|
||||
patchPol2 := &modifyTeamPolicyResponse{}
|
||||
|
@ -20,14 +20,15 @@ import (
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
type teamPolicyRequest struct {
|
||||
TeamID uint `url:"team_id"`
|
||||
QueryID *uint `json:"query_id"`
|
||||
Query string `json:"query"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Resolution string `json:"resolution"`
|
||||
Platform string `json:"platform"`
|
||||
Critical bool `json:"critical" premium:"true"`
|
||||
TeamID uint `url:"team_id"`
|
||||
QueryID *uint `json:"query_id"`
|
||||
Query string `json:"query"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Resolution string `json:"resolution"`
|
||||
Platform string `json:"platform"`
|
||||
Critical bool `json:"critical" premium:"true"`
|
||||
CalendarEventsEnabled bool `json:"calendar_events_enabled"`
|
||||
}
|
||||
|
||||
type teamPolicyResponse struct {
|
||||
@ -40,13 +41,14 @@ func (r teamPolicyResponse) error() error { return r.Err }
|
||||
func teamPolicyEndpoint(ctx context.Context, request interface{}, svc fleet.Service) (errorer, error) {
|
||||
req := request.(*teamPolicyRequest)
|
||||
resp, err := svc.NewTeamPolicy(ctx, req.TeamID, fleet.PolicyPayload{
|
||||
QueryID: req.QueryID,
|
||||
Name: req.Name,
|
||||
Query: req.Query,
|
||||
Description: req.Description,
|
||||
Resolution: req.Resolution,
|
||||
Platform: req.Platform,
|
||||
Critical: req.Critical,
|
||||
QueryID: req.QueryID,
|
||||
Name: req.Name,
|
||||
Query: req.Query,
|
||||
Description: req.Description,
|
||||
Resolution: req.Resolution,
|
||||
Platform: req.Platform,
|
||||
Critical: req.Critical,
|
||||
CalendarEventsEnabled: req.CalendarEventsEnabled,
|
||||
})
|
||||
if err != nil {
|
||||
return teamPolicyResponse{Err: err}, nil
|
||||
@ -390,6 +392,9 @@ func (svc *Service) modifyPolicy(ctx context.Context, teamID *uint, id uint, p f
|
||||
if p.Critical != nil {
|
||||
policy.Critical = *p.Critical
|
||||
}
|
||||
if p.CalendarEventsEnabled != nil {
|
||||
policy.CalendarEventsEnabled = *p.CalendarEventsEnabled
|
||||
}
|
||||
logging.WithExtras(ctx, "name", policy.Name, "sql", policy.Query)
|
||||
|
||||
err = svc.ds.SavePolicy(ctx, policy, shouldRemoveAll)
|
||||
|
@ -124,7 +124,8 @@ func TestTriggerFailingPoliciesWebhookBasic(t *testing.T) {
|
||||
"passing_host_count": 0,
|
||||
"failing_host_count": 0,
|
||||
"host_count_updated_at": null,
|
||||
"critical": true
|
||||
"critical": true,
|
||||
"calendar_events_enabled": false
|
||||
},
|
||||
"hosts": [
|
||||
{
|
||||
@ -183,16 +184,17 @@ func TestTriggerFailingPoliciesWebhookTeam(t *testing.T) {
|
||||
policiesByID := map[uint]*fleet.Policy{
|
||||
1: {
|
||||
PolicyData: fleet.PolicyData{
|
||||
ID: 1,
|
||||
Name: "policy1",
|
||||
Query: "select 1",
|
||||
Description: "policy1 description",
|
||||
AuthorID: ptr.Uint(1),
|
||||
AuthorName: "Alice",
|
||||
AuthorEmail: "alice@example.com",
|
||||
TeamID: &teamID,
|
||||
Resolution: ptr.String("policy1 resolution"),
|
||||
Platform: "darwin",
|
||||
ID: 1,
|
||||
Name: "policy1",
|
||||
Query: "select 1",
|
||||
Description: "policy1 description",
|
||||
AuthorID: ptr.Uint(1),
|
||||
AuthorName: "Alice",
|
||||
AuthorEmail: "alice@example.com",
|
||||
TeamID: &teamID,
|
||||
Resolution: ptr.String("policy1 resolution"),
|
||||
Platform: "darwin",
|
||||
CalendarEventsEnabled: true,
|
||||
},
|
||||
},
|
||||
2: {
|
||||
@ -309,7 +311,8 @@ func TestTriggerFailingPoliciesWebhookTeam(t *testing.T) {
|
||||
"passing_host_count": 0,
|
||||
"failing_host_count": 0,
|
||||
"host_count_updated_at": null,
|
||||
"critical": false
|
||||
"critical": false,
|
||||
"calendar_events_enabled": true
|
||||
},
|
||||
"hosts": [
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user