Perhaps someone has done this before, I didn’t really search around for it before I put this workflow together.
As we know, the jamf binary does not use APNs, so we haven’t had a way to “send a push command” to call the jamf binary for things like ‘jamf recon’, ‘jamf policy’, etc.. Until now. Sorta.
Here is my workflow for achieving this.
Create a LaunchDaemon that watches for a particular Managed Preference (MCX) plist
Run a script via the LaunchDaemon that reads the MCX file for the jamf verb (recon, policy, etc)
Create a Configuration Profile with the “Custom” payload to push the MCX file
Scope the Configuration Profile to a Static Group
Add a Mac to the static group to force a call to the jamf binary via MDM/APNs
File Name: /Library/LaunchDaemons/com.yourdomain.daemon.mdm_trigger.plist
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.yourdomain.daemon.mdm_trigger</string> <key>ProgramArguments</key> <array> <string>sh</string> <string>-c</string> <string>/usr/local/bin/mcx_watcher.sh</string> </array> <key>WatchPaths</key> <array> <string>/Library/Managed Preferences/com.yourdomain.mdm_trigger.plist</string> </array> </dict> </plist>
File Name: mcx_watcher.sh
#!/bin/sh COMMAND=$(defaults read /Library/Managed Preferences/com.yourdomain.mdm_trigger Command) /usr/local/jamf/bin/jamf $COMMAND exit 0
File Name: com.yourdomain.mdm_trigger.plist (make sure it matches the “WatchPaths” in the LaunchDaemon)
Value for the Command key: the jamf verb (ie recon, policy, manage, etc)
Upload this to the "Custom" payload in a Configuration Profile
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Command</key> <string>recon</string> </dict> </plist>
The Static Group
Group Name: Recon Trigger
Scope the Configuration Profile to this group
Adding a Mac to this group puts it in scope for the Configuration Profile
Rather than changing the scope of the profile itself, which prompts if you want to “Distribute to All” each time, this just quietly scopes and un-scopes the the target Mac(s) to the Config Profile
Each time you add a Mac to this static group, it pushes the plist file which the LaunchDaemon is watching for, which triggers the script to read the “verb” for the jamf command, then runs the 'jamf verb' command
There may be a good way to use the API to trigger this process, but this basic workflow is working as a proof of concept.
Package the script and the LaunchDaemon with composer
Add a “postinstall” script to the pkg:
#!/bin/sh chown 0:0 /usr/local/bin/mcx_watcher.sh chmod u+x /usr/local/bin/mcx_watcher.sh chown 0:0 /Library/LaunchDaemons/com.yourdomain.daemon.mdm_trigger.plist chmod 644 /Library/LaunchDaemons/com.yourdomain.daemon.mdm_trigger.plist launchctl load /Library/LaunchDaemons/com.yourdomain.daemon.mdm_trigger.plist exit 0
@B_Hanson Thanks for posting this. User @Rajeev described something like it in a thread named SuperMDM, but has since deleted the contents of the post describing his technique, and the GitHub page referenced in the thread is no longer accessible.
One extension I'd suggest for your approach is to handle additional parameters for command in addition to verb. That'd allow triggering a specific policy by adding -event or -id to the policy command.