Skip to content

Commit

Permalink
fix: correctly get VPP token ID when doing a renewal (#25657)
Browse files Browse the repository at this point in the history
> For #25567

# 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/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/Committing-Changes.md#changes-files)
for more information.
- [x] Added/updated automated tests
- [x] A detailed QA plan exists on the associated ticket (if it isn't
there, work with the product group's QA engineer to add it)
- [x] Manual QA for all new/changed functionality

---------

Co-authored-by: Ian Littman <iansltx@gmail.com>
  • Loading branch information
jahzielv and iansltx authored Jan 22, 2025
1 parent ac656f6 commit bb8054b
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 1 deletion.
1 change: 1 addition & 0 deletions changes/25567-renew-vpp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* Fixed a bug in Fleet's handling of VPP token renewal requests
16 changes: 15 additions & 1 deletion server/service/integration_mdm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1405,6 +1405,10 @@ func (s *integrationMDMTestSuite) TestGetMDMCSR() {
}

func (s *integrationMDMTestSuite) uploadDataViaForm(endpoint, fieldName, fileName string, data []byte, expectedStatus int, wantErr string, response any) {
s.uploadDataViaFormWithVerb(endpoint, "POST", fieldName, fileName, data, expectedStatus, wantErr, response)
}

func (s *integrationMDMTestSuite) uploadDataViaFormWithVerb(endpoint, verb, fieldName, fileName string, data []byte, expectedStatus int, wantErr string, response any) {
t := s.T()

var b bytes.Buffer
Expand All @@ -1424,7 +1428,7 @@ func (s *integrationMDMTestSuite) uploadDataViaForm(endpoint, fieldName, fileNam
"Authorization": fmt.Sprintf("Bearer %s", s.token),
}

res := s.DoRawWithHeaders("POST", endpoint, b.Bytes(), expectedStatus, headers)
res := s.DoRawWithHeaders(verb, endpoint, b.Bytes(), expectedStatus, headers)
if wantErr != "" {
errMsg := extractServerErrorText(res.Body)
assert.Contains(t, errMsg, wantErr)
Expand Down Expand Up @@ -10907,6 +10911,8 @@ func (s *integrationMDMTestSuite) TestVPPApps() {
// Invalid token
t.Setenv("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL+"?invalidToken")
s.uploadDataViaForm("/api/latest/fleet/vpp_tokens", "token", "token.vpptoken", []byte("foobar"), http.StatusUnprocessableEntity, "Invalid token. Please provide a valid content token from Apple Business Manager.", nil)
// Attempt to renew an invalid (nonexistent) token, should fail
s.uploadDataViaFormWithVerb("/api/latest/fleet/vpp_tokens/999/renew", "PATCH", "token", "token.vpptoken", []byte(base64.StdEncoding.EncodeToString([]byte("foobar"))), http.StatusUnprocessableEntity, "Invalid token. Please provide a valid content token from Apple Business Manager.", nil)

// Simulate a server error from the Apple API
t.Setenv("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL+"?serverError")
Expand All @@ -10925,6 +10931,14 @@ func (s *integrationMDMTestSuite) TestVPPApps() {

s.lastActivityMatches(fleet.ActivityEnabledVPP{}.ActivityName(), "", 0)

// Renew valid token
expTime = expTime.Add(24 * time.Hour).UTC().Round(time.Second)
expDate = expTime.Format(fleet.VPPTimeFormat)
tokenJSON = fmt.Sprintf(`{"expDate":"%s","token":"%s","orgName":"%s"}`, expDate, token, orgName)
s.uploadDataViaFormWithVerb(fmt.Sprintf("/api/latest/fleet/vpp_tokens/%d/renew", validToken.Token.ID), "PATCH", "token", "token.vpptoken", []byte(base64.StdEncoding.EncodeToString([]byte(tokenJSON))), http.StatusAccepted, "", &validToken)
// Valid token bytes, but non-existent token ID. Should get not found
s.uploadDataViaFormWithVerb("/api/latest/fleet/vpp_tokens/999/renew", "PATCH", "token", "token.vpptoken", []byte(base64.StdEncoding.EncodeToString([]byte(tokenJSON))), http.StatusNotFound, "VPPToken was not found in the datastore", nil)

// Get the token
var resp getVPPTokensResponse
s.DoJSON("GET", "/api/latest/fleet/vpp_tokens", &getVPPTokensRequest{}, http.StatusOK, &resp)
Expand Down
8 changes: 8 additions & 0 deletions server/service/vpp.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"net/http"

"github.com/docker/go-units"
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
"github.com/fleetdm/fleet/v4/server/fleet"
)

Expand Down Expand Up @@ -173,6 +174,13 @@ func (patchVPPTokenRenewRequest) DecodeRequest(ctx context.Context, r *http.Requ

decoded.File = r.MultipartForm.File["token"][0]

id, err := uintFromRequest(r, "id")
if err != nil {
return nil, ctxerr.Wrap(ctx, err, "failed to parse vpp token id")
}

decoded.ID = uint(id) //nolint:gosec // dismiss G115

return &decoded, nil
}

Expand Down

0 comments on commit bb8054b

Please sign in to comment.