mirror of
https://github.com/empayre/fleet.git
synced 2024-11-06 08:55:24 +00:00
114 lines
3.4 KiB
Go
114 lines
3.4 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/fleetdm/fleet/v4/server/fleet"
|
|
"github.com/fleetdm/fleet/v4/server/service"
|
|
kithttp "github.com/go-kit/kit/transport/http"
|
|
"github.com/urfave/cli/v2"
|
|
)
|
|
|
|
func mdmCommand() *cli.Command {
|
|
return &cli.Command{
|
|
Name: "mdm",
|
|
Usage: "Run MDM commands against your hosts",
|
|
Flags: []cli.Flag{
|
|
configFlag(),
|
|
contextFlag(),
|
|
debugFlag(),
|
|
},
|
|
Subcommands: []*cli.Command{
|
|
mdmRunCommand(),
|
|
},
|
|
}
|
|
}
|
|
|
|
func mdmRunCommand() *cli.Command {
|
|
return &cli.Command{
|
|
Name: "run-command",
|
|
Aliases: []string{"run_command"},
|
|
Usage: "Run a custom MDM command on one macOS host. Head to Apple's documentation for a list of available commands and example payloads here: https://developer.apple.com/documentation/devicemanagement/commands_and_queries",
|
|
Flags: []cli.Flag{
|
|
&cli.StringFlag{
|
|
Name: "host",
|
|
Usage: "The host, specified by hostname, uuid, osquery_host_id or node_key, that you want to run the MDM command on.",
|
|
Required: true,
|
|
},
|
|
&cli.StringFlag{
|
|
Name: "payload",
|
|
Usage: "A path to an XML file containing the raw MDM request payload.",
|
|
Required: true,
|
|
},
|
|
},
|
|
Action: func(c *cli.Context) error {
|
|
client, err := clientFromCLI(c)
|
|
if err != nil {
|
|
return fmt.Errorf("create client: %w", err)
|
|
}
|
|
|
|
// print an error if MDM is not configured
|
|
if err := client.CheckMDMEnabled(); err != nil {
|
|
return err
|
|
}
|
|
|
|
hostIdent := c.String("host")
|
|
payloadFile := c.String("payload")
|
|
payload, err := os.ReadFile(payloadFile)
|
|
if err != nil {
|
|
return fmt.Errorf("read payload: %w", err)
|
|
}
|
|
|
|
host, err := client.HostByIdentifier(hostIdent)
|
|
if err != nil {
|
|
var nfe service.NotFoundErr
|
|
if errors.As(err, &nfe) {
|
|
return errors.New("The host doesn't exist. Please provide a valid hostname, uuid, osquery_host_id or node_key.")
|
|
}
|
|
var sce kithttp.StatusCoder
|
|
if errors.As(err, &sce) {
|
|
if sce.StatusCode() == http.StatusForbidden {
|
|
return fmt.Errorf("Permission denied. You don't have permission to run an MDM command on this host: %w", err)
|
|
}
|
|
}
|
|
return err
|
|
}
|
|
|
|
// TODO(mna): this "On" check is brittle, but looks like it's the only
|
|
// enrollment indication we have right now...
|
|
if host.MDM.EnrollmentStatus == nil || !strings.HasPrefix(*host.MDM.EnrollmentStatus, "On") ||
|
|
host.MDM.Name != fleet.WellKnownMDMFleet {
|
|
return errors.New("Can't run the MDM command because the host doesn't have MDM turned on. Run the following command to see a list of hosts with MDM on: fleetctl get hosts --mdm")
|
|
}
|
|
|
|
result, err := client.EnqueueCommand([]string{host.UUID}, payload)
|
|
if err != nil {
|
|
var sce kithttp.StatusCoder
|
|
if errors.As(err, &sce) {
|
|
if sce.StatusCode() == http.StatusForbidden {
|
|
return fmt.Errorf("Permission denied. You don't have permission to run an MDM command on this host: %w", err)
|
|
}
|
|
if sce.StatusCode() == http.StatusUnsupportedMediaType {
|
|
return fmt.Errorf("The payload isn't valid. Please provide a valid MDM command in the form of a plist-encoded XML file: %w", err)
|
|
}
|
|
}
|
|
return err
|
|
}
|
|
|
|
fmt.Fprintf(c.App.Writer, `
|
|
The hosts will run the command the next time it checks into Fleet.
|
|
|
|
Copy and run this command to see results:
|
|
|
|
fleetctl get mdm-command-results --id=%v
|
|
`, result.CommandUUID)
|
|
|
|
return nil
|
|
},
|
|
}
|
|
}
|