diff --git a/CHANGELOG.md b/CHANGELOG.md index a930ff31..b3756d95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## [Unreleased](https://github.com/micromdm/micromdm/compare/v1.8.0...main) TBD - Fix SetFirmwarePassword and VerifyFirmwarePassword parameters (#743) +- Command UUID can now be passed in as as a request parameter (#754) ## [v1.8.0](https://github.com/micromdm/micromdm/compare/v1.7.1...v1.8.0) February, 2021 diff --git a/mdm/mdm/command.go b/mdm/mdm/command.go index 16e2b81d..4627387a 100644 --- a/mdm/mdm/command.go +++ b/mdm/mdm/command.go @@ -1,12 +1,15 @@ package mdm import ( + "strings" + "github.com/google/uuid" "github.com/micromdm/micromdm/mdm/appmanifest" ) type CommandRequest struct { - UDID string `json:"udid"` + UDID string `json:"udid"` + CommandUUID string `json:"command_uuid"` *Command } @@ -17,9 +20,12 @@ type CommandPayload struct { func NewCommandPayload(request *CommandRequest) (*CommandPayload, error) { payload := &CommandPayload{ - CommandUUID: uuid.New().String(), + CommandUUID: request.CommandUUID, Command: request.Command, } + if strings.TrimSpace(payload.CommandUUID) == "" { + payload.CommandUUID = uuid.New().String() + } return payload, nil } diff --git a/mdm/mdm/mdm_command_test.go b/mdm/mdm/mdm_command_test.go index 84a3efbd..cdb426e5 100644 --- a/mdm/mdm/mdm_command_test.go +++ b/mdm/mdm/mdm_command_test.go @@ -133,6 +133,49 @@ func TestUnmarshalCommandPayload(t *testing.T) { }) } } +func TestNewCommandPayload(t *testing.T) { + // Unit test cases for request params + var tests = []struct { + name string + request CommandRequest + testFn func(t *testing.T, payload *CommandPayload) + }{ + { + name: "Uses UUID passed to CommandRequest", + request: CommandRequest{CommandUUID: "this-uuid-should-be-used"}, + testFn: func(t *testing.T, payload *CommandPayload) { + if payload.CommandUUID != "this-uuid-should-be-used" { + t.Error("CommandUUID is not set to CommandRequest.CommandUUID") + } + }, + }, + { + name: "Defaults to generated UUID if CommandUUID is an empty string", + request: CommandRequest{CommandUUID: ""}, + testFn: func(t *testing.T, payload *CommandPayload) { + if payload.CommandUUID == "" { + t.Error("CommandUUID should be a generated UUID") + } + }, + }, + { + name: "Defaults to generated UUID if CommandUUID is all whitespace", + request: CommandRequest{CommandUUID: " "}, + testFn: func(t *testing.T, payload *CommandPayload) { + if payload.CommandUUID == " " { + t.Error("CommandUUID should be a generated UUID") + } + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var payload, _ = NewCommandPayload(&tt.request) + tt.testFn(t, payload) + }) + } +} func mustLoadFile(t *testing.T, filename string) []byte { t.Helper() diff --git a/mdm/mdm/unmarshal_json.go b/mdm/mdm/unmarshal_json.go index 5324672a..6622d55a 100644 --- a/mdm/mdm/unmarshal_json.go +++ b/mdm/mdm/unmarshal_json.go @@ -11,12 +11,14 @@ func (c *CommandRequest) UnmarshalJSON(data []byte) error { var request = struct { UDID string `json:"udid"` RequestType string `json:"request_type"` + CommandUUID string `json:"command_uuid"` }{} if err := json.Unmarshal(data, &request); err != nil { return errors.Wrap(err, "mdm: unmarshal json command request") } c.UDID = request.UDID c.Command = &Command{} + c.CommandUUID = request.CommandUUID return c.Command.UnmarshalJSON(data) }