fleetdm / fleet

Open-source platform for IT, security, and infrastructure teams. (Linux, macOS, Chrome, Windows, cloud, data center)
https://fleetdm.com
Other
3.01k stars 418 forks source link

Finalize MDM commands #9643

Closed noahtalerman closed 1 year ago

noahtalerman commented 1 year ago

User story

As an IT admin, I want to be able to run an MDM command on my macOS hosts, so that I can restart, lock, or wipe a Mac remotely.

Requirements

Design

CLI usage

Add a fleetctl mdm run-command command
$ fleetctl mdm run-command --host=Alexs-MacBook-Pro.local --payload=command.xml

Copy and run this command to see results:

fleetctl get mdm-command-results --id=1


##### Errors

- ✅ ~~If `--host` isn't specified, display this error: `Error: No host targeted. Please provide --host.`~~ Required flags are handled in a common, consistent way throughout the CLI. (e.g. `Error: Required flag "host" not set`)
- ✅ If the `--host` doesn't exist, display this error: `Error: The host doesn't exist. Please provide a valid hostname, uuid, osquery_host_id or node_key.`
- ✅ If the the user doesn't have permissions to run an MDM command on the host, display this error: `Error: Permission denied. You don't have permission to run an MDM command on this host.`
- ✅ If the `--host` isn't connected to Fleet's MDM server, display this error: `Error: 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`
- ✅ Error if `--payload` doesn't contain valid XML: `Error: The payload isn't valid XML. Please provide a file with valid XML.`
- ✅ Error if the `--payload` points to a file that doesn't exist.
- ✅ Error if the user is using Fleet Free and they try to run the EraseDevice or DeviceLock command. These are Fleet Premium only.
- ✅ Error if MDM features aren't turned on in Fleet: Display this error message: `Error: MDM features aren't turned on. Use `fleetctl generate mdm-apple` and then `fleet serve` with `mdm` configuration to turn on MDM features.`

##### Add a `fleetctl get mdm-command-results` command
* [x] Add a `fleetctl get mdm-command-results` command

$ fleetctl get mdm-command-results --id=1


- `--id` flag accepts a command ID.
- Returns a table with ID (command id), TIME, TYPE, STATUS, HOSTNAME, and RESULTS columns. RESULTS is the raw XML result.

##### Errors

* ✅ ~~If --id isn't specified, display this error: Error: No command targeted. Please provide --id.~~ Required flags are handled in a common, consistent way throughout the CLI. (e.g. Error: Required flag "id" not set)
* ✅ If the --id doesn't exist, display this error: Error: `The command doesn't exist. Please provide a valid command ID. To see a list of commands that were run, run `fleetct get mdm-commands`.`
* ✅ Error if MDM features aren't turned on in Fleet: Display this error message: `Error: MDM features aren't turned on. Use `fleetctl generate mdm-apple` and then `fleet serve` with `mdm` configuration to turn on MDM features.`

##### Update `fleetctl get hosts` command
* [x] Update `fleetctl get hosts` command

- Add an `--mdm`. If the flag is included, return the list of hosts with MDM on (automatic and manual) and connected to Fleet's MDM server.
- Add an `--mdm-pending` flag. If the flag is included,, the list of hosts includes hosts with MDM pending.

##### Errors

- Error if MDM features aren't turned on in Fleet: Display this error message: `Error: MDM features aren't turned on. Use `fleetctl generate mdm-apple` and then `fleet serve` with `mdm` configuration to turn on MDM features.`

##### Help pages

* [x] `fleetctl`

```bash
$ fleetctl -h
NAME:
   fleetctl

COMMANDS:
   ... REMAINS SAME BUT ADD:
   mdm                                                  Run MDM commands against your hosts.
$ fleetctl mdm -h
NAME:
   fleetctl mdm - Run MDM commands against your hosts.

COMMANDS:
   ... REMAINS SAME BUT ADD:
   run-command                                 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
$ fleetctl run-command -h
NAME:
   fleetctl run-command -  Run a custom MDM command on a 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

OPTIONS:
   --host                                          The host, specified by hostname, uuid, osquery_host_id or node_key, that you want to run the MDM command on.
   --payload                                          A path to an XML file containing the raw MDM request payload.
$ fleetctl get -h
NAME:
   fleetctl get - Get/list resources

COMMANDS:
   ... REMAINS SAME BUT ADD:
   mdm-commands                               List information about one or more MDM commands that were run.
   mdm-command-results                    Retrieve results for a specific MDM command.
$ fleetctl get mdm-commands -h
NAME:
   fleetctl get mdm-commands - List information about one or more MDM commands that were run.
$ fleetctl get mdm-command-results -h
NAME:
   fleetctl get mdm-command-results - Retrieve results for a specific MDM command.

OPTIONS:
   ... REMAINS SAME BUT ADD:
   --id                                            Filter MDM commands by ID.
$ fleetctl get hosts -h
NAME:
   fleetctl get hosts -  List information about one or more hosts.

OPTIONS:
   ... REMAINS SAME BUT ADD:
   --mdm                                          Filters hosts by hosts that have MDM turned on in Fleet and are connected to Fleet's MDM server.
   --mdm-pending                           Filters hosts by hosts ordered via Apple Business Manager (ABM). These will automatically enroll to Fleet and turn on MDM when they're unboxed.
noahtalerman commented 1 year ago

User questions:

Technical questions:

noahtalerman commented 1 year ago

Mike: Include a link to apple MDM command docs? This is a way we called out links to be more visible in the sails cli: [?] https://foobar.com (cmd+double click to open this link in the terminal)

noahtalerman commented 1 year ago

Hey @lukeheath @roperzh @zhumo when you get the chance, can you please check out the proposed CLI experience for this story and following stories?

Feedback I'm looking for...

lukeheath commented 1 year ago

@noahtalerman Looks good! I added some comments to the issues. One other thing: What if we used mdm instead of mdm-command? fleetctl mdm lock --host 123 is nice and compact. Also fleetctl get mdm-results.

noahtalerman commented 1 year ago

Story to address later: As an IT admin, I want to assign a new DEP profile to only my test Mac, so that I can test my new unboxing settings on my test Mac before I edit the settings in production.

noahtalerman commented 1 year ago

Hey @lukeheath @roperzh @zhumo I updated the specs following feedback and discussion during today's MDM command pt. 3 call (2022-03-03):

What do you think?

noahtalerman commented 1 year ago

@lukeheath I assigned this story, and the lock and wipe stories, to you.

When you get the chance, you please break them into technical subtasks? I moved the stories to the designed column.

noahtalerman commented 1 year ago

Hey @lukeheath I assigned myself and moved this story out of designed column. We still need UI for new activity feed items.

noahtalerman commented 1 year ago

@lukeheath I assigned you this issue and moved it to the designed column.

I decided to push activity feed items for this story. We can add these in a later story around the same time we add UI features for showing the status of MDM commands.

lukeheath commented 1 year ago

Hey team! Please add your planning poker estimate with Zenhub @gillespi314 @mna @roperzh

noahtalerman commented 1 year ago

Rename fleetctl apple-mdm enrollment-profiles create-automatic command to fleetctl mdm edit-unbox-settings

$ fleetctl mdm edit-unbox-settings --payload=dep_profile.json

  • Command is available in Fleet Premium only
  • Updates the automatic enrollment profile for all hosts that automatically enroll to Fleet. The profile is only updated for hosts that enroll to Fleet in the future
  • --payload accepts a relative a path to an automatic enrollment (DEP) profile
  • Errors if the file is not valid JSON.
  • In the docs, inform the user that the file must be a JSON file and link the user to > - Apple's reference docs on accepted keys: https://developer.apple.com/documentation/devicemanagement/profile

@lukeheath I removed the above specs for the fleetctl mdm edit-unbox-settings command.

I don't think we need to build this command anymore.

This is because editing the unbox settings (DEP profile) is now covered by the changes in this "Different unboxing settings for each team" issue: #10518

mna commented 1 year ago

@noahtalerman Can you confirm what is expected by:

Remove all commands under fleetctl mdm-apple namespace. All these commands are removed from fleetctl help pages

This is probably meant to be fleetctl apple-mdm, I can't find an mdm-apple sub-command. Does that mean that all of those commands (currently under fleetctl apple-mdm) are meant to be removed? I understand that some of those will be replaced under fleetctl mdm, but just want to make sure all of fleetctl apple-mdm is supposed to be cleared (AFAIK, enrollment-profiles and installers don't have a replacement as of yet?):

EDIT: just realized that you mentioned this in another comment regarding enrollment-profiles:

I don't think we need to build this command anymore. This is because editing the unbox settings (DEP profile) is now covered by the changes in this "Different unboxing settings for each team" issue: https://github.com/fleetdm/fleet/issues/10518

So that leaves installers in the list without a replacement.

NAME:
   fleetctl apple-mdm - Apple MDM functionality

USAGE:
   fleetctl apple-mdm command [command options] [arguments...]

COMMANDS:
   enrollment-profiles  Commands to manage enrollment profiles
   enqueue-command      Enqueue an MDM command. See the results using the command-results command and passing the command UUID that is returned from this command.
   dep                  Device Enrollment Program commands
   devices              Inspect enrolled devices
   command-results      Get MDM command results
   installers           Commands to manage macOS installers
   help, h              Shows a list of commands or help for one command
mna commented 1 year ago

@noahtalerman @lukeheath FYI, I'll remove lock and wipe from this help output in the spec as they won't be implemented as part of this ticket:

$ fleetctl mdm -h
NAME:
   fleetctl mdm - Run MDM commands against your hosts.

COMMANDS:
   ... REMAINS SAME BUT ADD:
   lock                                                  Lock a host when it needs to be returned to your organization for reuse.
   wipe                                                 Wipe a host when it’s lost or stolen. You will have to reinstall macOS before the Mac can be used.
   run-command                                 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
mna commented 1 year ago

@noahtalerman one more thing regarding fleetctl mdm run-command, for the --host flag the spec mentions:

--host accepts a hostname.

Unless we have a good reason not to, I'd make this argument work the same as what we allow for the "Host by identifier" endpoint (which is what fleetctl would use to resolve the host): https://fleetdm.com/docs/using-fleet/rest-api#get-host-by-identifier

This makes it consistent with the identifier that can be provided to fleetctl get host <identifier>. Accordingly, I'd change the flag's description to:

The host, specified by hostname, uuid, osquery_host_id or node_key, that you want to run the MDM command on.

noahtalerman commented 1 year ago

work the same as what we allow for the "Host by identifier" endpoint

I'd change the flag's description to: The host, specified by hostname, uuid, osquery_host_id or node_key, that you want to run the MDM command on.

@mna this makes sense to me! I updated the CLI specs to reflect this. cc @lukeheath

I'll remove lock and wipe from this help output in the spec as they won't be implemented as part of this ticket

Great catch.

noahtalerman commented 1 year ago

I updated the CLI specs to reflect this

@mna in the CLI specs, I also updated the error message copy for when user doesn't target a valid host to the following:

Error: The host doesn't exist. Please provide a valid hostname, uuid, osquery_host_id or node_key.

mna commented 1 year ago

@noahtalerman @lukeheath

The spec mentions:

Only maintainers (global and team) and up can run MDM commands.

Is it the same to read the results (fleetctl get mdm-command-results), or can observers view them?

lukeheath commented 1 year ago

@mna Let's assume it's the same permissions to read results unless Noah says differently.

noahtalerman commented 1 year ago

Hey @mna I think it makes sense to give observers permission to view command results. Is it difficult/time consuming to change it?

cc @lukeheath

mna commented 1 year ago

@noahtalerman @lukeheath

it makes sense to give observers permission to view command results. Is it difficult/time consuming to change it?

No problem, I'll take a closer look, I haven't implemented the "read" authorization part yet but it may not be much more difficult than if it was just admin/maintainer.

mna commented 1 year ago

@noahtalerman @lukeheath for the output of the fleetctl get mdm-command-results command, the spec mentions:

Returns a table with ID, TIME, TYPE, STATUS, HOSTNAME, and RESULTS columns. RESULTS is the raw XML result.

What is the ID field in this case? Is it the command id (which would be the same for all rows, and equal to the one provided in the --id flag) or is it the host's uuid? The host uuid seems more useful in this case, but if so I'd change the header name to "Host UUID" to make it clear.

I'll go with that for now, it's not a big change either way.

noahtalerman commented 1 year ago

What is the ID field in this case?

Hey @mna! It's supposed to be the command id.

This way, the IT admin knows what command id to enter when they want to view a specific command's results (fleetctl get mdm-command-results --id=X)

which would be the same for all rows

The command id is the same for all commands? I would expect this to be unique for each command.

mna commented 1 year ago

@noahtalerman Note that this is for the fleetctl get mdm-command-results --id <cmdid> command, that returns the results for a single command (I think you have the other command in mind, the one that lists all commands that were executed?).

noahtalerman commented 1 year ago

this is for the fleetctl get mdm-command-results --id

@mna doh! You're right. I got it mixed up.

Still, the plan is for ID to be the command id (in the results for the fleetctl get mdm-command-results --id <cmdid>)

IT can use the ID to verify that they are viewing the results for the command they specified. I think that's valuable...what do you think?

mna commented 1 year ago

@noahtalerman Gotcha, yeah that works for me!

noahtalerman commented 1 year ago

Sweet. I updated the specs is the issue description to specify that it's the command id:

Returns a table with ID (command id), TIME, TYPE, STATUS, HOSTNAME, and RESULTS columns. RESULTS is the raw XML result.

mna commented 1 year ago

@noahtalerman @lukeheath

Mentioning it here so we can keep track of this. We have this pending discussion with Noah regarding a potential edge-case (which I don't think is critical for the upcoming release): (has been discussed and addressed in linked PR in the EDIT below)

https://github.com/fleetdm/fleet/pull/10964#discussion_r1157871242

And then there's this output from the fleetctl get mdm-command-results that we may want to tweak for the release, given that the fleetctl get mdm-commands command will not be ready/part of the release? (has been addresed in linked PR in the EDIT below)

https://github.com/fleetdm/fleet/pull/10964/files#diff-c83f7602b8ed12b771f57bf632370b0f5da9a70d7da23c0d146c436709ce1e74R1239

Let me know if we want to remove the "To see a list of commands that were run, run fleetct get mdm-commands." part for the release.

Otherwise, it is good to go. I'm working on the 4th and final command of this ticket (fleetctl get mdm-commands), but it won't make it for the freeze.

EDIT: both points addressed in https://github.com/fleetdm/fleet/pull/10997 (I went ahead and truncated the message that mentioned fleetctl get mdm-commands)

xpkoala commented 1 year ago

Providing valid xml, but an invalid payload for the fleetctl mdm run-command command results in a 500 response. To reproduce point the --payload at a .mobileconfig file. I don't believe this scenario was covered in the error state responses of the original ticket.

reed@reed fleet % sudo ./build/fleetctl mdm run-command --host reed.localdomain --payload ./test.mobileconfig
Error: run command request: POST /api/latest/fleet/mdm/apple/enqueue received status 500 invalid command: invalid command
noahtalerman commented 1 year ago

@xpkoala great find. Looks like we missed spec'ing an error message when the user doesn't provide a .xml file.

I think filing a separate bug for this makes sense. I don't think it needs to block the release.

fleet-release commented 1 year ago

I couldn't think of a haiku this time. (See fleetdm.com logs for more information.)