mirror of
https://github.com/empayre/fleet.git
synced 2024-11-06 00:45:19 +00:00
fix: return bad request error during MDM migration when appropriate (#16551)
> Related issue: https://github.com/fleetdm/confidential/issues/5138 # Checklist for submitter If some of the following don't apply, delete the relevant line. <!-- Note that API documentation changes are now addressed by the product design team. --> - [x] 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] Manual QA for all new/changed functionality
This commit is contained in:
parent
91f2f11f9c
commit
babf4e17c8
2
changes/5138-mdm-migration-err
Normal file
2
changes/5138-mdm-migration-err
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
- Fixes issue where a bad request response from a 3rd party MDM solution would result in a 500 error
|
||||||
|
in Fleet during MDM migration.
|
@ -6196,6 +6196,75 @@ func (s *integrationMDMTestSuite) TestMigrateMDMDeviceWebhook() {
|
|||||||
require.False(t, webhookCalled)
|
require.False(t, webhookCalled)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *integrationMDMTestSuite) TestMigrateMDMDeviceWebhookErrors() {
|
||||||
|
t := s.T()
|
||||||
|
|
||||||
|
h := createHostAndDeviceToken(t, s.ds, "good-token")
|
||||||
|
|
||||||
|
var webhookCalled bool
|
||||||
|
webhookSrv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
webhookCalled = true
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
}))
|
||||||
|
defer webhookSrv.Close()
|
||||||
|
|
||||||
|
// patch app config with webhook url
|
||||||
|
acResp := fleet.AppConfig{}
|
||||||
|
s.DoJSON("PATCH", "/api/latest/fleet/config", json.RawMessage(fmt.Sprintf(`{
|
||||||
|
"mdm": {
|
||||||
|
"macos_migration": {
|
||||||
|
"enable": true,
|
||||||
|
"mode": "voluntary",
|
||||||
|
"webhook_url": "%s/test_mdm_migration"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`, webhookSrv.URL)), http.StatusOK, &acResp)
|
||||||
|
require.True(t, acResp.MDM.MacOSMigration.Enable)
|
||||||
|
|
||||||
|
isServer, enrolled, installedFromDEP := true, true, true
|
||||||
|
mdmName := "ExampleMDM"
|
||||||
|
mdmURL := "https://mdm.example.com"
|
||||||
|
|
||||||
|
// host is enrolled to a third-party MDM but hasn't been assigned in
|
||||||
|
// ABM yet, so migration is not allowed
|
||||||
|
require.NoError(t, s.ds.SetOrUpdateMDMData(context.Background(), h.ID, !isServer, enrolled, mdmURL, installedFromDEP, mdmName, ""))
|
||||||
|
s.Do("POST", fmt.Sprintf("/api/v1/fleet/device/%s/migrate_mdm", "good-token"), nil, http.StatusBadRequest)
|
||||||
|
require.False(t, webhookCalled)
|
||||||
|
|
||||||
|
// simulate that the device is assigned to Fleet in ABM
|
||||||
|
s.mockDEPResponse(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
switch r.URL.Path {
|
||||||
|
case "/session":
|
||||||
|
_, _ = w.Write([]byte(`{"auth_session_token": "xyz"}`))
|
||||||
|
case "/profile":
|
||||||
|
encoder := json.NewEncoder(w)
|
||||||
|
err := encoder.Encode(godep.ProfileResponse{ProfileUUID: "abc"})
|
||||||
|
require.NoError(t, err)
|
||||||
|
case "/server/devices", "/devices/sync":
|
||||||
|
encoder := json.NewEncoder(w)
|
||||||
|
err := encoder.Encode(godep.DeviceResponse{
|
||||||
|
Devices: []godep.Device{
|
||||||
|
{
|
||||||
|
SerialNumber: h.HardwareSerial,
|
||||||
|
Model: "Mac Mini",
|
||||||
|
OS: "osx",
|
||||||
|
OpType: "added",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
s.runDEPSchedule()
|
||||||
|
|
||||||
|
// hosts meets all requirements, webhook is run but returns an error, server should respond with
|
||||||
|
// the same status code
|
||||||
|
require.False(t, webhookCalled)
|
||||||
|
s.Do("POST", fmt.Sprintf("/api/v1/fleet/device/%s/migrate_mdm", "good-token"), nil, http.StatusBadRequest)
|
||||||
|
require.True(t, webhookCalled)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *integrationMDMTestSuite) TestMDMMacOSSetup() {
|
func (s *integrationMDMTestSuite) TestMDMMacOSSetup() {
|
||||||
t := s.T()
|
t := s.T()
|
||||||
|
|
||||||
|
@ -37,6 +37,22 @@ func httpSuccessStatus(statusCode int) bool {
|
|||||||
return statusCode >= 200 && statusCode <= 299
|
return statusCode >= 200 && statusCode <= 299
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// errWithStatus is an error with a particular status code.
|
||||||
|
type errWithStatus struct {
|
||||||
|
err string
|
||||||
|
statusCode int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error implements the error interface
|
||||||
|
func (e *errWithStatus) Error() string {
|
||||||
|
return e.err
|
||||||
|
}
|
||||||
|
|
||||||
|
// StatusCode implements the StatusCoder interface for returning custom status codes.
|
||||||
|
func (e *errWithStatus) StatusCode() int {
|
||||||
|
return e.statusCode
|
||||||
|
}
|
||||||
|
|
||||||
func PostJSONWithTimeout(ctx context.Context, url string, v interface{}) error {
|
func PostJSONWithTimeout(ctx context.Context, url string, v interface{}) error {
|
||||||
jsonBytes, err := json.Marshal(v)
|
jsonBytes, err := json.Marshal(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -59,7 +75,7 @@ func PostJSONWithTimeout(ctx context.Context, url string, v interface{}) error {
|
|||||||
|
|
||||||
if !httpSuccessStatus(resp.StatusCode) {
|
if !httpSuccessStatus(resp.StatusCode) {
|
||||||
body, _ := io.ReadAll(resp.Body)
|
body, _ := io.ReadAll(resp.Body)
|
||||||
return fmt.Errorf("error posting to %s: %d. %s", MaskSecretURLParams(url), resp.StatusCode, string(body))
|
return &errWithStatus{err: fmt.Sprintf("error posting to %s: %d. %s", MaskSecretURLParams(url), resp.StatusCode, string(body)), statusCode: resp.StatusCode}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -41,6 +41,10 @@ module.exports = {
|
|||||||
unauthorized: {
|
unauthorized: {
|
||||||
responseType: 'unauthorized',
|
responseType: 'unauthorized',
|
||||||
description: 'This webhook request could not be verified.',
|
description: 'This webhook request could not be verified.',
|
||||||
|
},
|
||||||
|
badRequest: {
|
||||||
|
responseType: 'badRequest',
|
||||||
|
description: 'Invalid MDM migration request.'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -102,7 +106,7 @@ module.exports = {
|
|||||||
if(err.raw.statusCode === 404){
|
if(err.raw.statusCode === 404){
|
||||||
return new Error(`When sending a request to unenroll a host from a Workspace One instance (Host information: Serial number: ${host.hardware_serial}, id: ${host.id}, uuid: ${host.uuid}), the specified host was not found on the customer's Workspace One instance. Full error: ${err.stack}`);
|
return new Error(`When sending a request to unenroll a host from a Workspace One instance (Host information: Serial number: ${host.hardware_serial}, id: ${host.id}, uuid: ${host.uuid}), the specified host was not found on the customer's Workspace One instance. Full error: ${err.stack}`);
|
||||||
} else if(err.raw.statusCode === 400) {
|
} else if(err.raw.statusCode === 400) {
|
||||||
return new Error(`When sending a request to unenroll a host from a Workspace One instance (Host information: Serial number: ${host.hardware_serial}, id: ${host.id}, uuid: ${host.uuid}), the Workspace One instance could not unenroll the specified host. Full error: ${err.stack}`);
|
return { badRequest: `When sending a request to unenroll a host from a Workspace One instance (Host information: Serial number: ${host.hardware_serial}, id: ${host.id}, uuid: ${host.uuid}), the Workspace One instance could not unenroll the specified host. Full error: ${err.stack}` };
|
||||||
} else {
|
} else {
|
||||||
return new Error(`When sending a request to unenroll a host from a Workspace One instance (Host information: Serial number: ${host.hardware_serial}, id: ${host.id}, uuid: ${host.uuid}), an error occured. Full error: ${err.stack}`);
|
return new Error(`When sending a request to unenroll a host from a Workspace One instance (Host information: Serial number: ${host.hardware_serial}, id: ${host.id}, uuid: ${host.uuid}), an error occured. Full error: ${err.stack}`);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user