Return 400 instead of 500 on Apple BM auth error (#11899)

This commit is contained in:
Martin Angers 2023-05-29 11:52:42 -04:00 committed by GitHub
parent 8b1bf35414
commit 4a077793f5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 52 additions and 4 deletions

View file

@ -0,0 +1 @@
* Updated the `/api/latest/fleet/mdm/apple_bm` to return 400 instead of 500 when it fails to authenticate with Apple's Business Manager API, as this indicates a Fleet configuration issue with the Apple BM certificate or token.

View file

@ -8,6 +8,7 @@ import (
"encoding/json"
"errors"
"io"
"net/http"
"net/url"
"strings"
@ -23,6 +24,7 @@ import (
kitlog "github.com/go-kit/kit/log"
"github.com/go-kit/kit/log/level"
"github.com/google/uuid"
depclient "github.com/micromdm/nanodep/client"
"github.com/micromdm/nanodep/storage"
)
@ -66,6 +68,20 @@ func getAppleBMAccountDetail(ctx context.Context, depStorage storage.AllStorage,
depClient := apple_mdm.NewDEPClient(depStorage, ds, logger)
res, err := depClient.AccountDetail(ctx, apple_mdm.DEPName)
if err != nil {
var authErr *depclient.AuthError
if errors.As(err, &authErr) {
// authentication failure with 401 unauthorized means that the configured
// Apple BM certificate and/or token are invalid. Fail with a 400 Bad
// Request.
msg := err.Error()
if authErr.StatusCode == http.StatusUnauthorized {
msg = "The Apple Business Manager certificate or server token is invalid. Restart Fleet with a valid certificate and token. See https://fleetdm.com/docs/using-fleet/mdm-setup#apple-business-manager-abm for help."
}
return nil, ctxerr.Wrap(ctx, &fleet.BadRequestError{
Message: msg,
InternalErr: err,
}, "apple GET /account request failed with authentication error")
}
return nil, ctxerr.Wrap(ctx, err, "apple GET /account request failed")
}

View file

@ -301,19 +301,50 @@ func (s *integrationMDMTestSuite) TestAppleGetAppleMDM() {
func (s *integrationMDMTestSuite) TestABMExpiredToken() {
t := s.T()
var returnType string
s.mockDEPResponse(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusForbidden)
_, _ = w.Write([]byte(`{"code": "T_C_NOT_SIGNED"}`))
switch returnType {
case "not_signed":
w.WriteHeader(http.StatusForbidden)
_, _ = w.Write([]byte(`{"code": "T_C_NOT_SIGNED"}`))
case "unauthorized":
w.WriteHeader(http.StatusUnauthorized)
_, _ = w.Write([]byte(`{}`))
case "success":
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(`{"auth_session_token": "abcd"}`))
default:
require.Fail(t, "unexpected return type: %s", returnType)
}
}))
config := s.getConfig()
require.False(t, config.MDM.AppleBMTermsExpired)
var getAppleBMResp getAppleBMResponse
s.DoJSON("GET", "/api/latest/fleet/mdm/apple_bm", nil, http.StatusInternalServerError, &getAppleBMResp)
// not signed error flips the AppleBMTermsExpired flag
returnType = "not_signed"
res := s.DoRaw("GET", "/api/latest/fleet/mdm/apple_bm", nil, http.StatusBadRequest)
errMsg := extractServerErrorText(res.Body)
require.Contains(t, errMsg, "DEP auth error: 403 Forbidden")
config = s.getConfig()
require.True(t, config.MDM.AppleBMTermsExpired)
// a successful call clears it
returnType = "success"
s.DoRaw("GET", "/api/latest/fleet/mdm/apple_bm", nil, http.StatusOK)
config = s.getConfig()
require.False(t, config.MDM.AppleBMTermsExpired)
// an unauthorized call returns 400 but does not flip the terms expired flag
returnType = "unauthorized"
res = s.DoRaw("GET", "/api/latest/fleet/mdm/apple_bm", nil, http.StatusBadRequest)
errMsg = extractServerErrorText(res.Body)
require.Contains(t, errMsg, "Apple Business Manager certificate or server token is invalid")
config = s.getConfig()
require.False(t, config.MDM.AppleBMTermsExpired)
}
func (s *integrationMDMTestSuite) TestProfileManagement() {