mirror of
https://github.com/fleetdm/fleet
synced 2026-05-24 01:18:42 +00:00
mdm docs index (#22716)
effort to compile all the resources we have scattered about MDM and document a few fleet-specific behaviors. --------- Co-authored-by: Victor Lyuboslavsky <victor.lyuboslavsky@gmail.com> Co-authored-by: mostlikelee <tim@mostlikelee.com>
This commit is contained in:
parent
8979e8ff1b
commit
a49adc8214
2 changed files with 211 additions and 14 deletions
197
docs/Contributing/MDM.md
Normal file
197
docs/Contributing/MDM.md
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
# MDM index
|
||||
|
||||
## Knowledge transfer videos
|
||||
|
||||
- Roberto's MDM knowledge transfer videos
|
||||
- [Google Drive](https://drive.google.com/drive/u/0/folders/1xvR89NNJWEc2dG0Se9m0goTz0Pjh1-RN)
|
||||
- Also on Loom -- search for `MDM knowledge dump`
|
||||
|
||||
- Marcos's Windows knowledge transfer videos
|
||||
- [Session1](https://drive.google.com/file/d/1d4rcK2bsLGVocbh2s88vW2FNzOQxP1B_)
|
||||
- [Session2](https://drive.google.com/file/d/1V5Jl7azXnZZRnkjwDaEvF1pe24nVZHSH)
|
||||
|
||||
## Protocol
|
||||
|
||||
### Apple
|
||||
|
||||
- Apple documentation for MDM
|
||||
- Web version: https://developer.apple.com/documentation/devicemanagement
|
||||
- YAML version: https://github.com/apple/device-management
|
||||
- NOTE: documentation for upcoming/beta features is available in the YAML version first, look for branches.
|
||||
|
||||
- Fleet's MDM glossary: https://github.com/fleetdm/fleet/blob/main/tools/mdm/apple/glossary-and-protocols.md
|
||||
|
||||
- MicroMDM and NanoMDM wikis.
|
||||
|
||||
- MacAdmins Slack, channels: #mdmdev, #declarative-management, #apple-feedback, #nudge, #swiftdialog
|
||||
|
||||
### Windows
|
||||
|
||||
- Enrollment protocol: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-mde/5c841535-042e-489e-913c-9d783d741267
|
||||
|
||||
- MDM protocol: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-mdm/33769a92-ac31-47ef-ae7b-dc8501f7104f
|
||||
|
||||
- CSPs: https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-configuration-service-provider
|
||||
|
||||
### Development
|
||||
|
||||
- `./Testing-and-local-development.md` has many sections about setting up MDM and debugging specific features
|
||||
- `tools/mdm/apple/troubleshooting.md` has instructions to troubleshoot Apple MDM in hosts
|
||||
- `tools/mdm/*` contains many ad-hoc tools we've been adding to aid development, including but not limited to:
|
||||
- Servers to perform MDM migrations from different providers
|
||||
- Tools to debug the ABM APIs
|
||||
- Tools to import/export certificates and keys from the DB
|
||||
|
||||
## Fleet specific features
|
||||
|
||||
### Profiles and Declarations
|
||||
|
||||
For Windows and Apple MDM, Fleet defines "profiles" as groups of settings that can be SyncML (Windows), XML, or JSON (Apple).
|
||||
|
||||
Settings are defined per team and can be further targeted to hosts using labels.
|
||||
|
||||
Profiles and declarations can be uploaded via the UI/CLI by the IT admin. Additionally, Fleet automatically sends profiles to hosts as part of high-level UI actions. For instance, enabling disk encryption in macOS sends the relevant configuration to the host.
|
||||
|
||||
To determine the subset of profiles/declarations that should be applied to a specific host, we use the following approach:
|
||||
|
||||
1. **Ideal State:** The "ideal state" of a host is calculated by combining team profiles with any label-based inclusions/exclusions using the `mdm_*_configuration_profiles` and `mdm_apple_declarations` tables.
|
||||
2. **Current State:** The "current state" of a host is tracked using the `host_mdm_*_configuration_profiles` and `host_mdm_apple_declarations` tables, which are updated based on MDM protocol responses and kept in sync via osquery (commonly referred to as "profile verification" or "double-check").
|
||||
3. **Diff Calculation:** We use set algebra to compute the difference between the ideal and current states—determining the profiles that need to be installed ("to install") and those that should be removed ("to remove").
|
||||
|
||||
This logic runs in two main places:
|
||||
|
||||
1. **`mdm_apple_profile_manager` Cron Job:** Runs every 30 seconds and performs the following actions:
|
||||
- Calculates the profiles to install/remove
|
||||
- Enqueues the necessary commands
|
||||
- Sends push notifications to the hosts
|
||||
|
||||
(Note: Despite its name, this cron job handles both Apple and Windows MDM. [Issue link](https://github.com/fleetdm/fleet/issues/22824))
|
||||
|
||||
2. **`ds.BulkSetPendingMDMHostProfiles`:** This method is called to mark profiles and declarations as "pending." It's a lighter process than the cron job, only updating database records to reflect pending profiles in the UI, providing immediate feedback to users.
|
||||
|
||||
### Profile/declaration verification (double check)
|
||||
|
||||
Osquery double checks are explained in good detail as part of their initial specs:
|
||||
|
||||
- https://github.com/fleetdm/fleet/issues/11099
|
||||
- https://github.com/fleetdm/fleet/issues/9780
|
||||
|
||||
### NanoMDM Integration for Apple MDM
|
||||
|
||||
[NanoMDM](https://github.com/micromdm/nanomdm) handles the core protocol operations for Apple MDM. Fleet extends the protocol and adds custom handling to align with our desired workflows.
|
||||
|
||||
After NanoMDM processes a protocol operation, it allows for custom logic by implementing the `CheckinAndCommandService` interface. Our implementation can be found in the service layer.
|
||||
|
||||
https://github.com/fleetdm/fleet/blob/4ff5f7a18abcaa9003fe250fb50d7a246d2af795/server/service/apple_mdm.go#L2595-L2600
|
||||
|
||||
Additionally, per request from management, we maintain a modified version of the NanoMDM repository under `server/mdm/nanomdm/` to support Fleet-specific requirements.
|
||||
|
||||
### MDM Lifecycle
|
||||
|
||||
While implementing MDM-specific features, we identified recurring patterns related to managing the "MDM connection" to the host. We refer to this as the "MDM lifecycle." A few examples:
|
||||
|
||||
- The MDM server is not always notified when a host unenrolls. As a result, we perform cleanup during host enrollment since it's impossible to reliably determine whether a host is enrolling for the first time.
|
||||
- Special MDM actions are triggered when a host is deleted via the UI.
|
||||
|
||||
All lifecycle-related actions are implemented in the `HostLifecycle` struct. A great way to familiarize yourself with the different MDM actions is to search for the usages of the different `HostAction`s we have.
|
||||
|
||||
We use the terminology "turn on" and "turn off" to align with the language used by the product group, which is generally associated with enrollment and unenrollment.
|
||||
|
||||
### SCEP Renewals
|
||||
|
||||
MicroMDM has documented the intricacies of SCEP certificate renewals in detail: [MicroMDM SCEP Documentation](https://github.com/micromdm/micromdm/wiki/Device-Identity-Certificate-Expiration).
|
||||
|
||||
In Fleet, we issue certificates with a 1-year validity period. To renew certificates, we send a new enrollment profile via the `InstallProfile` command.
|
||||
|
||||
The command to install the profile is queued in the `renew_scep_certificates` job, which is part of the `cleanups_then_aggregation` cron schedule.
|
||||
|
||||
It's important to note that when sending a new enrollment profile, certain fields must remain unchanged. Apple has documented these restrictions here: [Apple MDM Profile Restrictions](https://github.com/apple/device-management/blob/85fae8ac896578447f8fcb07ff6c976128133a9c/mdm/profiles/com.apple.mdm.yaml#L1).
|
||||
|
||||
### Puppet module
|
||||
|
||||
The implementation of the Puppet module is described in detail at: `ee/tools/puppet/fleetdm/CONTRIBUTING.md`
|
||||
|
||||
### MDM migrations
|
||||
|
||||
Windows MDM is more flexible when it comes to switching MDM servers, so MDM migrations are generally not a big deal.
|
||||
|
||||
Apple MDM is more strict, and we have built two different flows:
|
||||
|
||||
1. The "regular" flow is what most customers will use, involve `fleetd` guiding the user through the migration to perform manual steps. The user documentation for this flow is https://fleetdm.com/guides/mdm-migration
|
||||
2. The "seamless" flow allows customers with access to their MDM database and ownership of the domain used as the `ServerURL` in the enrollment profile to migrate the devices without user action. The user documentation for this flow is https://fleetdm.com/guides/seamless-mdm-migration
|
||||
1. The proxy for the seamless flow lives in `./tools/mdm/migration/mdmproxy/`
|
||||
2. The tool to extract data from MicroMDM lives in `./tools/mdm/migration/micromdm/touchless/`
|
||||
|
||||
### Disk encryption
|
||||
|
||||
Enabling and retrieving the disk encryption keys for a host behaves differently depending on the OS.
|
||||
|
||||
After the key is retrieved, it's stored in the `host_disk_encryption_keys` table. The value for the key is encrypted using Fleet's CA certificate, and thus can only be decrypted if you have the CA private key.
|
||||
|
||||
**FileVault (macOS)**
|
||||
|
||||
For macOS, disk encryption involves a two step process:
|
||||
|
||||
1. Sending a profile with two payloads:
|
||||
1. A Payload to configure how the disk is going to be encrypted
|
||||
2. A Payload to configure the escrow of the encryption key
|
||||
|
||||
2. Retrieving the disk encryption key:
|
||||
1. Via osquery, we grab the (encrypted) disk encryption key
|
||||
2. In a cron job, we verify that we're able to decrypt the key. It's necessary to verify if a key is encrypted because we could have grabbed a key generated by a third-party MDM, or an invalid key.
|
||||
|
||||
If we're not able to decrypt the key for a host, the key needs to be rotated. Rotation happens silently by:
|
||||
|
||||
1. The server sends a notification to orbit, notifying that the key couldn't be decrypted.
|
||||
2. orbit installs an authorization plugin named [Escrow Buddy](https://github.com/macadmins/escrow-buddy) that performs the key rotation the next time the user logs in.
|
||||
3. Fleet retrieves and tries to validate the key again.
|
||||
|
||||
**BitLocker (Windows)**
|
||||
|
||||
Disk encryption in Windows is performed entirely by orbit.
|
||||
|
||||
When disk encryption is enabled, the server sends a notification to orbit, who calls the [Win32_EncryptableVolume class](https://learn.microsoft.com/en-us/windows/win32/secprov/getencryptionmethod-win32-encryptablevolume) to encrypt/decrypt the disk and generate an encryption key.
|
||||
|
||||
After the disk is encrypted, orbit sends the key back to the server using an orbit-authenticated endpoint (`POST /api/fleet/orbit/disk_encryption_key`)
|
||||
|
||||
### Load testing
|
||||
|
||||
osquery-perf supports MDM load testing for Windows and Apple devices. Under the hood it uses the `mdmtest` package to simulate MDM clients.
|
||||
|
||||
Documentation about setting up load testing for MDM can be found in ./infrastructure/loadtesting/terraform/readme.md
|
||||
|
||||
### ADE
|
||||
|
||||
For a high-level overview of how ADE works please check the [glossary](https://github.com/fleetdm/fleet/blob/main/tools/mdm/apple/glossary-and-protocols.md
|
||||
)
|
||||
|
||||
Below is a summary of Fleet-specific behaviors for ADE.
|
||||
|
||||
### Sync
|
||||
|
||||
Sincronization of devices from all ABM tokens uploaded to Fleet happen in the `dep_syncer` cron job, which runs every 30 seconds.
|
||||
|
||||
We keep a record of all devices ingested via the ADE sync in the `host_dep_assignments` table. Entries in this table are soft-deleted.
|
||||
|
||||
On every run, we pull the list of added/modified/deleted devices and:
|
||||
|
||||
1. If the host was added/modified, we:
|
||||
1. Create/match a row in the `hosts` table for the new host. This allows IT admin to move the host between teams before it turns on MDM or has `fleetd` installed.
|
||||
1. Assign the corresponding JSON profile to each host using ABM's APIs.
|
||||
2. If the host was deleted, we soft delete the `host_dep_assignments` entry
|
||||
|
||||
#### Special case: host in ABM is deleted in Fleet
|
||||
|
||||
If an IT admin deletes a host in the UI/API, and we have a non-deleted entry in `host_dep_assignments` for the host, we immediately create a new host entry as if the device was just ingested from the ABM sync.
|
||||
|
||||
### IdP integration
|
||||
|
||||
If the IT admin configured an MDM IdP integration, we change the `configuration_web_url` value in the JSON profile to be `{server_url}/mdm/sso`, this page initiates the SSO flow in the setup assistant webview.
|
||||
|
||||
Key points about he IdP flow:
|
||||
|
||||
1. The SSO flow ends with a callback to the Fleet server which contains information about the user that just logged in. We store this information in the `mdm_idp_accounts` table. Because at this point we don't know from which host UUID the request is coming in, we generate a random UUID as the key to look up this information.
|
||||
2. The Fleet server responds with an enrollment profile, that contains a special `ServerURL` with a query parameter `enrollment_reference`, this parameter has the random UUID generated in step 1.
|
||||
3. During MDM enrollment, we grab the `enrollment_reference` parameter, if present, and we try to match it to a host. This allows us to link end user IdP accounts used during enrollment with a host.
|
||||
4. Before releasing the device from awaiting configuration, we send an `AccountConfiguration` command to the host, to pre-set the macOS local account user name to the value we got stored in `mdm_idp_accounts`
|
||||
|
||||
|
|
@ -11,19 +11,19 @@ Resources:
|
|||
- [SCEP summary](#scep-summary) below
|
||||
- [RFC 8894](https://datatracker.ietf.org/doc/html/rfc8894)
|
||||
|
||||
### DEP: Device Enrollment Program
|
||||
### ADE: Automatic Device Enrollment (formerly DEP)
|
||||
|
||||
A device enrolled via DEP prompts the user to enroll in MDM during the initial
|
||||
A device enrolled via ADE prompts the user to enroll in MDM during the initial
|
||||
device setup process (right after macOS is installed.)
|
||||
|
||||
DEP is also called "automatic" enrollment because it doesn't require user
|
||||
ADE is also called "automatic" enrollment because it doesn't require user
|
||||
action to download and activate a profile like [manual
|
||||
enrollment](#manual-enrollment) does.
|
||||
|
||||
Resources:
|
||||
|
||||
- [DEP Workflow Summary](#dep-workflow-summary)
|
||||
- [MDM protocol specification](https://developer.apple.com/business/documentation/MDM-Protocol-Reference.pdf)
|
||||
- [ADE Workflow Summary](#ade-workflow-summary)
|
||||
- [MDM protocol specification](https://developer.apple.com/documentation/devicemanagement)
|
||||
|
||||
### Manual enrollment
|
||||
|
||||
|
|
@ -33,8 +33,8 @@ profile](#enrollment-profile).
|
|||
|
||||
### ABM: Apple Business Manager
|
||||
|
||||
Interface to administer Devices and MDM servers, mainly used for [DEP
|
||||
enrollment](#dep-enrollment).
|
||||
Interface to administer Devices and MDM servers, mainly used for [ADE
|
||||
enrollment](#ade-enrollment).
|
||||
|
||||
Can be accessed at https://business.apple.com/ .
|
||||
|
||||
|
|
@ -73,9 +73,9 @@ to enroll a device to an MDM server.
|
|||
For [manual enrollment](#manual-enrollment) the profile needs to be downloaded
|
||||
and installed by the user.
|
||||
|
||||
For [DEP enrollment](#dep-device-enrollment-program) the enrollment profile is downloaded from the MDM server specified in the DEP JSON profile (see below), fields `url` and `configuration_web_url`.
|
||||
For [ADE enrollment](#ade-device-enrollment-program) the enrollment profile is downloaded from the MDM server specified in the ADE JSON profile (see below), fields `url` and `configuration_web_url`.
|
||||
|
||||
### DEP profile
|
||||
### ADE profile
|
||||
|
||||
This (JSON) profile is used to configure a device in Apple Business Manager.
|
||||
It contains all the necessary information that a device needs to automatically enroll to an MDM server during device setup.
|
||||
|
|
@ -213,9 +213,9 @@ out a push notification to the device, then:
|
|||
To see all available commands, look under "Support for macOS Requests" in the
|
||||
MDM Protocol Reference.
|
||||
|
||||
### DEP Workflow Summary
|
||||
### ADE Workflow Summary
|
||||
|
||||
In order to get information about devices enrolled through DEP, the MDM server
|
||||
In order to get information about devices enrolled through ADE, the MDM server
|
||||
needs to communicate with Apple servers periodically.
|
||||
|
||||
The workflow looks like:
|
||||
|
|
@ -228,10 +228,10 @@ The workflow looks like:
|
|||
`GET https://mdmenrollment.apple.com/devices/sync` to get
|
||||
information about newly enrolled devices and changes on devices already
|
||||
enrolled.
|
||||
3. The MDM server defines and assigns DEP profiles (JSON) to devices using `POST
|
||||
3. The MDM server defines and assigns [ADE profiles](https://developer.apple.com/documentation/devicemanagement/profile) (JSON) to devices using `POST
|
||||
https://mdmenrollment.apple.com/profile` and `PUT
|
||||
https://mdmenrollment.apple.com/profile/devices`
|
||||
4. The MDM server removes DEP profiles (JSON) from a device using `DELETE
|
||||
4. The MDM server removes ADE profiles (JSON) from a device using `DELETE
|
||||
https://mdmenrollment.apple.com/profile/devices`
|
||||
|
||||
### DDM: Declarative Device Management
|
||||
|
|
@ -247,4 +247,4 @@ All DDM messages are JSON messages embedded (base64 encoded) within XML messages
|
|||
Resources:
|
||||
- [WWDC21](https://developer.apple.com/videos/play/wwdc2021/10131)
|
||||
- [WWDC22](https://developer.apple.com/videos/play/wwdc2022/10046)
|
||||
- [WWDC23](https://developer.apple.com/videos/play/wwdc2023/10041)
|
||||
- [WWDC23](https://developer.apple.com/videos/play/wwdc2023/10041)
|
||||
|
|
|
|||
Loading…
Reference in a new issue