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)
|
||||
}
|
||||
|
||||
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() {
|
||||
t := s.T()
|
||||
|
||||
|
@ -37,6 +37,22 @@ func httpSuccessStatus(statusCode int) bool {
|
||||
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 {
|
||||
jsonBytes, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
@ -59,7 +75,7 @@ func PostJSONWithTimeout(ctx context.Context, url string, v interface{}) error {
|
||||
|
||||
if !httpSuccessStatus(resp.StatusCode) {
|
||||
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
|
||||
|
@ -41,6 +41,10 @@ module.exports = {
|
||||
unauthorized: {
|
||||
responseType: 'unauthorized',
|
||||
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){
|
||||
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) {
|
||||
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 {
|
||||
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