Skip to content

Commit

Permalink
fix fleetctl to set different CmdUID for Windows (#14895)
Browse files Browse the repository at this point in the history
for #14891
  • Loading branch information
Roberto Dip authored Nov 2, 2023
1 parent 722a206 commit b04b20f
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 1 deletion.
4 changes: 4 additions & 0 deletions cmd/fleetctl/mdm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,11 @@ func TestMDMRunCommand(t *testing.T) {
}
return hosts, nil
}
winCmds := map[string]struct{}{}
ds.MDMWindowsInsertCommandForHostsFunc = func(ctx context.Context, deviceIDs []string, cmd *fleet.MDMWindowsCommand) error {
// every command uuid is different
require.NotContains(t, winCmds, cmd.CommandUUID)
winCmds[cmd.CommandUUID] = struct{}{}
return nil
}
ds.GetMDMWindowsBitLockerStatusFunc = func(ctx context.Context, host *fleet.Host) (*fleet.HostMDMDiskEncryption, error) {
Expand Down
19 changes: 18 additions & 1 deletion server/service/client_mdm.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"path/filepath"
"strings"

"github.com/beevik/etree"
"github.com/fleetdm/fleet/v4/pkg/file"
"github.com/fleetdm/fleet/v4/server/fleet"
"github.com/google/uuid"
Expand Down Expand Up @@ -334,7 +335,23 @@ func (c *Client) prepareWindowsMDMCommand(rawCmd []byte) ([]byte, error) {
if _, err := fleet.ParseWindowsMDMCommand(rawCmd); err != nil {
return nil, err
}
return rawCmd, nil

// ensure there's a CmdID with a random UUID value, we're manipulating
// the document this way to make sure we don't introduce any unintended
// changes to the command XML.
doc := etree.NewDocument()
if err := doc.ReadFromBytes(rawCmd); err != nil {
return nil, err
}
element := doc.FindElement("//CmdID")
// if we can't find a CmdID, just add one.
if element == nil {
root := doc.Root()
element = root.CreateElement("CmdID")
}
element.SetText(uuid.NewString())

return doc.WriteToBytes()
}

func (c *Client) prepareAppleMDMCommand(rawCmd []byte) ([]byte, error) {
Expand Down
66 changes: 66 additions & 0 deletions server/service/client_mdm_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package service

import (
"testing"

"github.com/beevik/etree"
"github.com/stretchr/testify/assert"
)

func TestPrepareWindowsMDMCommand(t *testing.T) {
c := &Client{}

validXML := []byte(`
<Exec>
<CmdID>some-id</CmdID>
<Item></Item>
</Exec>
`)

invalidCmdXML := []byte(`
<Add>
<CmdID>some-id</Cmd>
<Item></Item>
</Add>
`)

noCmdIDXML := []byte(`
<Exec>
<Item></Item>
</Exec>
`)

t.Run("Modifies valid CmdID", func(t *testing.T) {
modified, err := c.prepareWindowsMDMCommand(validXML)
assert.Nil(t, err)

doc := etree.NewDocument()
err = doc.ReadFromBytes(modified)
assert.Nil(t, err)

element := doc.FindElement("//CmdID")
assert.NotNil(t, element)
assert.NotEmpty(t, element.Text())
})

t.Run("Adds CmdID if missing", func(t *testing.T) {
modified, err := c.prepareWindowsMDMCommand(noCmdIDXML)
assert.Nil(t, err)

doc := etree.NewDocument()
err = doc.ReadFromBytes(modified)
assert.Nil(t, err)

element := doc.FindElement("//CmdID")
assert.NotNil(t, element)
assert.NotEmpty(t, element.Text())
})

t.Run("Returns error on invalid XML", func(t *testing.T) {
_, err := c.prepareWindowsMDMCommand(invalidCmdXML)
assert.NotNil(t, err)

_, err = c.prepareWindowsMDMCommand([]byte("<Exec><Exec"))
assert.NotNil(t, err)
})
}

0 comments on commit b04b20f

Please sign in to comment.