mirror of
https://github.com/fleetdm/fleet
synced 2026-04-21 13:37:30 +00:00
feedback
This commit is contained in:
parent
2bfa0aaa3a
commit
18ef69ae78
3 changed files with 126 additions and 0 deletions
|
|
@ -548,6 +548,8 @@ func (ds *Datastore) MDMWindowsSaveResponse(ctx context.Context, deviceID string
|
|||
|
||||
var result *fleet.MDMWindowsSaveResponseResult
|
||||
if err := ds.withRetryTxx(ctx, func(tx sqlx.ExtContext) error {
|
||||
result = nil
|
||||
|
||||
// store the full response
|
||||
const saveFullRespStmt = `INSERT INTO windows_mdm_responses (enrollment_id, raw_response) VALUES (?, ?)`
|
||||
sqlResult, err := tx.ExecContext(ctx, saveFullRespStmt, enrolledDevice.ID, enrichedSyncML.Raw)
|
||||
|
|
|
|||
|
|
@ -1021,6 +1021,10 @@ func (a ActivityTypeWipeFailedHost) HostIDs() []uint {
|
|||
return []uint{a.HostID}
|
||||
}
|
||||
|
||||
func (a ActivityTypeWipeFailedHost) WasFromAutomation() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// ActivityTypeRotatedHostRecoveryLockPassword is for password rotation.
|
||||
// Can be user-initiated (manual) or Fleet-initiated (auto-rotation after password viewed).
|
||||
type ActivityTypeRotatedHostRecoveryLockPassword struct {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
"database/sql"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
|
@ -2857,3 +2858,122 @@ func TestNewMDMProfilePremiumOnlyAndroid(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestProcessIncomingMDMCmdsWipeFailedActivity(t *testing.T) {
|
||||
ds := new(mock.Store)
|
||||
opts := &TestServerOpts{}
|
||||
svc, ctx := newTestService(t, ds, nil, nil, opts)
|
||||
|
||||
var svcImpl *Service
|
||||
switch v := svc.(type) {
|
||||
case validationMiddleware:
|
||||
svcImpl = v.Service.(*Service)
|
||||
case *Service:
|
||||
svcImpl = v
|
||||
}
|
||||
|
||||
testHostUUID := "test-host-uuid"
|
||||
testHostID := uint(42)
|
||||
testDeviceID := "test-device-id"
|
||||
|
||||
// MDMWindowsSaveResponse returns a WipeFailed result.
|
||||
ds.MDMWindowsSaveResponseFunc = func(ctx context.Context, deviceID string, enrichedSyncML fleet.EnrichedSyncML, commandIDsBeingResent []string) (*fleet.MDMWindowsSaveResponseResult, error) {
|
||||
return &fleet.MDMWindowsSaveResponseResult{
|
||||
WipeFailed: &fleet.MDMWindowsWipeResult{
|
||||
HostUUID: testHostUUID,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Stub for the resending flow (no 418 commands in our test).
|
||||
ds.GetWindowsMDMCommandsForResendingFunc = func(ctx context.Context, deviceID string, cmdUUIDs []string) ([]*fleet.MDMWindowsCommand, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// HostByIdentifier returns a test host.
|
||||
ds.HostByIdentifierFunc = func(ctx context.Context, identifier string) (*fleet.Host, error) {
|
||||
require.Equal(t, testHostUUID, identifier)
|
||||
return &fleet.Host{
|
||||
ID: testHostID,
|
||||
ComputerName: "DESKTOP-TEST",
|
||||
UUID: testHostUUID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Track activity creation.
|
||||
var createdActivity activity_api.ActivityDetails
|
||||
opts.ActivityMock.NewActivityFunc = func(_ context.Context, user *activity_api.User, activity activity_api.ActivityDetails) error {
|
||||
assert.Nil(t, user, "wipe_failed_host activity should have nil user")
|
||||
createdActivity = activity
|
||||
return nil
|
||||
}
|
||||
|
||||
// Build a minimal valid SyncML message with a <Status> entry so that
|
||||
// NewEnrichedSyncML produces a non-empty CmdRefUUIDs and HasCommands()
|
||||
// returns true, which is needed for saveResponse to call MDMWindowsSaveResponse.
|
||||
fakeCmdUUID := uuid.NewString()
|
||||
rawSyncML := fmt.Sprintf(`<SyncML xmlns="SYNCML:SYNCML1.2">
|
||||
<SyncHdr>
|
||||
<VerDTD>1.2</VerDTD>
|
||||
<VerProto>DM/1.2</VerProto>
|
||||
<SessionID>1</SessionID>
|
||||
<MsgID>1</MsgID>
|
||||
<Source><LocURI>%s</LocURI></Source>
|
||||
</SyncHdr>
|
||||
<SyncBody>
|
||||
<Status>
|
||||
<CmdID>1</CmdID>
|
||||
<MsgRef>1</MsgRef>
|
||||
<CmdRef>%s</CmdRef>
|
||||
<Cmd>Exec</Cmd>
|
||||
<Data>500</Data>
|
||||
</Status>
|
||||
<Final/>
|
||||
</SyncBody>
|
||||
</SyncML>`, testDeviceID, fakeCmdUUID)
|
||||
|
||||
reqMsg := &fleet.SyncML{}
|
||||
require.NoError(t, xml.Unmarshal([]byte(rawSyncML), reqMsg))
|
||||
reqMsg.Raw = []byte(rawSyncML)
|
||||
|
||||
_, err := svcImpl.processIncomingMDMCmds(ctx, testDeviceID, reqMsg, RequestAuthStateTrusted)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify the activity was created.
|
||||
require.NotNil(t, createdActivity)
|
||||
wipeFailed, ok := createdActivity.(fleet.ActivityTypeWipeFailedHost)
|
||||
require.True(t, ok, "expected ActivityTypeWipeFailedHost, got %T", createdActivity)
|
||||
assert.Equal(t, testHostID, wipeFailed.HostID)
|
||||
assert.Equal(t, "DESKTOP-TEST", wipeFailed.HostDisplayName)
|
||||
assert.True(t, opts.ActivityMock.NewActivityFuncInvoked)
|
||||
|
||||
t.Run("no activity when WipeFailed is nil", func(t *testing.T) {
|
||||
ds.MDMWindowsSaveResponseFunc = func(ctx context.Context, deviceID string, enrichedSyncML fleet.EnrichedSyncML, commandIDsBeingResent []string) (*fleet.MDMWindowsSaveResponseResult, error) {
|
||||
return nil, nil
|
||||
}
|
||||
opts.ActivityMock.NewActivityFuncInvoked = false
|
||||
|
||||
_, err := svcImpl.processIncomingMDMCmds(ctx, testDeviceID, reqMsg, RequestAuthStateTrusted)
|
||||
require.NoError(t, err)
|
||||
assert.False(t, opts.ActivityMock.NewActivityFuncInvoked)
|
||||
})
|
||||
|
||||
t.Run("activity skipped when host lookup fails", func(t *testing.T) {
|
||||
ds.MDMWindowsSaveResponseFunc = func(ctx context.Context, deviceID string, enrichedSyncML fleet.EnrichedSyncML, commandIDsBeingResent []string) (*fleet.MDMWindowsSaveResponseResult, error) {
|
||||
return &fleet.MDMWindowsSaveResponseResult{
|
||||
WipeFailed: &fleet.MDMWindowsWipeResult{
|
||||
HostUUID: testHostUUID,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
ds.HostByIdentifierFunc = func(ctx context.Context, identifier string) (*fleet.Host, error) {
|
||||
return nil, errors.New("host not found")
|
||||
}
|
||||
opts.ActivityMock.NewActivityFuncInvoked = false
|
||||
|
||||
_, err := svcImpl.processIncomingMDMCmds(ctx, testDeviceID, reqMsg, RequestAuthStateTrusted)
|
||||
require.NoError(t, err)
|
||||
// Activity should NOT be created since host lookup failed.
|
||||
assert.False(t, opts.ActivityMock.NewActivityFuncInvoked)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue