Fix conflicts

This commit is contained in:
Martin Angers
2024-03-05 08:11:28 -05:00
354 changed files with 11619 additions and 3218 deletions
+54
View File
@@ -385,6 +385,60 @@ spec:
assert.Equal(t, newMDMSettings, teamsByName["team1"].Config.MDM)
// enroll secret not cleared since not provided
assert.Equal(t, []*fleet.EnrollSecret{{Secret: "BBB"}}, enrolledSecretsCalled[uint(42)])
// Apply team host_status_webhook
filename = writeTmpYml(
t, `
apiVersion: v1
kind: team
spec:
team:
name: team1
webhook_settings:
host_status_webhook:
days_count: 14
destination_url: https://example.com
enable_host_status_webhook: true
host_percentage: 25
`,
)
require.Equal(t, "[+] applied 1 teams\n", runAppForTest(t, []string{"apply", "-f", filename}))
// Ensure the webhook settings are applied
assert.Equal(
t, fleet.HostStatusWebhookSettings{
DaysCount: 14,
DestinationURL: "https://example.com",
Enable: true,
HostPercentage: 25,
}, teamsByName["team1"].Config.WebhookSettings.HostStatusWebhook,
)
assert.Equal(t, fleet.FailingPoliciesWebhookSettings{}, teamsByName["team1"].Config.WebhookSettings.FailingPoliciesWebhook)
// enroll secret not cleared since not provided
assert.Equal(t, []*fleet.EnrollSecret{{Secret: "BBB"}}, enrolledSecretsCalled[uint(42)])
// Apply empty webhook settings
filename = writeTmpYml(
t, `
apiVersion: v1
kind: team
spec:
team:
name: team1
webhook_settings:
`,
)
require.Equal(t, "[+] applied 1 teams\n", runAppForTest(t, []string{"apply", "-f", filename}))
// Ensure the webhook settings have not changed
assert.Equal(
t, fleet.HostStatusWebhookSettings{
DaysCount: 14,
DestinationURL: "https://example.com",
Enable: true,
HostPercentage: 25,
}, teamsByName["team1"].Config.WebhookSettings.HostStatusWebhook,
)
}
func writeTmpYml(t *testing.T, contents string) string {
+1 -1
View File
@@ -360,7 +360,7 @@ func TestGetHosts(t *testing.T) {
}, nil
}
ds.GetHostLockWipeStatusFunc = func(ctx context.Context, hostID uint, fleetPlatform string) (*fleet.HostLockWipeStatus, error) {
ds.GetHostLockWipeStatusFunc = func(ctx context.Context, host *fleet.Host) (*fleet.HostLockWipeStatus, error) {
return &fleet.HostLockWipeStatus{}, nil
}
+35
View File
@@ -514,4 +514,39 @@ func TestFullTeamGitOps(t *testing.T) {
assert.Len(t, appliedScripts, 1)
assert.Len(t, appliedMacProfiles, 1)
assert.Len(t, appliedWinProfiles, 1)
assert.True(t, savedTeam.Config.WebhookSettings.HostStatusWebhook.Enable)
assert.Equal(t, "https://example.com/host_status_webhook", savedTeam.Config.WebhookSettings.HostStatusWebhook.DestinationURL)
// Now clear the settings
tmpFile, err := os.CreateTemp(t.TempDir(), "*.yml")
require.NoError(t, err)
secret := "TestSecret"
t.Setenv("TEST_SECRET", secret)
_, err = tmpFile.WriteString(
`
controls:
queries:
policies:
agent_options:
name: ${TEST_TEAM_NAME}
team_settings:
secrets: [{"secret":"${TEST_SECRET}"}]
`,
)
require.NoError(t, err)
// Dry run
savedTeam = nil
_ = runAppForTest(t, []string{"gitops", "-f", tmpFile.Name(), "--dry-run"})
assert.Nil(t, savedTeam)
// Real run
_ = runAppForTest(t, []string{"gitops", "-f", tmpFile.Name()})
require.NotNil(t, savedTeam)
assert.Equal(t, teamName, savedTeam.Name)
require.Len(t, enrolledSecrets, 1)
assert.Equal(t, secret, enrolledSecrets[0].Secret)
assert.False(t, savedTeam.Config.WebhookSettings.HostStatusWebhook.Enable)
assert.Equal(t, "", savedTeam.Config.WebhookSettings.HostStatusWebhook.DestinationURL)
}
+88 -56
View File
@@ -27,6 +27,7 @@ func mdmCommand() *cli.Command {
mdmRunCommand(),
mdmLockCommand(),
mdmUnlockCommand(),
mdmWipeCommand(),
},
}
}
@@ -179,38 +180,11 @@ func mdmLockCommand() *cli.Command {
Action: func(c *cli.Context) error {
hostIdent := c.String("host")
if len(hostIdent) == 0 {
return errors.New("No host targeted. Please provide --host.")
}
client, err := clientFromCLI(c)
client, host, err := hostMdmActionSetup(c, hostIdent, "lock")
if err != nil {
return fmt.Errorf("create client: %w", err)
}
host, err := client.HostByIdentifier(hostIdent)
if err != nil {
var nfe service.NotFoundErr
if errors.As(err, &nfe) {
return errors.New("The host doesn't exist. Please provide a valid host identifier.")
}
var sce kithttp.StatusCoder
if errors.As(err, &sce) {
if sce.StatusCode() == http.StatusForbidden {
return errors.New("Permission denied. You don't have permission to lock this host.")
}
}
return err
}
if host.Platform == "windows" || host.Platform == "darwin" {
if host.MDM.EnrollmentStatus == nil || !strings.HasPrefix(*host.MDM.EnrollmentStatus, "On") ||
host.MDM.Name != fleet.WellKnownMDMFleet {
return errors.New(`Can't lock the host because it doesn't have MDM turned on.`)
}
}
if err := client.MDMLockHost(host.ID); err != nil {
return fmt.Errorf("Failed to lock host: %w", err)
}
@@ -245,38 +219,11 @@ func mdmUnlockCommand() *cli.Command {
Action: func(c *cli.Context) error {
hostIdent := c.String("host")
if len(hostIdent) == 0 {
return errors.New("No host targeted. Please provide --host.")
}
client, err := clientFromCLI(c)
client, host, err := hostMdmActionSetup(c, hostIdent, "unlock")
if err != nil {
return fmt.Errorf("create client: %w", err)
}
host, err := client.HostByIdentifier(hostIdent)
if err != nil {
var nfe service.NotFoundErr
if errors.As(err, &nfe) {
return errors.New("The host doesn't exist. Please provide a valid host identifier.")
}
var sce kithttp.StatusCoder
if errors.As(err, &sce) {
if sce.StatusCode() == http.StatusForbidden {
return errors.New("Permission denied. You don't have permission to unlock this host.")
}
}
return err
}
if host.Platform == "windows" || host.Platform == "darwin" {
if host.MDM.EnrollmentStatus == nil || !strings.HasPrefix(*host.MDM.EnrollmentStatus, "On") ||
host.MDM.Name != fleet.WellKnownMDMFleet {
return errors.New(`Can't unlock the host because it doesn't have MDM turned on.`)
}
}
pin, err := client.MDMUnlockHost(host.ID)
if err != nil {
return fmt.Errorf("Failed to unlock host: %w", err)
@@ -306,3 +253,88 @@ fleetctl get host %s
},
}
}
// create a mdm command to wipe the device
func mdmWipeCommand() *cli.Command {
return &cli.Command{
Name: "wipe",
Usage: "Wipe a host to erase all content on a workstation.",
Flags: []cli.Flag{contextFlag(), debugFlag(), &cli.StringFlag{
Name: "host",
Usage: "The host, specified by identifier, that you want to wipe.",
Required: true,
}},
Action: func(c *cli.Context) error {
hostIdent := c.String("host")
client, host, err := hostMdmActionSetup(c, hostIdent, "wipe")
if err != nil {
return err
}
config, err := client.GetAppConfig()
if err != nil {
return err
}
// linux hosts need scripts to be enabled in the org settings to wipe.
if host.Platform == "linux" && config.ServerSettings.ScriptsDisabled {
return errors.New("Can't wipe host because running scripts is disabled in organization settings.")
}
if err := client.MDMWipeHost(host.ID); err != nil {
return fmt.Errorf("Failed to wipe host: %w", err)
}
fmt.Fprintf(c.App.Writer, `
The host will wipe when it comes online.
Copy and run this command to see results:
fleetctl get host %s`, hostIdent)
return nil
},
}
}
// Does some common setup for the host mdm actions such as validating the host,
// creating the client, getting the desired host, checking permissions, and
// ensuring MDM is turned on for the host.
func hostMdmActionSetup(c *cli.Context, hostIdent string, actionType string) (client *service.Client, host *service.HostDetailResponse, err error) {
if len(hostIdent) == 0 {
return nil, nil, errors.New("No host targeted. Please provide --host.")
}
client, err = clientFromCLI(c)
if err != nil {
return nil, nil, fmt.Errorf("create client: %w", err)
}
host, err = client.HostByIdentifier(hostIdent)
if err != nil {
var nfe service.NotFoundErr
if errors.As(err, &nfe) {
fmt.Println(hostIdent)
return nil, nil, errors.New("The host doesn't exist. Please provide a valid host identifier.")
}
var sce kithttp.StatusCoder
if errors.As(err, &sce) {
if sce.StatusCode() == http.StatusForbidden {
return nil, nil, fmt.Errorf("Permission denied. You don't have permission to %s this host.", actionType)
}
}
return nil, nil, err
}
// check mdm is on for the host
if host.Platform == "windows" || host.Platform == "darwin" {
if host.MDM.EnrollmentStatus == nil || !strings.HasPrefix(*host.MDM.EnrollmentStatus, "On") ||
host.MDM.Name != fleet.WellKnownMDMFleet {
return nil, nil, fmt.Errorf("Can't %s the host because it doesn't have MDM turned on.", actionType)
}
}
return client, host, nil
}
+504 -178
View File
@@ -196,7 +196,7 @@ func TestMDMRunCommand(t *testing.T) {
ds.GetHostMDMMacOSSetupFunc = func(ctx context.Context, hostID uint) (*fleet.HostMDMMacOSSetup, error) {
return nil, nil
}
ds.GetHostLockWipeStatusFunc = func(ctx context.Context, hostID uint, fleetPlatform string) (*fleet.HostLockWipeStatus, error) {
ds.GetHostLockWipeStatusFunc = func(ctx context.Context, host *fleet.Host) (*fleet.HostLockWipeStatus, error) {
return &fleet.HostLockWipeStatus{}, nil
}
ds.ListHostsLiteByUUIDsFunc = func(ctx context.Context, filter fleet.TeamFilter, uuids []string) ([]*fleet.Host, error) {
@@ -370,6 +370,21 @@ func TestMDMLockCommand(t *testing.T) {
MDMInfo: &fleet.HostMDM{Enrolled: true, Name: fleet.WellKnownMDMFleet},
MDM: fleet.MDMHostData{Name: fleet.WellKnownMDMFleet, EnrollmentStatus: ptr.String("On (manual)")},
}
winEnrolledWP := &fleet.Host{
ID: 12,
UUID: "win-enrolled-wp",
Platform: "windows",
MDMInfo: &fleet.HostMDM{Enrolled: true, Name: fleet.WellKnownMDMFleet},
MDM: fleet.MDMHostData{Name: fleet.WellKnownMDMFleet, EnrollmentStatus: ptr.String("On (manual)")},
}
macEnrolledWP := &fleet.Host{
ID: 13,
UUID: "mac-enrolled-wp",
Platform: "darwin",
MDMInfo: &fleet.HostMDM{Enrolled: true, Name: fleet.WellKnownMDMFleet},
MDM: fleet.MDMHostData{Name: fleet.WellKnownMDMFleet, EnrollmentStatus: ptr.String("On (manual)")},
}
hostByUUID := make(map[string]*fleet.Host)
hostsByID := make(map[uint]*fleet.Host)
for _, h := range []*fleet.Host{
@@ -384,6 +399,8 @@ func TestMDMLockCommand(t *testing.T) {
macEnrolledUP,
winEnrolledLP,
macEnrolledLP,
winEnrolledWP,
macEnrolledWP,
} {
hostByUUID[h.UUID] = h
hostsByID[h.ID] = h
@@ -393,58 +410,28 @@ func TestMDMLockCommand(t *testing.T) {
winEnrolledUP.ID: winEnrolledUP,
macEnrolledUP.ID: macEnrolledUP,
}
lockPending := map[uint]*fleet.Host{
winEnrolledLP.ID: winEnrolledLP,
macEnrolledLP.ID: macEnrolledLP,
}
enqueuer := new(mock.MDMAppleStore)
license := &fleet.LicenseInfo{Tier: fleet.TierPremium, Expiration: time.Now().Add(24 * time.Hour)}
wipePending := map[uint]*fleet.Host{
winEnrolledWP.ID: winEnrolledWP,
macEnrolledWP.ID: macEnrolledWP,
}
_, ds := runServerWithMockedDS(t, &service.TestServerOpts{
MDMStorage: enqueuer,
MDMPusher: mockPusher{},
License: license,
NoCacheDatastore: true,
})
ds := setupTestServer(t)
setupDSMocks(ds, hostByUUID, hostsByID)
// custom ds mocks for these tests
ds.GetHostLockWipeStatusFunc = func(ctx context.Context, host *fleet.Host) (*fleet.HostLockWipeStatus, error) {
fleetPlatform := host.FleetPlatform()
// Mock datastore funcs
ds.HostByIdentifierFunc = func(ctx context.Context, identifier string) (*fleet.Host, error) {
h, ok := hostByUUID[identifier]
if !ok {
return nil, &notFoundError{}
}
return h, nil
}
ds.LoadHostSoftwareFunc = func(ctx context.Context, host *fleet.Host, includeCVEScores bool) error {
return nil
}
ds.ListPacksForHostFunc = func(ctx context.Context, hid uint) (packs []*fleet.Pack, err error) {
return nil, nil
}
ds.ListHostBatteriesFunc = func(ctx context.Context, id uint) ([]*fleet.HostBattery, error) {
return nil, nil
}
ds.ListPoliciesForHostFunc = func(ctx context.Context, host *fleet.Host) ([]*fleet.HostPolicy, error) {
return nil, nil
}
ds.ListLabelsForHostFunc = func(ctx context.Context, hid uint) ([]*fleet.Label, error) {
return nil, nil
}
ds.GetHostMDMAppleProfilesFunc = func(ctx context.Context, hostUUID string) ([]fleet.HostMDMAppleProfile, error) {
return nil, nil
}
ds.GetHostMDMWindowsProfilesFunc = func(ctx context.Context, hostUUID string) ([]fleet.HostMDMWindowsProfile, error) {
return nil, nil
}
ds.GetHostMDMMacOSSetupFunc = func(ctx context.Context, hostID uint) (*fleet.HostMDMMacOSSetup, error) {
return nil, nil
}
ds.GetHostLockWipeStatusFunc = func(ctx context.Context, hostID uint, fleetPlatform string) (*fleet.HostLockWipeStatus, error) {
var status fleet.HostLockWipeStatus
status.HostFleetPlatform = fleetPlatform
if _, ok := unlockPending[hostID]; ok {
if _, ok := unlockPending[host.ID]; ok {
if fleetPlatform == "darwin" {
status.UnlockPIN = "1234"
status.UnlockRequestedAt = time.Now()
@@ -454,7 +441,7 @@ func TestMDMLockCommand(t *testing.T) {
status.UnlockScript = &fleet.HostScriptResult{}
}
if _, ok := lockPending[hostID]; ok {
if _, ok := lockPending[host.ID]; ok {
if fleetPlatform == "darwin" {
status.LockMDMCommand = &fleet.MDMCommand{}
return &status, nil
@@ -463,38 +450,24 @@ func TestMDMLockCommand(t *testing.T) {
status.LockScript = &fleet.HostScriptResult{}
}
if _, ok := wipePending[host.ID]; ok {
if fleetPlatform == "linux" {
status.WipeScript = &fleet.HostScriptResult{ExitCode: nil}
return &status, nil
}
status.WipeMDMCommand = &fleet.MDMCommand{}
status.WipeMDMCommandResult = nil
return &status, nil
}
return &status, nil
}
ds.LockHostViaScriptFunc = func(ctx context.Context, request *fleet.HostScriptRequestPayload) error {
return nil
}
ds.HostLiteFunc = func(ctx context.Context, hostID uint) (*fleet.Host, error) {
h, ok := hostsByID[hostID]
if !ok {
return nil, &notFoundError{}
}
return h, nil
}
ds.GetMDMWindowsBitLockerStatusFunc = func(ctx context.Context, host *fleet.Host) (*fleet.HostMDMDiskEncryption, error) {
return nil, nil
}
ds.GetHostMDMFunc = func(ctx context.Context, hostID uint) (*fleet.HostMDM, error) {
h, ok := hostsByID[hostID]
if !ok {
return nil, &notFoundError{}
}
return h.MDMInfo, nil
}
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
ds.LockHostViaScriptFunc = func(ctx context.Context, request *fleet.HostScriptRequestPayload, platform string) error {
return nil
}
appCfgAllMDM := &fleet.AppConfig{MDM: fleet.MDM{EnabledAndConfigured: true, WindowsEnabledAndConfigured: true}}
appCfgWinMDM := &fleet.AppConfig{MDM: fleet.MDM{WindowsEnabledAndConfigured: true}}
appCfgMacMDM := &fleet.AppConfig{MDM: fleet.MDM{EnabledAndConfigured: true}}
appCfgNoMDM := &fleet.AppConfig{MDM: fleet.MDM{}}
appCfgAllMDM, appCfgWinMDM, appCfgMacMDM, appCfgNoMDM := setupAppConigs()
successfulOutput := func(ident string) string {
return fmt.Sprintf(`
@@ -535,25 +508,11 @@ fleetctl mdm unlock --host=%s
{appCfgAllMDM, "valid macos but pending unlock", []string{"--host", macEnrolledUP.UUID}, "Host has pending unlock request."},
{appCfgAllMDM, "valid windows but pending lock", []string{"--host", winEnrolledLP.UUID}, "Host has pending lock request."},
{appCfgAllMDM, "valid macos but pending lock", []string{"--host", macEnrolledLP.UUID}, "Host has pending lock request."},
// TODO: add test for wipe once implemented
{appCfgAllMDM, "valid windows but pending wipe", []string{"--host", winEnrolledWP.UUID}, "Host has pending wipe request."},
{appCfgAllMDM, "valid macos but pending wipe", []string{"--host", macEnrolledWP.UUID}, "Host has pending wipe request."},
}
for _, c := range cases {
ds.AppConfigFunc = func(ctx context.Context) (*fleet.AppConfig, error) {
return c.appCfg, nil
}
enqueuer.EnqueueDeviceLockCommandFunc = func(ctx context.Context, host *fleet.Host, cmd *mdm.Command, pin string) error {
return nil
}
buf, err := runAppNoChecks(append([]string{"mdm", "lock"}, c.flags...))
if c.wantErr != "" {
require.Error(t, err, c.desc)
require.ErrorContains(t, err, c.wantErr, c.desc)
} else {
require.NoError(t, err, c.desc)
require.Equal(t, buf.String(), successfulOutput(c.flags[1]), c.desc)
}
}
runTestCases(t, ds, "lock", successfulOutput, cases)
}
func TestMDMUnlockCommand(t *testing.T) {
@@ -614,7 +573,6 @@ func TestMDMUnlockCommand(t *testing.T) {
MDMInfo: &fleet.HostMDM{Enrolled: true, Name: fleet.WellKnownMDMFleet},
MDM: fleet.MDMHostData{Name: fleet.WellKnownMDMFleet, EnrollmentStatus: ptr.String("On (manual)")},
}
winEnrolledLP := &fleet.Host{
ID: 10,
UUID: "win-enrolled-lp",
@@ -629,6 +587,20 @@ func TestMDMUnlockCommand(t *testing.T) {
MDMInfo: &fleet.HostMDM{Enrolled: true, Name: fleet.WellKnownMDMFleet},
MDM: fleet.MDMHostData{Name: fleet.WellKnownMDMFleet, EnrollmentStatus: ptr.String("On (manual)")},
}
winEnrolledWP := &fleet.Host{
ID: 12,
UUID: "win-enrolled-wp",
Platform: "windows",
MDMInfo: &fleet.HostMDM{Enrolled: true, Name: fleet.WellKnownMDMFleet},
MDM: fleet.MDMHostData{Name: fleet.WellKnownMDMFleet, EnrollmentStatus: ptr.String("On (manual)")},
}
macEnrolledWP := &fleet.Host{
ID: 13,
UUID: "mac-enrolled-wp",
Platform: "darwin",
MDMInfo: &fleet.HostMDM{Enrolled: true, Name: fleet.WellKnownMDMFleet},
MDM: fleet.MDMHostData{Name: fleet.WellKnownMDMFleet, EnrollmentStatus: ptr.String("On (manual)")},
}
hostByUUID := make(map[string]*fleet.Host)
hostsByID := make(map[uint]*fleet.Host)
@@ -644,6 +616,8 @@ func TestMDMUnlockCommand(t *testing.T) {
macEnrolledUP,
winEnrolledLP,
macEnrolledLP,
winEnrolledWP,
macEnrolledWP,
} {
hostByUUID[h.UUID] = h
hostsByID[h.ID] = h
@@ -664,56 +638,21 @@ func TestMDMUnlockCommand(t *testing.T) {
macEnrolledLP.ID: macEnrolledLP,
}
enqueuer := new(mock.MDMAppleStore)
license := &fleet.LicenseInfo{Tier: fleet.TierPremium, Expiration: time.Now().Add(24 * time.Hour)}
enqueuer.EnqueueDeviceLockCommandFunc = func(ctx context.Context, host *fleet.Host, cmd *mdm.Command, pin string) error {
return nil
wipePending := map[uint]*fleet.Host{
winEnrolledWP.ID: winEnrolledWP,
macEnrolledWP.ID: macEnrolledWP,
}
_, ds := runServerWithMockedDS(t, &service.TestServerOpts{
MDMStorage: enqueuer,
MDMPusher: mockPusher{},
License: license,
NoCacheDatastore: true,
})
ds := setupTestServer(t)
setupDSMocks(ds, hostByUUID, hostsByID)
// custom mocks for these test
ds.GetHostLockWipeStatusFunc = func(ctx context.Context, host *fleet.Host) (*fleet.HostLockWipeStatus, error) {
fleetPlatform := host.FleetPlatform()
// Mock datastore funcs
ds.HostByIdentifierFunc = func(ctx context.Context, identifier string) (*fleet.Host, error) {
h, ok := hostByUUID[identifier]
if !ok {
return nil, &notFoundError{}
}
return h, nil
}
ds.LoadHostSoftwareFunc = func(ctx context.Context, host *fleet.Host, includeCVEScores bool) error {
return nil
}
ds.ListPacksForHostFunc = func(ctx context.Context, hid uint) (packs []*fleet.Pack, err error) {
return nil, nil
}
ds.ListHostBatteriesFunc = func(ctx context.Context, id uint) ([]*fleet.HostBattery, error) {
return nil, nil
}
ds.ListPoliciesForHostFunc = func(ctx context.Context, host *fleet.Host) ([]*fleet.HostPolicy, error) {
return nil, nil
}
ds.ListLabelsForHostFunc = func(ctx context.Context, hid uint) ([]*fleet.Label, error) {
return nil, nil
}
ds.GetHostMDMAppleProfilesFunc = func(ctx context.Context, hostUUID string) ([]fleet.HostMDMAppleProfile, error) {
return nil, nil
}
ds.GetHostMDMWindowsProfilesFunc = func(ctx context.Context, hostUUID string) ([]fleet.HostMDMWindowsProfile, error) {
return nil, nil
}
ds.GetHostMDMMacOSSetupFunc = func(ctx context.Context, hostID uint) (*fleet.HostMDMMacOSSetup, error) {
return nil, nil
}
ds.GetHostLockWipeStatusFunc = func(ctx context.Context, hostID uint, fleetPlatform string) (*fleet.HostLockWipeStatus, error) {
var status fleet.HostLockWipeStatus
status.HostFleetPlatform = fleetPlatform
if _, ok := locked[hostID]; ok {
if _, ok := locked[host.ID]; ok {
if fleetPlatform == "darwin" {
status.LockMDMCommand = &fleet.MDMCommand{}
status.LockMDMCommandResult = &fleet.MDMCommandResult{Status: fleet.MDMAppleStatusAcknowledged}
@@ -723,7 +662,7 @@ func TestMDMUnlockCommand(t *testing.T) {
status.LockScript = &fleet.HostScriptResult{ExitCode: ptr.Int64(0)}
}
if _, ok := unlockPending[hostID]; ok {
if _, ok := unlockPending[host.ID]; ok {
if fleetPlatform == "darwin" {
status.UnlockPIN = "1234"
status.UnlockRequestedAt = time.Now()
@@ -733,7 +672,7 @@ func TestMDMUnlockCommand(t *testing.T) {
status.UnlockScript = &fleet.HostScriptResult{}
}
if _, ok := lockPending[hostID]; ok {
if _, ok := lockPending[host.ID]; ok {
if fleetPlatform == "darwin" {
status.LockMDMCommand = &fleet.MDMCommand{}
return &status, nil
@@ -742,41 +681,27 @@ func TestMDMUnlockCommand(t *testing.T) {
status.LockScript = &fleet.HostScriptResult{}
}
if _, ok := wipePending[host.ID]; ok {
if fleetPlatform == "linux" {
status.WipeScript = &fleet.HostScriptResult{ExitCode: nil}
return &status, nil
}
status.WipeMDMCommand = &fleet.MDMCommand{}
status.WipeMDMCommandResult = nil
return &status, nil
}
return &status, nil
}
ds.UnlockHostViaScriptFunc = func(ctx context.Context, request *fleet.HostScriptRequestPayload) error {
ds.UnlockHostViaScriptFunc = func(ctx context.Context, request *fleet.HostScriptRequestPayload, platform string) error {
return nil
}
ds.UnlockHostManuallyFunc = func(ctx context.Context, hostID uint, ts time.Time) error {
return nil
}
ds.HostLiteFunc = func(ctx context.Context, hostID uint) (*fleet.Host, error) {
h, ok := hostsByID[hostID]
if !ok {
return nil, &notFoundError{}
}
return h, nil
}
ds.GetMDMWindowsBitLockerStatusFunc = func(ctx context.Context, host *fleet.Host) (*fleet.HostMDMDiskEncryption, error) {
return nil, nil
}
ds.GetHostMDMFunc = func(ctx context.Context, hostID uint) (*fleet.HostMDM, error) {
h, ok := hostsByID[hostID]
if !ok {
return nil, &notFoundError{}
}
return h.MDMInfo, nil
}
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
ds.UnlockHostManuallyFunc = func(ctx context.Context, hostID uint, platform string, ts time.Time) error {
return nil
}
appCfgAllMDM := &fleet.AppConfig{MDM: fleet.MDM{EnabledAndConfigured: true, WindowsEnabledAndConfigured: true}}
appCfgWinMDM := &fleet.AppConfig{MDM: fleet.MDM{WindowsEnabledAndConfigured: true}}
appCfgMacMDM := &fleet.AppConfig{MDM: fleet.MDM{EnabledAndConfigured: true}}
appCfgNoMDM := &fleet.AppConfig{MDM: fleet.MDM{}}
appCfgAllMDM, appCfgWinMDM, appCfgMacMDM, appCfgNoMDM := setupAppConigs()
successfulOutput := func(ident string) string {
h := hostByUUID[ident]
@@ -801,7 +726,7 @@ fleetctl get host %s
}{
{appCfgAllMDM, "no flags", nil, `Required flag "host" not set`},
{appCfgAllMDM, "host flag empty", []string{"--host", ""}, `No host targeted. Please provide --host.`},
{appCfgAllMDM, "lock non-existent host", []string{"--host", "notfound"}, `The host doesn't exist. Please provide a valid host identifier.`},
{appCfgAllMDM, "unlock non-existent host", []string{"--host", "notfound"}, `The host doesn't exist. Please provide a valid host identifier.`},
{appCfgMacMDM, "valid windows but only macos mdm", []string{"--host", winEnrolled.UUID}, `Windows MDM isn't turned on.`},
{appCfgAllMDM, "valid windows", []string{"--host", winEnrolled.UUID}, ""},
{appCfgAllMDM, "valid macos", []string{"--host", macEnrolled.UUID}, ""},
@@ -817,22 +742,310 @@ fleetctl get host %s
{appCfgAllMDM, "valid macos but pending unlock", []string{"--host", macEnrolledUP.UUID}, ""},
{appCfgAllMDM, "valid windows but pending lock", []string{"--host", winEnrolledLP.UUID}, "Host has pending lock request."},
{appCfgAllMDM, "valid macos but pending lock", []string{"--host", macEnrolledLP.UUID}, "Host has pending lock request."},
// TODO: add test for wipe once implemented
{appCfgAllMDM, "valid windows but pending wipe", []string{"--host", winEnrolledWP.UUID}, "Host has pending wipe request."},
{appCfgAllMDM, "valid macos but pending wipe", []string{"--host", macEnrolledWP.UUID}, "Host has pending wipe request."},
}
for _, c := range cases {
ds.AppConfigFunc = func(ctx context.Context) (*fleet.AppConfig, error) {
return c.appCfg, nil
}
buf, err := runAppNoChecks(append([]string{"mdm", "unlock"}, c.flags...))
if c.wantErr != "" {
require.Error(t, err, c.desc)
require.ErrorContains(t, err, c.wantErr, c.desc)
} else {
require.NoError(t, err, c.desc)
require.Contains(t, buf.String(), successfulOutput(c.flags[1]), c.desc)
}
runTestCases(t, ds, "unlock", successfulOutput, cases)
}
func TestMDMWipeCommand(t *testing.T) {
macEnrolled := &fleet.Host{
ID: 1,
UUID: "mac-enrolled",
Platform: "darwin",
MDMInfo: &fleet.HostMDM{Enrolled: true, Name: fleet.WellKnownMDMFleet},
MDM: fleet.MDMHostData{Name: fleet.WellKnownMDMFleet, EnrollmentStatus: ptr.String("On (manual)")},
}
winEnrolled := &fleet.Host{
ID: 2,
UUID: "win-enrolled",
Platform: "windows",
MDMInfo: &fleet.HostMDM{Enrolled: true, Name: fleet.WellKnownMDMFleet},
MDM: fleet.MDMHostData{Name: fleet.WellKnownMDMFleet, EnrollmentStatus: ptr.String("On (manual)")},
}
linuxEnrolled := &fleet.Host{
ID: 3,
UUID: "linux-enrolled",
Platform: "linux",
}
winNotEnrolled := &fleet.Host{
ID: 4,
UUID: "win-not-enrolled",
Platform: "windows",
}
macNotEnrolled := &fleet.Host{
ID: 5,
UUID: "mac-not-enrolled",
Platform: "darwin",
}
macPending := &fleet.Host{
ID: 6,
UUID: "mac-pending",
Platform: "darwin",
MDMInfo: &fleet.HostMDM{Enrolled: false, Name: fleet.WellKnownMDMFleet},
MDM: fleet.MDMHostData{Name: fleet.WellKnownMDMFleet, EnrollmentStatus: ptr.String("Pending")},
}
winPending := &fleet.Host{
ID: 7,
UUID: "win-pending",
Platform: "windows",
MDMInfo: &fleet.HostMDM{Enrolled: false, Name: fleet.WellKnownMDMFleet},
MDM: fleet.MDMHostData{Name: fleet.WellKnownMDMFleet, EnrollmentStatus: ptr.String("Pending")},
}
winEnrolledUP := &fleet.Host{
ID: 8,
UUID: "win-enrolled-up",
Platform: "windows",
MDMInfo: &fleet.HostMDM{Enrolled: true, Name: fleet.WellKnownMDMFleet},
MDM: fleet.MDMHostData{Name: fleet.WellKnownMDMFleet, EnrollmentStatus: ptr.String("On (manual)")},
}
macEnrolledUP := &fleet.Host{
ID: 9,
UUID: "mac-enrolled-up",
Platform: "darwin",
MDMInfo: &fleet.HostMDM{Enrolled: true, Name: fleet.WellKnownMDMFleet},
MDM: fleet.MDMHostData{Name: fleet.WellKnownMDMFleet, EnrollmentStatus: ptr.String("On (manual)")},
}
winEnrolledLP := &fleet.Host{
ID: 10,
UUID: "win-enrolled-lp",
Platform: "windows",
MDMInfo: &fleet.HostMDM{Enrolled: true, Name: fleet.WellKnownMDMFleet},
MDM: fleet.MDMHostData{Name: fleet.WellKnownMDMFleet, EnrollmentStatus: ptr.String("On (manual)")},
}
macEnrolledLP := &fleet.Host{
ID: 11,
UUID: "mac-enrolled-lp",
Platform: "darwin",
MDMInfo: &fleet.HostMDM{Enrolled: true, Name: fleet.WellKnownMDMFleet},
MDM: fleet.MDMHostData{Name: fleet.WellKnownMDMFleet, EnrollmentStatus: ptr.String("On (manual)")},
}
winEnrolledWP := &fleet.Host{
ID: 12,
UUID: "win-enrolled-wp",
Platform: "windows",
MDMInfo: &fleet.HostMDM{Enrolled: true, Name: fleet.WellKnownMDMFleet},
MDM: fleet.MDMHostData{Name: fleet.WellKnownMDMFleet, EnrollmentStatus: ptr.String("On (manual)")},
}
macEnrolledWP := &fleet.Host{
ID: 13,
UUID: "mac-enrolled-wp",
Platform: "darwin",
MDMInfo: &fleet.HostMDM{Enrolled: true, Name: fleet.WellKnownMDMFleet},
MDM: fleet.MDMHostData{Name: fleet.WellKnownMDMFleet, EnrollmentStatus: ptr.String("On (manual)")},
}
winEnrolledWiped := &fleet.Host{
ID: 14,
UUID: "win-enrolled-wiped",
Platform: "windows",
MDMInfo: &fleet.HostMDM{Enrolled: true, Name: fleet.WellKnownMDMFleet},
MDM: fleet.MDMHostData{Name: fleet.WellKnownMDMFleet, EnrollmentStatus: ptr.String("On (manual)")},
}
macEnrolledWiped := &fleet.Host{
ID: 15,
UUID: "mac-enrolled-wiped",
Platform: "darwin",
MDMInfo: &fleet.HostMDM{Enrolled: true, Name: fleet.WellKnownMDMFleet},
MDM: fleet.MDMHostData{Name: fleet.WellKnownMDMFleet, EnrollmentStatus: ptr.String("On (manual)")},
}
winEnrolledLocked := &fleet.Host{
ID: 16,
UUID: "win-enrolled-locked",
Platform: "windows",
MDMInfo: &fleet.HostMDM{Enrolled: true, Name: fleet.WellKnownMDMFleet},
MDM: fleet.MDMHostData{Name: fleet.WellKnownMDMFleet, EnrollmentStatus: ptr.String("On (manual")},
}
macEnrolledLocked := &fleet.Host{
ID: 17,
UUID: "mac-enrolled-locked",
Platform: "darwin",
MDMInfo: &fleet.HostMDM{Enrolled: true, Name: fleet.WellKnownMDMFleet},
MDM: fleet.MDMHostData{Name: fleet.WellKnownMDMFleet, EnrollmentStatus: ptr.String("On (manual")},
}
hostByUUID := make(map[string]*fleet.Host)
hostsByID := make(map[uint]*fleet.Host)
for _, h := range []*fleet.Host{
winEnrolled,
macEnrolled,
linuxEnrolled,
macNotEnrolled,
winNotEnrolled,
macPending,
winPending,
winEnrolledUP,
macEnrolledUP,
winEnrolledLP,
macEnrolledLP,
winEnrolledWP,
macEnrolledWP,
winEnrolledWiped,
macEnrolledWiped,
winEnrolledLocked,
macEnrolledLocked,
} {
hostByUUID[h.UUID] = h
hostsByID[h.ID] = h
}
locked := map[uint]*fleet.Host{
winEnrolledLocked.ID: winEnrolledLocked,
macEnrolledLocked.ID: macEnrolledLocked,
}
unlockPending := map[uint]*fleet.Host{
winEnrolledUP.ID: winEnrolledUP,
macEnrolledUP.ID: macEnrolledUP,
}
lockPending := map[uint]*fleet.Host{
winEnrolledLP.ID: winEnrolledLP,
macEnrolledLP.ID: macEnrolledLP,
}
wipePending := map[uint]*fleet.Host{
winEnrolledWP.ID: winEnrolledWP,
macEnrolledWP.ID: macEnrolledWP,
}
wiped := map[uint]*fleet.Host{
winEnrolledWiped.ID: winEnrolledWiped,
macEnrolledWiped.ID: macEnrolledWiped,
}
ds := setupTestServer(t)
setupDSMocks(ds, hostByUUID, hostsByID)
// TODO: custom ds mocks for these tests
ds.GetHostLockWipeStatusFunc = func(ctx context.Context, host *fleet.Host) (*fleet.HostLockWipeStatus, error) {
fleetPlatform := host.FleetPlatform()
var status fleet.HostLockWipeStatus
status.HostFleetPlatform = fleetPlatform
if _, ok := locked[host.ID]; ok {
if fleetPlatform == "darwin" {
status.LockMDMCommand = &fleet.MDMCommand{}
status.LockMDMCommandResult = &fleet.MDMCommandResult{Status: fleet.MDMAppleStatusAcknowledged}
return &status, nil
}
status.LockScript = &fleet.HostScriptResult{ExitCode: ptr.Int64(0)}
}
if _, ok := unlockPending[host.ID]; ok {
if fleetPlatform == "darwin" {
status.UnlockPIN = "1234"
status.UnlockRequestedAt = time.Now()
return &status, nil
}
status.UnlockScript = &fleet.HostScriptResult{}
}
if _, ok := lockPending[host.ID]; ok {
if fleetPlatform == "darwin" {
status.LockMDMCommand = &fleet.MDMCommand{}
return &status, nil
}
status.LockScript = &fleet.HostScriptResult{}
}
if _, ok := wipePending[host.ID]; ok {
if fleetPlatform == "linux" {
status.WipeScript = &fleet.HostScriptResult{ExitCode: nil}
return &status, nil
}
status.WipeMDMCommand = &fleet.MDMCommand{}
status.WipeMDMCommandResult = nil
return &status, nil
}
if _, ok := wiped[host.ID]; ok {
if fleetPlatform == "linux" {
status.WipeScript = &fleet.HostScriptResult{ExitCode: ptr.Int64(0)}
}
if fleetPlatform == "darwin" {
status.WipeMDMCommand = &fleet.MDMCommand{}
status.WipeMDMCommandResult = &fleet.MDMCommandResult{
Status: fleet.MDMAppleStatusAcknowledged,
}
}
if fleetPlatform == "windows" {
status.WipeMDMCommand = &fleet.MDMCommand{}
status.WipeMDMCommandResult = &fleet.MDMCommandResult{
Status: "200",
}
}
return &status, nil
}
return &status, nil
}
ds.UnlockHostViaScriptFunc = func(ctx context.Context, request *fleet.HostScriptRequestPayload, hostFleetPlatform string) error {
return nil
}
ds.UnlockHostManuallyFunc = func(ctx context.Context, hostID uint, hostFleetPlatform string, ts time.Time) error {
return nil
}
ds.WipeHostViaWindowsMDMFunc = func(ctx context.Context, host *fleet.Host, cmd *fleet.MDMWindowsCommand) error {
return nil
}
ds.WipeHostViaScriptFunc = func(ctx context.Context, request *fleet.HostScriptRequestPayload, hostFleetPlatform string) error {
return nil
}
appCfgAllMDM, appCfgWinMDM, appCfgMacMDM, appCfgNoMDM := setupAppConigs()
appCfgScriptsDisabled := &fleet.AppConfig{ServerSettings: fleet.ServerSettings{ScriptsDisabled: true}}
cases := []struct {
appCfg *fleet.AppConfig
desc string
flags []string
wantErr string
}{
{appCfgAllMDM, "no flags", nil, `Required flag "host" not set`},
{appCfgAllMDM, "host flag empty", []string{"--host", ""}, `No host targeted. Please provide --host.`},
{appCfgAllMDM, "wipe non-existent host", []string{"--host", "notfound"}, `The host doesn't exist. Please provide a valid host identifier.`},
{appCfgMacMDM, "valid windows but only macos mdm", []string{"--host", winEnrolled.UUID}, `Windows MDM isn't turned on.`},
{appCfgAllMDM, "valid windows", []string{"--host", winEnrolled.UUID}, ""},
{appCfgAllMDM, "valid macos", []string{"--host", macEnrolled.UUID}, ""},
{appCfgNoMDM, "valid linux", []string{"--host", linuxEnrolled.UUID}, ""},
{appCfgNoMDM, "valid windows but no mdm", []string{"--host", winEnrolled.UUID}, `Windows MDM isn't turned on.`},
{appCfgMacMDM, "valid macos but not enrolled", []string{"--host", macNotEnrolled.UUID}, `Can't wipe the host because it doesn't have MDM turned on.`},
{appCfgWinMDM, "valid windows but not enrolled", []string{"--host", winNotEnrolled.UUID}, `Can't wipe the host because it doesn't have MDM turned on.`},
{appCfgWinMDM, "valid windows but pending mdm enroll", []string{"--host", winPending.UUID}, `Can't wipe the host because it doesn't have MDM turned on.`},
{appCfgMacMDM, "valid macos but pending mdm enroll", []string{"--host", macPending.UUID}, `Can't wipe the host because it doesn't have MDM turned on.`},
{appCfgAllMDM, "valid windows but pending unlock", []string{"--host", winEnrolledUP.UUID}, "Host has pending unlock request."},
{appCfgAllMDM, "valid macos but pending unlock", []string{"--host", macEnrolledUP.UUID}, "Host has pending unlock request."},
{appCfgAllMDM, "valid windows but pending lock", []string{"--host", winEnrolledLP.UUID}, "Host has pending lock request."},
{appCfgAllMDM, "valid macos but pending lock", []string{"--host", macEnrolledLP.UUID}, "Host has pending lock request."},
{appCfgAllMDM, "valid windows but pending wipe", []string{"--host", winEnrolledWP.UUID}, "Host has pending wipe request."},
{appCfgAllMDM, "valid macos but pending wipe", []string{"--host", macEnrolledWP.UUID}, "Host has pending wipe request."},
{appCfgAllMDM, "valid windows but host wiped", []string{"--host", winEnrolledWiped.UUID}, "Host is already wiped."},
{appCfgAllMDM, "valid macos but host wiped", []string{"--host", macEnrolledWiped.UUID}, "Host is already wiped."},
{appCfgAllMDM, "valid windows but host is locked", []string{"--host", winEnrolledLocked.UUID}, "Host cannot be wiped until it is unlocked."},
{appCfgAllMDM, "valid macos but host is locked", []string{"--host", macEnrolledLocked.UUID}, "Host cannot be wiped until it is unlocked."},
{appCfgAllMDM, "valid macos but host is locked", []string{"--host", macEnrolledLocked.UUID}, "Host cannot be wiped until it is unlocked."},
{appCfgScriptsDisabled, "valid linux but script are disabled", []string{"--host", linuxEnrolled.UUID}, "Can't wipe host because running scripts is disabled in organization settings."},
}
successfulOutput := func(ident string) string {
return fmt.Sprintf(`
The host will wipe when it comes online.
Copy and run this command to see results:
fleetctl get host %s`, ident)
}
runTestCases(t, ds, "wipe", successfulOutput, cases)
}
func writeTmpAppleMDMCmd(t *testing.T, commandName string) string {
@@ -882,3 +1095,116 @@ func writeTmpMobileconfig(t *testing.T, name string) string {
require.NoError(t, err)
return tmpFile.Name()
}
// sets up the test server with the mock datastore and returns the mock datastore
func setupTestServer(t *testing.T) *mock.Store {
enqueuer := new(mock.MDMAppleStore)
license := &fleet.LicenseInfo{Tier: fleet.TierPremium, Expiration: time.Now().Add(24 * time.Hour)}
enqueuer.EnqueueDeviceLockCommandFunc = func(ctx context.Context, host *fleet.Host, cmd *mdm.Command, pin string) error {
return nil
}
enqueuer.EnqueueDeviceWipeCommandFunc = func(ctx context.Context, host *fleet.Host, cmd *mdm.Command) error {
return nil
}
_, ds := runServerWithMockedDS(t, &service.TestServerOpts{
MDMStorage: enqueuer,
MDMPusher: mockPusher{},
License: license,
NoCacheDatastore: true,
})
return ds
}
// sets up common data store mocks that are needed for the tests.
func setupDSMocks(ds *mock.Store, hostByUUID map[string]*fleet.Host, hostsByID map[uint]*fleet.Host) {
ds.HostByIdentifierFunc = func(ctx context.Context, identifier string) (*fleet.Host, error) {
h, ok := hostByUUID[identifier]
if !ok {
return nil, &notFoundError{}
}
return h, nil
}
ds.LoadHostSoftwareFunc = func(ctx context.Context, host *fleet.Host, includeCVEScores bool) error {
return nil
}
ds.ListPacksForHostFunc = func(ctx context.Context, hid uint) (packs []*fleet.Pack, err error) {
return nil, nil
}
ds.ListHostBatteriesFunc = func(ctx context.Context, id uint) ([]*fleet.HostBattery, error) {
return nil, nil
}
ds.ListPoliciesForHostFunc = func(ctx context.Context, host *fleet.Host) ([]*fleet.HostPolicy, error) {
return nil, nil
}
ds.ListLabelsForHostFunc = func(ctx context.Context, hid uint) ([]*fleet.Label, error) {
return nil, nil
}
ds.GetHostMDMAppleProfilesFunc = func(ctx context.Context, hostUUID string) ([]fleet.HostMDMAppleProfile, error) {
return nil, nil
}
ds.GetHostMDMWindowsProfilesFunc = func(ctx context.Context, hostUUID string) ([]fleet.HostMDMWindowsProfile, error) {
return nil, nil
}
ds.GetHostMDMMacOSSetupFunc = func(ctx context.Context, hostID uint) (*fleet.HostMDMMacOSSetup, error) {
return nil, nil
}
ds.HostLiteFunc = func(ctx context.Context, hostID uint) (*fleet.Host, error) {
h, ok := hostsByID[hostID]
if !ok {
return nil, &notFoundError{}
}
return h, nil
}
ds.GetMDMWindowsBitLockerStatusFunc = func(ctx context.Context, host *fleet.Host) (*fleet.HostMDMDiskEncryption, error) {
return nil, nil
}
ds.GetHostMDMFunc = func(ctx context.Context, hostID uint) (*fleet.HostMDM, error) {
h, ok := hostsByID[hostID]
if !ok {
return nil, &notFoundError{}
}
return h.MDMInfo, nil
}
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
return nil
}
}
// sets up the various app configs for the tests. These app configs reflect the various
// states of the MDM configuration.
func setupAppConigs() (*fleet.AppConfig, *fleet.AppConfig, *fleet.AppConfig, *fleet.AppConfig) {
appCfgAllMDM := &fleet.AppConfig{MDM: fleet.MDM{EnabledAndConfigured: true, WindowsEnabledAndConfigured: true}}
appCfgWinMDM := &fleet.AppConfig{MDM: fleet.MDM{WindowsEnabledAndConfigured: true}}
appCfgMacMDM := &fleet.AppConfig{MDM: fleet.MDM{EnabledAndConfigured: true}}
appCfgNoMDM := &fleet.AppConfig{MDM: fleet.MDM{}}
return appCfgAllMDM, appCfgWinMDM, appCfgMacMDM, appCfgNoMDM
}
func runTestCases(t *testing.T, ds *mock.Store, actionType string, successfulOutput func(ident string) string, cases []struct {
appCfg *fleet.AppConfig
desc string
flags []string
wantErr string
},
) {
for _, c := range cases {
ds.AppConfigFunc = func(ctx context.Context) (*fleet.AppConfig, error) {
return c.appCfg, nil
}
buf, err := runAppNoChecks(append([]string{"mdm", actionType}, c.flags...))
if c.wantErr != "" {
require.Error(t, err, c.desc)
require.ErrorContains(t, err, c.wantErr, c.desc)
} else {
require.NoError(t, err, c.desc)
require.Contains(t, buf.String(), successfulOutput(c.flags[1]), c.desc)
}
}
}
+1 -1
View File
@@ -240,7 +240,7 @@ Fleet records the last 10,000 characters to prevent downtime.
}
return &fleet.HostScriptResult{}, nil
}
ds.GetHostLockWipeStatusFunc = func(ctx context.Context, hostID uint, fleetPlatform string) (*fleet.HostLockWipeStatus, error) {
ds.GetHostLockWipeStatusFunc = func(ctx context.Context, host *fleet.Host) (*fleet.HostLockWipeStatus, error) {
return &fleet.HostLockWipeStatus{}, nil
}
ds.NewHostScriptExecutionRequestFunc = func(ctx context.Context, req *fleet.HostScriptRequestPayload) (*fleet.HostScriptResult, error) {
+12
View File
@@ -12,6 +12,12 @@
"host_expiry_window": 0
},
"webhook_settings": {
"host_status_webhook": {
"enable_host_status_webhook": false,
"destination_url": "",
"host_percentage": 0,
"days_count": 0
},
"failing_policies_webhook": {
"enable_failing_policies_webhook": false,
"destination_url": "",
@@ -81,6 +87,12 @@
"host_expiry_window": 15
},
"webhook_settings": {
"host_status_webhook": {
"enable_host_status_webhook": false,
"destination_url": "",
"host_percentage": 0,
"days_count": 0
},
"failing_policies_webhook": {
"enable_failing_policies_webhook": false,
"destination_url": "",
+4
View File
@@ -26,6 +26,8 @@ spec:
enable_end_user_authentication: false
macos_setup_assistant:
scripts: null
webhook_settings:
host_status_webhook: null
name: team1
---
apiVersion: v1
@@ -64,4 +66,6 @@ spec:
enable_end_user_authentication: false
macos_setup_assistant:
scripts: null
webhook_settings:
host_status_webhook: null
name: team2
+99 -98
View File
@@ -1,100 +1,101 @@
{
"kind": "host",
"apiVersion": "v1",
"spec": {
"created_at": "0001-01-01T00:00:00Z",
"updated_at": "0001-01-01T00:00:00Z",
"id": 0,
"detail_updated_at": "0001-01-01T00:00:00Z",
"label_updated_at": "0001-01-01T00:00:00Z",
"policy_updated_at": "0001-01-01T00:00:00Z",
"last_enrolled_at": "0001-01-01T00:00:00Z",
"last_restarted_at": "0001-01-01T00:00:00Z",
"seen_time": "0001-01-01T00:00:00Z",
"software_updated_at": "0001-01-01T00:00:00Z",
"refetch_requested": false,
"refetch_critical_queries_until": null,
"hostname": "test_host",
"uuid": "",
"platform": "",
"osquery_version": "",
"os_version": "",
"build": "",
"platform_like": "",
"code_name": "",
"uptime": 0,
"memory": 0,
"cpu_type": "",
"cpu_subtype": "",
"cpu_brand": "",
"cpu_physical_cores": 0,
"cpu_logical_cores": 0,
"hardware_vendor": "",
"hardware_model": "",
"hardware_version": "",
"hardware_serial": "",
"computer_name": "test_host",
"public_ip": "",
"primary_ip": "",
"primary_mac": "",
"distributed_interval": 0,
"config_tls_refresh": 0,
"logger_tls_period": 0,
"mdm": {
"device_status": "unlocked",
"encryption_key_available": false,
"enrollment_status": null,
"name": "",
"pending_action": "",
"server_url": null
},
"team_id": null,
"pack_stats": null,
"team_name": null,
"gigs_disk_space_available": 0,
"percent_disk_space_available": 0,
"gigs_total_disk_space": 0,
"issues": {
"total_issues_count": 0,
"failing_policies_count": 0
},
"labels": [],
"packs": [],
"policies": [
{
"id": 1,
"query": "select 1 from osquery_info where start_time > 1;",
"name": "query1",
"platform": "",
"description": "Some description",
"author_email": "alice@example.com",
"author_id": 1,
"author_name": "Alice",
"response": "passes",
"resolution": "Some resolution",
"team_id": 1,
"updated_at": "0001-01-01T00:00:00Z",
"created_at": "0001-01-01T00:00:00Z",
"critical": false
},
{
"id": 2,
"query": "select 1 from osquery_info where start_time > 1;",
"name": "query2",
"platform": "",
"description": "",
"author_email": "alice@example.com",
"author_id": 1,
"author_name": "Alice",
"response": "fails",
"team_id": null,
"updated_at": "0001-01-01T00:00:00Z",
"created_at": "0001-01-01T00:00:00Z",
"critical": false
}
],
"status": "offline",
"display_text": "test_host",
"display_name": "test_host"
}
"kind": "host",
"apiVersion": "v1",
"spec": {
"created_at": "0001-01-01T00:00:00Z",
"updated_at": "0001-01-01T00:00:00Z",
"id": 0,
"detail_updated_at": "0001-01-01T00:00:00Z",
"label_updated_at": "0001-01-01T00:00:00Z",
"policy_updated_at": "0001-01-01T00:00:00Z",
"last_enrolled_at": "0001-01-01T00:00:00Z",
"last_restarted_at": "0001-01-01T00:00:00Z",
"seen_time": "0001-01-01T00:00:00Z",
"software_updated_at": "0001-01-01T00:00:00Z",
"refetch_requested": false,
"refetch_critical_queries_until": null,
"hostname": "test_host",
"uuid": "",
"platform": "",
"osquery_version": "",
"os_version": "",
"build": "",
"platform_like": "",
"code_name": "",
"uptime": 0,
"memory": 0,
"cpu_type": "",
"cpu_subtype": "",
"cpu_brand": "",
"cpu_physical_cores": 0,
"cpu_logical_cores": 0,
"hardware_vendor": "",
"hardware_model": "",
"hardware_version": "",
"hardware_serial": "",
"computer_name": "test_host",
"public_ip": "",
"primary_ip": "",
"primary_mac": "",
"distributed_interval": 0,
"config_tls_refresh": 0,
"logger_tls_period": 0,
"mdm": {
"dep_profile_error": false,
"device_status": "unlocked",
"encryption_key_available": false,
"enrollment_status": null,
"name": "",
"pending_action": "",
"server_url": null
},
"team_id": null,
"pack_stats": null,
"team_name": null,
"gigs_disk_space_available": 0,
"percent_disk_space_available": 0,
"gigs_total_disk_space": 0,
"issues": {
"total_issues_count": 0,
"failing_policies_count": 0
},
"labels": [],
"packs": [],
"policies": [
{
"id": 1,
"query": "select 1 from osquery_info where start_time > 1;",
"name": "query1",
"platform": "",
"description": "Some description",
"author_email": "alice@example.com",
"author_id": 1,
"author_name": "Alice",
"response": "passes",
"resolution": "Some resolution",
"team_id": 1,
"updated_at": "0001-01-01T00:00:00Z",
"created_at": "0001-01-01T00:00:00Z",
"critical": false
},
{
"id": 2,
"query": "select 1 from osquery_info where start_time > 1;",
"name": "query2",
"platform": "",
"description": "",
"author_email": "alice@example.com",
"author_id": 1,
"author_name": "Alice",
"response": "fails",
"team_id": null,
"updated_at": "0001-01-01T00:00:00Z",
"created_at": "0001-01-01T00:00:00Z",
"critical": false
}
],
"status": "offline",
"display_text": "test_host",
"display_name": "test_host"
}
}
@@ -32,6 +32,7 @@ spec:
last_restarted_at: "0001-01-01T00:00:00Z"
logger_tls_period: 0
mdm:
dep_profile_error: false
device_status: unlocked
encryption_key_available: false
enrollment_status: null
+2
View File
@@ -42,6 +42,7 @@
"config_tls_refresh": 0,
"logger_tls_period": 0,
"mdm": {
"dep_profile_error": false,
"encryption_key_available": false,
"enrollment_status": null,
"name": "",
@@ -113,6 +114,7 @@
"config_tls_refresh": 0,
"logger_tls_period": 0,
"mdm": {
"dep_profile_error": false,
"encryption_key_available": false,
"enrollment_status": null,
"name": "",
+136 -134
View File
@@ -1,136 +1,138 @@
[
{
"kind": "host",
"apiVersion": "v1",
"spec": {
"created_at": "0001-01-01T00:00:00Z",
"updated_at": "0001-01-01T00:00:00Z",
"id": 0,
"detail_updated_at": "0001-01-01T00:00:00Z",
"label_updated_at": "0001-01-01T00:00:00Z",
"last_enrolled_at": "0001-01-01T00:00:00Z",
"last_restarted_at": "0001-01-01T00:00:00Z",
"seen_time": "0001-01-01T00:00:00Z",
"software_updated_at": "0001-01-01T00:00:00Z",
"refetch_requested": false,
"refetch_critical_queries_until": null,
"hostname": "test_host",
"display_name": "test_host",
"uuid": "",
"platform": "",
"osquery_version": "",
"os_version": "",
"build": "",
"platform_like": "",
"policy_updated_at": "0001-01-01T00:00:00Z",
"code_name": "",
"uptime": 0,
"memory": 0,
"cpu_type": "",
"cpu_subtype": "",
"cpu_brand": "",
"cpu_physical_cores": 0,
"cpu_logical_cores": 0,
"hardware_vendor": "",
"hardware_model": "",
"hardware_version": "",
"hardware_serial": "",
"computer_name": "test_host",
"public_ip": "",
"primary_ip": "",
"primary_mac": "",
"distributed_interval": 0,
"config_tls_refresh": 0,
"logger_tls_period": 0,
"mdm": {
"encryption_key_available": false,
"enrollment_status": null,
"name": "",
"server_url": null
},
"team_id": null,
"pack_stats": null,
"team_name": null,
"additional": {
"query1": [
{
"col1": "val",
"col2": 42
}
]
},
"gigs_disk_space_available": 0,
"percent_disk_space_available": 0,
"gigs_total_disk_space": 0,
"issues": {
"total_issues_count": 0,
"failing_policies_count": 0
},
"status": "offline",
"display_text": "test_host"
}
},
{
"kind": "host",
"apiVersion": "v1",
"spec": {
"created_at": "0001-01-01T00:00:00Z",
"updated_at": "0001-01-01T00:00:00Z",
"id": 0,
"detail_updated_at": "0001-01-01T00:00:00Z",
"label_updated_at": "0001-01-01T00:00:00Z",
"last_enrolled_at": "0001-01-01T00:00:00Z",
"last_restarted_at": "0001-01-01T00:00:00Z",
"seen_time": "0001-01-01T00:00:00Z",
"software_updated_at": "0001-01-01T00:00:00Z",
"refetch_requested": false,
"refetch_critical_queries_until": null,
"hostname": "test_host2",
"uuid": "",
"platform": "",
"osquery_version": "",
"os_version": "",
"build": "",
"platform_like": "",
"policy_updated_at": "0001-01-01T00:00:00Z",
"code_name": "",
"uptime": 0,
"memory": 0,
"cpu_type": "",
"cpu_subtype": "",
"cpu_brand": "",
"cpu_physical_cores": 0,
"cpu_logical_cores": 0,
"hardware_vendor": "",
"hardware_model": "",
"hardware_version": "",
"hardware_serial": "",
"computer_name": "test_host2",
"display_name": "test_host2",
"public_ip": "",
"primary_ip": "",
"primary_mac": "",
"distributed_interval": 0,
"config_tls_refresh": 0,
"logger_tls_period": 0,
"mdm": {
"encryption_key_available": false,
"enrollment_status": null,
"name": "",
"server_url": null
},
"team_id": null,
"pack_stats": null,
"team_name": null,
"gigs_disk_space_available": 0,
"percent_disk_space_available": 0,
"gigs_total_disk_space": 0,
"issues": {
"total_issues_count": 0,
"failing_policies_count": 0
},
"status": "offline",
"display_text": "test_host2"
}
}
{
"kind": "host",
"apiVersion": "v1",
"spec": {
"created_at": "0001-01-01T00:00:00Z",
"updated_at": "0001-01-01T00:00:00Z",
"id": 0,
"detail_updated_at": "0001-01-01T00:00:00Z",
"label_updated_at": "0001-01-01T00:00:00Z",
"last_enrolled_at": "0001-01-01T00:00:00Z",
"last_restarted_at": "0001-01-01T00:00:00Z",
"seen_time": "0001-01-01T00:00:00Z",
"software_updated_at": "0001-01-01T00:00:00Z",
"refetch_requested": false,
"refetch_critical_queries_until": null,
"hostname": "test_host",
"display_name": "test_host",
"uuid": "",
"platform": "",
"osquery_version": "",
"os_version": "",
"build": "",
"platform_like": "",
"policy_updated_at": "0001-01-01T00:00:00Z",
"code_name": "",
"uptime": 0,
"memory": 0,
"cpu_type": "",
"cpu_subtype": "",
"cpu_brand": "",
"cpu_physical_cores": 0,
"cpu_logical_cores": 0,
"hardware_vendor": "",
"hardware_model": "",
"hardware_version": "",
"hardware_serial": "",
"computer_name": "test_host",
"public_ip": "",
"primary_ip": "",
"primary_mac": "",
"distributed_interval": 0,
"config_tls_refresh": 0,
"logger_tls_period": 0,
"mdm": {
"dep_profile_error": false,
"encryption_key_available": false,
"enrollment_status": null,
"name": "",
"server_url": null
},
"team_id": null,
"pack_stats": null,
"team_name": null,
"additional": {
"query1": [
{
"col1": "val",
"col2": 42
}
]
},
"gigs_disk_space_available": 0,
"percent_disk_space_available": 0,
"gigs_total_disk_space": 0,
"issues": {
"total_issues_count": 0,
"failing_policies_count": 0
},
"status": "offline",
"display_text": "test_host"
}
},
{
"kind": "host",
"apiVersion": "v1",
"spec": {
"created_at": "0001-01-01T00:00:00Z",
"updated_at": "0001-01-01T00:00:00Z",
"id": 0,
"detail_updated_at": "0001-01-01T00:00:00Z",
"label_updated_at": "0001-01-01T00:00:00Z",
"last_enrolled_at": "0001-01-01T00:00:00Z",
"last_restarted_at": "0001-01-01T00:00:00Z",
"seen_time": "0001-01-01T00:00:00Z",
"software_updated_at": "0001-01-01T00:00:00Z",
"refetch_requested": false,
"refetch_critical_queries_until": null,
"hostname": "test_host2",
"uuid": "",
"platform": "",
"osquery_version": "",
"os_version": "",
"build": "",
"platform_like": "",
"policy_updated_at": "0001-01-01T00:00:00Z",
"code_name": "",
"uptime": 0,
"memory": 0,
"cpu_type": "",
"cpu_subtype": "",
"cpu_brand": "",
"cpu_physical_cores": 0,
"cpu_logical_cores": 0,
"hardware_vendor": "",
"hardware_model": "",
"hardware_version": "",
"hardware_serial": "",
"computer_name": "test_host2",
"display_name": "test_host2",
"public_ip": "",
"primary_ip": "",
"primary_mac": "",
"distributed_interval": 0,
"config_tls_refresh": 0,
"logger_tls_period": 0,
"mdm": {
"dep_profile_error": false,
"encryption_key_available": false,
"enrollment_status": null,
"name": "",
"server_url": null
},
"team_id": null,
"pack_stats": null,
"team_name": null,
"gigs_disk_space_available": 0,
"percent_disk_space_available": 0,
"gigs_total_disk_space": 0,
"issues": {
"total_issues_count": 0,
"failing_policies_count": 0
},
"status": "offline",
"display_text": "test_host2"
}
}
]
+2
View File
@@ -36,6 +36,7 @@ spec:
last_restarted_at: "0001-01-01T00:00:00Z"
logger_tls_period: 0
mdm:
dep_profile_error: false
encryption_key_available: false
enrollment_status: null
name: ""
@@ -93,6 +94,7 @@ spec:
last_restarted_at: "0001-01-01T00:00:00Z"
logger_tls_period: 0
mdm:
dep_profile_error: false
encryption_key_available: false
enrollment_status: null
server_url: null
+5 -4
View File
@@ -4,10 +4,11 @@ team_settings:
- secret: "SampleSecret123"
- secret: "ABC"
webhook_settings:
failing_policies_webhook:
enable_failing_policies_webhook: true
destination_url: https://example.tines.com/webhook
policy_ids: [1, 2, 3, 4, 5, 6 ,7, 8, 9]
host_status_webhook:
days_count: 14
destination_url: https://example.com/host_status_webhook
enable_host_status_webhook: true
host_percentage: 25
features:
enable_host_users: true
enable_software_inventory: true
@@ -26,6 +26,8 @@ spec:
deadline_days: null
grace_period_days: null
scripts: null
webhook_settings:
host_status_webhook: null
name: tm1
---
apiVersion: v1
@@ -54,4 +56,6 @@ spec:
deadline_days: null
grace_period_days: null
scripts: null
webhook_settings:
host_status_webhook: null
name: tm2
@@ -26,6 +26,8 @@ spec:
deadline_days: null
grace_period_days: null
scripts: null
webhook_settings:
host_status_webhook: null
name: tm1
---
apiVersion: v1
@@ -54,4 +56,6 @@ spec:
deadline_days: null
grace_period_days: null
scripts: null
webhook_settings:
host_status_webhook: null
name: tm2
@@ -26,5 +26,7 @@ spec:
windows_settings:
custom_settings: null
scripts: null
webhook_settings:
host_status_webhook: null
name: tm1