Skip to main content
Question

Solve Jamf agent and MDM problems automatically?

  • December 12, 2025
  • 9 replies
  • 156 views

howie_isaacks
Forum|alt.badge.img+23

Like a lot of other Jamf admins I see a small number of Macs that have stopped checking in and sending inventories. I see some that appear to be having problems with MDM. I am curious about what everyone else is doing to solve these issues. Since we also use some other management agents I can see that a lot of the Macs that are having Jamf agent issues are working with the other management agents. They appear to be in use. I wrote a script that leverages the Jamf Management Framework redeployment API command. I was able to deploy it through Tanium to some systems that had stopped checking in and sending inventories. This has worked on some but not on others. For the systems having MDM issues, this may not work since the Jamf Management framework redeployment using the API needs MDM functionality to work. Here’s the current version of the script that I created.

#!/bin/zsh --no-rcs

:<<ABOUT_THIS_SCRIPT
---------------------------------------------------------------------------------------------------
Uses the Jamf Pro API to run the Jamf management framework command to re-enroll a Mac. Before the
command is run the computer is temporarily added to a static group that is excluded from running
enrollment policies that will be visible to the user.

USAGE:
1 - Add your Jamf Pro server URL, API client ID and secret to the variables for Jamf Pro API
login.

2 - Create a static group and exclude it from enrollment policies that would be visible to users.
Add the group ID to the variable "group_id". Exclude the group from enrollment policies. Comment
out the section that excludes the Mac from enrollment policies if this is not needed.

EXPERIMENTAL: Jamf Pro parameter 7 can be used to trigger the Jamf "removeFramework" command just
before running the Jamf management framework API command. Specify "yes" in parameter 7. If this script
is used with another management system, change the "remove_framework" variable to ="$1" to be able to
run the script with an argument to activate the removal of the Jamf framework.

VERSION 1

12/11/2025 | Howie Canterbury
---------------------------------------------------------------------------------------------------
ABOUT_THIS_SCRIPT

###########################
# OPTIONS #
###########################

remove_framework="$7"

###############################################################################
# JAMF PRO API LOGIN #
# Parameter 4: API client ID #
# Parameter 5: API client secret #
# Parameter 6: Enter "yes" to validate API login #
###############################################################################

# Jamf Pro API login
url="YOUR_SERVER"
client_id="$4"
client_secret="$5"
verify="$6"

# Jamf API authentication function
jamfAPI_auth() {
response=$(curl --silent --location --request POST "${url}/api/oauth/token" \
--header "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "client_id=${client_id}" \
--data-urlencode "grant_type=client_credentials" \
--data-urlencode "client_secret=${client_secret}")
token=$(echo "$response" | plutil -extract access_token raw -)
token_expires_in=$(echo "$response" | plutil -extract expires_in raw -)
token_expiration_epoch=$(($current_epoch + $token_expires_in - 1))
}

# Start authenticated API session
jamfAPI_auth

###############################################################################
# VALIDATE API LOGIN #
# The token and expiration time will be echoed into the script output #
# to verify that the API login credentials provided are working. #
###############################################################################

if [[ "$verify" == "yes" ]]; then
echo "API token: ${token}"
echo "Token expires in: ${token_expires_in} seconds"
fi

#####################################
# COMPUTER INFORMATION #
#####################################

# Computer serial number
serial=$(system_profiler SPHardwareDataType | grep Serial | /usr/bin/awk '{print $4}')
echo "Computer serial number is ${serial}"

# Jamf ID
jss_ID=$(curl -s -H "Accept: text/xml" -H "Authorization: Bearer ${token}" ${url}/JSSResource/computers/serialnumber/"$serial" | xmllint --xpath '/computer/general/id/text()' -)
echo "Computer JSS ID is ${jss_ID}"

###################################################################
# ADD COMPUTER TO ENROLLMENT POLICY EXCLUSION GROUP #
###################################################################
group_id=""

# Adding the computer to the enrollment policy exclusion group will prevent the ZTP policy from running after enrollment.
echo "Excluding ${serial} from enrollment policies..."
curl -X PUT "${url}/JSSResource/computergroups/id/${group_id}" -H "Authorization: Bearer ${token}" -H "Content-Type: application/xml" -d "<computer_group><computer_additions><computer><id>$jss_ID</id></computer></computer_additions></computer_group>"

###################################################################
# RUN JAMF MANAGEMENT FRAMEWORK COMMAND TO ENROLL THE MAC #
###################################################################

# Remove Jamf framework
if [[ "$remove_framework" == "yes" ]]; then
echo "Removing Jamf framework"
/usr/local/jamf/bin/jamf removeFramework
fi

# MDM action to install and run a Jamf quick add package to reinstall the Jamf management framework and trigger a re-enrolllment.
echo "Running Jamf management framework command to trigger re-enroll"
curl -X 'POST' \
"${url}/api/v1/jamf-management-framework/redeploy/${jss_ID}" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" \
-d ''

 

9 replies

Chubs
Forum|alt.badge.img+23
  • Jamf Heroes
  • December 12, 2025

I wrote a launchdaemon that did something similar in the past when I had users remove the framework so the device would auto-reenroll (pre-MDM).

A lot of what you’ve specified above can be automated using a CI/CD platform (like GitHub or power automate with web hooks) and smart groups in JAMF.  This would be an awesome automation to add to Jamf Routines though!



 


mattjerome
Forum|alt.badge.img+9
  • Jamf Heroes
  • December 12, 2025

Check out this JNUC 2024 presentation 

 


howie_isaacks
Forum|alt.badge.img+23
  • Author
  • Esteemed Contributor
  • December 12, 2025

I have been thinking of deploying a launch daemon that would run a script to do some checks on Jamf agent and MDM health. Once I have these created I can proactively deploy them to help keep the Jamf agent and MDM healthy. It’s a shame that Jamf does not provide this ability as a built-in feature.


Chubs
Forum|alt.badge.img+23
  • Jamf Heroes
  • December 15, 2025

I have been thinking of deploying a launch daemon that would run a script to do some checks on Jamf agent and MDM health. Once I have these created I can proactively deploy them to help keep the Jamf agent and MDM healthy. It’s a shame that Jamf does not provide this ability as a built-in feature.

I guess for me is: what would make the binary or MDM be considered “healthy”?  Would also be awesome to kickoff a reenroll on the device if it isn’t found in the associated database.  

I’m white boarding this now.  Thanks for the idea(s)


mattjerome
Forum|alt.badge.img+9
  • Jamf Heroes
  • December 15, 2025

I have been thinking of deploying a launch daemon that would run a script to do some checks on Jamf agent and MDM health. Once I have these created I can proactively deploy them to help keep the Jamf agent and MDM healthy. It’s a shame that Jamf does not provide this ability as a built-in feature.

I guess for me is: what would make the binary or MDM be considered “healthy”?  Would also be awesome to kickoff a reenroll on the device if it isn’t found in the associated database.  

I’m white boarding this now.  Thanks for the idea(s)

I’d say if it’s not checking in or collecting inventory it’s not healthy. There’s a jamf routine to redeploy the framework. That may fix it as those are MDM commands vs policies. But if it’s not reporting, mileage may vary. A LaunchDaemon with the self heal script may be worth exploring but that requires credentials for the API.


howie_isaacks
Forum|alt.badge.img+23
  • Author
  • Esteemed Contributor
  • December 22, 2025

@mattjerome The JNUC 2024 presentation you suggested that I watch gave me some good ideas. The profile for the Macs that show that they have not had check-ins helped identify Macs that appear to be in current use. Since they received the profile, that means that the Jamf management framework command sent using the API would work on them. It has for some of the Macs that received the profile. This was very helpful. Thanks!


Chubs
Forum|alt.badge.img+23
  • Jamf Heroes
  • December 22, 2025

The only issue with the API call is that it only resolves the binary issues.  Need something to resolve the MDM portion issues when they occur (because let’s face it, they do happen).


howie_isaacks
Forum|alt.badge.img+23
  • Author
  • Esteemed Contributor
  • December 22, 2025

The only issue with the API call is that it only resolves the binary issues.  Need something to resolve the MDM portion issues when they occur (because let’s face it, they do happen).

Right! Those always require re-enrolling a Mac, and sometimes they require using “jamf removeFramework” first. I have a few Macs that fail some MDM checks. The Jamf agent is working fine but MDM somehow breaks.


mattjerome
Forum|alt.badge.img+9
  • Jamf Heroes
  • December 22, 2025

@mattjerome The JNUC 2024 presentation you suggested that I watch gave me some good ideas. The profile for the Macs that show that they have not had check-ins helped identify Macs that appear to be in current use. Since they received the profile, that means that the Jamf management framework command sent using the API would work on them. It has for some of the Macs that received the profile. This was very helpful. Thanks!

Glad it worked out for you!