> For the complete documentation index, see [llms.txt](https://newdocs.keeper.io/en/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://newdocs.keeper.io/en/keeperpam/endpoint-privilege-manager/deployment/deploy-with-macos/macos-deployment-via-mdm.md).

# macOS Deployment via MDM

<figure><img src="https://762006384-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MJXOXEifAmpyvNVL1to%2Fuploads%2FBfqNPwMALisBMotziGAX%2Fimage.png?alt=media&amp;token=4715cc90-7146-473b-84b5-6548f1c31f9a" alt=""><figcaption></figcaption></figure>

This page describes how to deploy Keeper Endpoint Privilege Manager (Keeper EPM) to managed Macs through an MDM platform (Jamf, Intune, Kandji, Mosyle, or equivalent) without user interaction. A correct MDM deployment delivers three configuration profiles, installs the signed `.pkg`, and optionally triggers a reboot so the system extension and Full Disk Access (FDA) grants take effect.

This guide focuses on what Keeper EPM requires from your MDM. It assumes you already know how to upload profiles, assign device groups, and push `InstallEnterpriseApplication` (or equivalent) commands in your MDM product. For interactive install steps, service management, and manual registration, see [Deploy with macOS](/en/keeperpam/endpoint-privilege-manager/deployment/deploy-with-macos.md).

{% hint style="info" %}
**Minimum KEPM Version:** 2.1.1.2 introduces headless macOS MDM install support, including automatic system extension activation when the pre-approval profile is present and suppression of the Post Install Steps window on a compliant MDM deploy.
{% endhint %}

***

### What MDM Must Deliver

A compliant MDM deployment consists of three configuration profiles, the signed installer package, and an optional restart command. All profiles must be scoped to the **System** (device) channel.

<table><thead><tr><th width="53.6666259765625">#</th><th width="169">Profile</th><th width="188.6666259765625">Payload Type</th><th>Purpose</th></tr></thead><tbody><tr><td>1</td><td>Registration Key</td><td><code>com.apple.ManagedClient.preferences</code></td><td>Writes the registration token so the agent registers automatically after install</td></tr><tr><td>2</td><td>System Extension Pre-Approval</td><td><code>com.apple.system-extension-policy</code></td><td>Pre-approves the Endpoint Security extension for silent activation</td></tr><tr><td>3</td><td>Full Disk Access (PPPC)</td><td><code>com.apple.TCC.configuration-profile-policy</code></td><td>Grants Full Disk Access to KEPM binaries and the system extension</td></tr></tbody></table>

<table><thead><tr><th width="129.333251953125">Item</th><th>Requirement</th></tr></thead><tbody><tr><td>Package</td><td>Signed <code>keeper-privilege-manager.&#x3C;version>.&#x3C;arch>.pkg</code> (Developer ID Installer)</td></tr><tr><td>Team ID</td><td><code>234QNB7GCA</code> (Callpod Inc. / Keeper Security production builds)</td></tr><tr><td>Profile Scope</td><td>All profiles at <strong>System</strong> scope (device channel)</td></tr><tr><td>Reboot</td><td><strong>Recommended</strong> after first install so extension activation and TCC settle</td></tr></tbody></table>

{% hint style="info" %}
**`PayloadIdentifier` is not product-matched.** Outer and inner identifiers must be unique in your MDM tenant, and GUID-style values (common with Intune) are supported. Keeper EPM detects the system extension and FDA profiles by **payload content**, not by a Keeper-specific profile ID string.
{% endhint %}

When all three profiles are installed, the package is on disk, the extension reports `[activated enabled]`, and the activated build matches the embedded system extension version, Keeper EPM does not display the Post Install Steps window. After an in-place PKG upgrade with a newer embedded extension that is already activated, `com.keeper.keeperse` silently submits a replace request for both MDM and Manual installs. First-time silent activation still requires the system extension MDM profile.

***

### Deployment Order

Push all configuration profiles before the install package. The profiles must be present on the device before the package runs, but they can be pushed well in advance — even hours or days earlier as part of a device's baseline configuration. The order below reflects a typical single-session deployment:

1. Registration Key profile
2. System Extension profile
3. FDA (PPPC) profile
4. `InstallEnterpriseApplication` (`.pkg`)
5. `RestartDevice` (optional, recommended on first deploy)

<table><thead><tr><th width="200.6666259765625">Rule</th><th>Why It Matters</th></tr></thead><tbody><tr><td>Profiles present before the package runs</td><td>macOS evaluates the System Extension and PPPC payloads against Keeper EPM's Team ID and bundle identifiers, not against files on disk. As long as the profiles are installed before the package executes, TCC grants and system extension activation apply cleanly when the binaries land.</td></tr><tr><td>Reboot after first deploy</td><td>The system extension host app (<code>com.keeper.keeperse</code> LaunchDaemon) auto-submits the extension activation request when the system extension profile is present. A reboot ensures activation, FDA application, and registration startup jobs all run in a clean boot sequence.</td></tr><tr><td>Brief pause between MDM commands</td><td>A short delay (typically one to two seconds) lets the device check in and apply each payload before the next command arrives. The exact interval is environment-dependent — network conditions, MDM platform, and device hardware all affect check-in timing, so tune this to what works reliably in your environment.</td></tr></tbody></table>

{% hint style="info" %}
**Note:** The three profiles (Registration Key, System Extension, FDA) are shown separately for clarity, but there is no requirement to deliver them as three distinct `.mobileconfig` files. All three payloads can be combined into a single configuration profile if that better suits your MDM workflow. Keeper EPM detects the System Extension and FDA payloads by content, not by which profile carries them.
{% endhint %}

***

### Profile 1 — Registration Key

**Payload Type:** `com.apple.ManagedClient.preferences`

**Writes To:** `/Library/Managed Preferences/com.keeper.keeper-privilege-manager.plist`

**Key:** `KEEPERREGCODE` — your deployment registration token, formatted as `hostname:deployment-uid:private-key`

#### Example Payload

```xml
<key>PayloadType</key>
<string>com.apple.ManagedClient.preferences</string>
<key>PayloadContent</key>
<dict>
  <key>com.keeper.keeper-privilege-manager</key>
  <dict>
    <key>Forced</key>
    <array>
      <dict>
        <key>mcx_preference_settings</key>
        <dict>
          <key>KEEPERREGCODE</key>
          <string>YOUR_REGISTRATION_TOKEN</string>
        </dict>
      </dict>
    </array>
  </dict>
</dict>
```

After install and service start, Keeper EPM reads the managed preference and registers automatically. No registration dialog is shown in MDM mode.

#### Verify on Device

```bash
# Content match (PayloadIdentifier may be a GUID)
profiles show -type configuration -output stdout-xml | grep -A5 'KEEPERREGCODE'
sudo plutil -p "/Library/Managed Preferences/com.keeper.keeper-privilege-manager.plist" 2>/dev/null | grep KEEPERREGCODE
curl -ks https://localhost:6989/api/Keeper/registration | python3 -m json.tool
```

***

### Profile 2 — System Extension Pre-Approval

**Payload Type:** `com.apple.system-extension-policy`

**Extension Bundle ID:** `com.keeper.keeper-privilege-manager.monitor`

**Team ID:** `234QNB7GCA`

**Extension Type:** `EndpointSecurityExtension`

#### Example Payload

```xml
<key>PayloadType</key>
<string>com.apple.system-extension-policy</string>
<key>AllowedSystemExtensions</key>
<dict>
  <key>234QNB7GCA</key>
  <array>
    <string>com.keeper.keeper-privilege-manager.monitor</string>
  </array>
</dict>
<key>AllowedSystemExtensionTypes</key>
<dict>
  <key>234QNB7GCA</key>
  <array>
    <string>EndpointSecurityExtension</string>
  </array>
</dict>
<key>AllowUserOverrides</key>
<false/>
```

{% hint style="info" %}
MDM pre-approval alone does not register the extension. Keeper EPM 2.1.1.2 and later automatically submits `OSSystemExtensionRequest` when a system-extension-policy profile approving this Team ID and bundle ID is installed and the host app launches. Detection is by that payload content; the profile's `PayloadIdentifier` may be any unique value, including an Intune-assigned GUID.
{% endhint %}

#### Verify on Device

```bash
# Content match — do not rely on a specific PayloadIdentifier string
profiles show -type configuration -output stdout-xml | grep -E 'system-extension-policy|keeper-privilege-manager.monitor|234QNB7GCA'
systemextensionsctl list | grep keeper-privilege-manager.monitor
# Expect: [activated enabled]
```

***

### Profile 3 — Full Disk Access (PPPC)

**Payload Type:** `com.apple.TCC.configuration-profile-policy`

**Service:** `SystemPolicyAllFiles` (TCC key `kTCCServiceSystemPolicyAllFiles`)

Keeper EPM needs FDA on the **wrapper app**, **daemon**, **host app**, and **system extension**. Each PPPC entry's `CodeRequirement` must use the binary's real codesign `Identifier` — not a parent or prefix ID.

#### Required FDA Targets

| UI Name (System Settings)                   | Bundle ID / Path                                            | Codesign `Identifier` in CodeRequirement                  |
| ------------------------------------------- | ----------------------------------------------------------- | --------------------------------------------------------- |
| KeeperPrivilegeManager                      | `com.keeper.endpoint-privilege-manager.launcher`            | `com.keeper.endpoint-privilege-manager.launcher`          |
| (wrapper path)                              | `/Library/Keeper/KeeperPrivilegeManager.app`                | same as launcher                                          |
| (daemon signing ID)                         | `com.keeper.endpoint-privilege-manager.privilege-manager`   | `com.keeper.endpoint-privilege-manager.privilege-manager` |
| (daemon path)                               | `/Library/Keeper/sbin/KeeperPrivilegeManager`               | same as daemon                                            |
| Keeper Endpoint Privilege Manager           | `com.keeper.keeper-privilege-manager`                       | `com.keeper.keeper-privilege-manager`                     |
| Keeper Endpoint Privilege Manager Extension | `com.keeper.keeper-privilege-manager.monitor`               | `com.keeper.keeper-privilege-manager.monitor`             |
| (embedded extension path)                   | path under host app `Contents/Library/SystemExtensions/...` | same as monitor                                           |

{% hint style="danger" %}
Do **not** use bare `com.keeper.endpoint-privilege-manager` or `.service` — production builds use `.launcher` (wrapper) and `.privilege-manager` (daemon). Do **not** assume the daemon inherits FDA from the wrapper after `exec`; grant the daemon explicitly.
{% endhint %}

#### PPPC Rules

* Use **`Allowed`** only (`<integer>1</integer>` or `<true/>`). Do not combine `Allowed` and `Authorization` on the same entry — macOS rejects the payload.
* `CodeRequirement` `identifier "..."` must match `codesign -dv` `Identifier=` for that binary. Team ID `234QNB7GCA` for production (Callpod Inc.).
* Set outer profile **`PayloadScope`** to **System**.
* Generate **unique** `PayloadUUID` and `PayloadIdentifier` values when creating your own profile. GUIDs are supported.
* `MDMOverrides.plist` listing `Allowed=1` is necessary but not sufficient — a mismatched `CodeRequirement` still leaves runtime FDA ineffective (for example, Downloads returns EPERM).

#### Three-Way Identifier Alignment

For an MDM PPPC grant to apply silently — without prompting the user in System Settings — three identifiers must all match for each target process:

<table><thead><tr><th width="67.6666259765625">#</th><th width="406.6666259765625">Where</th><th>Must Equal</th></tr></thead><tbody><tr><td>1</td><td>App bundle code signature (<code>codesign -dvvvv … | grep ^Identifier</code>)</td><td>The bundle ID in the PPPC profile entry</td></tr><tr><td>2</td><td><code>CFBundleIdentifier</code> in the app's <code>Info.plist</code></td><td>Same as above</td></tr><tr><td>3</td><td><code>AssociatedBundleIdentifiers</code> array in the LaunchDaemon plist that launches the app</td><td>Same as above</td></tr></tbody></table>

If any of the three is missing or mismatched, macOS cannot correlate the PPPC grant to the running process. The user will be prompted to approve FDA manually in **System Settings → Privacy & Security → Full Disk Access**, even though the MDM profile shows as installed.

#### Verify KeeperPrivilegeManager Alignment

```bash
# All three should return com.keeper.endpoint-privilege-manager.launcher
codesign -dvvvv /Library/Keeper/KeeperPrivilegeManager.app 2>&1 | grep ^Identifier
/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" \
  /Library/Keeper/KeeperPrivilegeManager.app/Contents/Info.plist
/usr/libexec/PlistBuddy -c "Print :AssociatedBundleIdentifiers:0" \
  /Library/LaunchDaemons/com.keeper.keeper-privilege-manager.plist
```

{% hint style="info" %}
`AssociatedBundleIdentifiers` was introduced in macOS 13.0 (Ventura). It is silently ignored on older macOS versions and causes no error. The Keeper EPM minimum system version is macOS 13.0, so this key is safe to include unconditionally.
{% endhint %}

#### Verify FDA Profile Application

```bash
# Content match — PPPC grants for KEPM clients (PayloadIdentifier may be a GUID)
profiles show -type configuration -output stdout-xml | grep -E 'SystemPolicyAllFiles|endpoint-privilege-manager|keeper-privilege-manager'
```

For deep TCC verification, inspect `MDMOverrides.plist`. The calling application (for example, Terminal) must itself have FDA to read this file:

```bash
sudo plutil -p "/Library/Application Support/com.apple.TCC/MDMOverrides.plist" | grep -i keeper
```

***

### Package Installation

Host the signed `.pkg` on HTTPS reachable from managed Macs, then push via MDM:

* **Request Type:** `InstallEnterpriseApplication`
* **Manifest:** software-package asset with pkg URL and optional SHA-256 chunk manifest

#### Requirements

* Valid **Developer ID Installer** signature (Callpod Inc.)
* The Mac can resolve DNS, complete TLS, and reach the URL through any firewall
* The web server returns HTTP **200** and directory permissions allow the server to read the file

{% hint style="info" %}
MDM returning **Acknowledged** for `InstallEnterpriseApplication` does not guarantee the package installed. Check device logs or on-disk paths if install appears to fail.
{% endhint %}

#### Verify on Device

```bash
pkgutil --pkgs | grep -i keeper
ls -ld "/Library/Keeper" "/Applications/Keeper"
launchctl list | grep keeper
```

Expected launchd entries include:

* `com.keeper.keeper-privilege-manager` (main service)
* `234QNB7GCA.com.keeper.keeper-privilege-manager.monitor` (system extension)
* `com.keeper.keeperse` (host app for extension activation)

***

### Expected End State

After a successful MDM deploy and reboot:

| Check                     | Expected Result                                                                               |
| ------------------------- | --------------------------------------------------------------------------------------------- |
| All three Keeper profiles | Installed (`profiles show -type configuration`)                                               |
| System extension          | `[activated enabled]` in `systemextensionsctl list`                                           |
| Post Install Steps window | **Not shown**                                                                                 |
| Agent registration        | `IsRegistered: true` from `/api/Keeper/registration`                                          |
| FDA in System Settings    | Toggles may show **OFF** even when MDM grants are active — this is normal for MDM-managed FDA |

***

### Quick Verification Checklist

Run on a managed Mac after deployment:

```bash
# Profiles — match product content (identifiers may be GUIDs)
profiles show -type configuration -output stdout-xml | grep -E 'system-extension-policy|SystemPolicyAllFiles|KEEPERREGCODE|keeper-privilege-manager.monitor'

# Extension
systemextensionsctl list | grep keeper-privilege-manager.monitor

# Registration
curl -ks https://localhost:6989/api/Keeper/registration

# Daemons
launchctl list | grep keeper
```

All checks should pass before rolling out to production groups.

***

### Troubleshooting

| Symptom                                                            | Likely Cause                                                                           | Action                                                                                                                                                                                                                |
| ------------------------------------------------------------------ | -------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| FDA profile installed but no TCC grants                            | FDA pushed before package                                                              | Re-push FDA profile **after** install                                                                                                                                                                                 |
| FDA profile installed, user still prompted to approve FDA manually | `AssociatedBundleIdentifiers` missing from LaunchDaemon plist, or identifiers mismatch | Verify three-way alignment: codesign ID = `CFBundleIdentifier` in `Info.plist` = `AssociatedBundleIdentifiers[0]` in `/Library/LaunchDaemons/com.keeper.keeper-privilege-manager.plist`; use KEPM 2.1.0.1789 or later |
| FDA profile rejected by Mac                                        | Invalid PPPC payload (`Allowed` + `Authorization`, bad UUIDs)                          | Validate the payload with `profiles show`; ensure a single control keyword per entry                                                                                                                                  |
| Extension not `[activated enabled]`                                | System extension profile missing or host app not run                                   | Confirm sysext policy content (Team ID + monitor bundle ID); reboot or re-run deploy                                                                                                                                  |
| Post Install Steps window shown (FDA only)                         | FDA PPPC content missing at host app launch                                            | Confirm PPPC `SystemPolicyAllFiles` grants; re-push FDA                                                                                                                                                               |
| Agent not registered                                               | Regcode managed preference missing or old KEPM build                                   | Confirm `/Library/Managed Preferences/com.keeper.keeper-privilege-manager.plist`; use KEPM 2.1.1.2 or later                                                                                                           |
| Package Acknowledged but not installed                             | HTTP 403, bad signature, hash mismatch                                                 | Fix hosting; verify signature with `pkgutil --check-signature`                                                                                                                                                        |
| Post Install Steps window after Intune deploy                      | Profile identifiers are GUIDs (expected)                                               | Verify payload **content** with `profiles … -output stdout-xml`, not Keeper reverse-DNS identifiers                                                                                                                   |

***

### Related Pages

* [System Extension Configuration](/en/keeperpam/endpoint-privilege-manager/deployment/deploy-with-macos/macos-system-extension-configuration.md)
* [Protected Path Design Intent](/en/keeperpam/endpoint-privilege-manager/deployment/deploy-with-macos/protected-path-design-intent.md)
* [Two-Layer Bypass Architecture](/en/keeperpam/endpoint-privilege-manager/deployment/deploy-with-macos/two-layer-bypass-architecture.md)
* [Signed Certificate Support](/en/keeperpam/endpoint-privilege-manager/deployment/deployment-reference/signed-certificate-support.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://newdocs.keeper.io/en/keeperpam/endpoint-privilege-manager/deployment/deploy-with-macos/macos-deployment-via-mdm.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
