API Script to Unenroll macs from jamf

Olga1
New Contributor

Is there an API script that will un-enroll macs from jamf pro? Similar to web Management Commands of "remove mdm profile". I don't need the mac to be deleted from jamf entirely.

I want to use the API so that jamf itself sends the MDM command to uninstall the profile. If I create a policy, it will package it up and run it on the device.

Is it possible to use the API script to check for machines in a smart group? I want the script to be executed only on macs that have a certain PKG installed on it. 

Thank you

2 ACCEPTED SOLUTIONS

stevewood
Honored Contributor II
Honored Contributor II

You should be able to use the Classic API endpoint 'computercommands':

https://{{url}}/JSSResource/computercommands/command/UnmanageDevice/id/<deviceID>

 

Replace "<deviceID>" with the JSS ID of the computer.

View solution in original post

stevewood
Honored Contributor II
Honored Contributor II
11 REPLIES 11

stevewood
Honored Contributor II
Honored Contributor II

You should be able to use the Classic API endpoint 'computercommands':

https://{{url}}/JSSResource/computercommands/command/UnmanageDevice/id/<deviceID>

 

Replace "<deviceID>" with the JSS ID of the computer.

stevewood
Honored Contributor II
Honored Contributor II

And here's a link to the documentation on our Developer website:

https://developer.jamf.com/jamf-pro/reference/createcomputercommandbycommandandid 

Thank you Steve!

mm2270
Legendary Contributor III


What @stevewood said. This is possible using the classic API endpoint he referenced.

You will need to get the Jamf Computer ID for the command to be posted to the device, so you may need to first run an API call from the computer to Jamf to get it's own ID, and then use that as a variable for the above command.

Is it possible to use the API script to check for machines in a smart group? I want the script to be executed only on macs that have a certain PKG installed on it. 


Yes, you would create a Smart Group using the "Packages Installed By Casper" criteria (<-- old throw back name). Pick the package name from a list you can pull up and any Mac with that package installed on it, and has had an inventory collection run on it since then, will fall into that group.

Keep in mind the list that Jamf Pro displays when adding this criteria to a Smart Group is dependent on at least one Mac having had that package installed AND an inventory collection done on it, otherwise it may not show up in the list to choose from.

 

Olga1
New Contributor

Thank you.

In my case, I would like to remove mdm profile on multiple devices that I want to filter out by a certain PKG that was installed on them. 

I can save a Computer Advanced search with needed Criteria and display JSS Computer ID.

How do I use API to remove profiles only on devices on this search list?

 

sdagley
Esteemed Contributor II

@Olga1 @stevewood and @mm2270 have described the endpoint to use for un-managing a device and creating a targeting Smart Group, but could you clarify your statement "I want to use the API so that jamf itself sends the MDM command to uninstall the profile. If I create a policy, it will package it up and run it on the device"?

Do you want the script to run via a Policy on the device to be removed, or are you looking to run a script from your own Mac that would target the Macs in Smart Group you've created for removal? I'm reading it as the latter, in which case you can use the /computergroups/id/{id} endpoint to retrieve the list of Macs in scope for the smart group described by @mm2270 , parse the IDs from that result, then use the endpoint @stevewood lists to send the UnmanageDevice command.

Olga1
New Contributor

Hi,

I'm looking to run a script from my Mac that would target the Macs in a smart group or in a Computer Advanced search.

So I can use either the /computergroups/id/{id} for smart group or /advancedcomputersearches/id/{id} for Computer Advanced search.

How do I parse the IDs from that result? How should the command look like? should the ID's be separated by commas?

/computercommands/command/UnmanageDevice/id/<deviceID>

mm2270
Legendary Contributor III

Do you know the Computer Group ID from Jamf Pro that you're targeting? If so, something like this would parse the computer IDs for members of that group and string them together. And yes, according to Jamf's documentation, you separate multiple IDs by a comma (no space).

 

 

#!/bin/zsh

userName="adminName"
passWord="adminPassword"
jamfURL="https://your.jamf.url"
groupID="##" ## Put the group ID here

allIDs=$(/usr/bin/curl -H "Accept: application/xml" -su "${userName}:${passWord}" ${jamfURL}/JSSResource/computergroups/id/14 | /usr/bin/xpath -e '/computer_group/computers/computer/id/text()' 2>/dev/null | /usr/bin/tr '\n' ',')

/bin/echo "$allIDs"

 

 

From there, you can pass the $allIDs variable into another API command to send the UnmanageDevice to them all in one shot.

Note that I have never tried unmanaging a group of Macs all at once thru the API, so hopefully this works for you.

 

sdagley
Esteemed Contributor II

That

/usr/bin/tr '\n' ','

is going to leave a "," at the end of the list. You can remove it by adding a rev/cut/rev sequence:

/usr/bin/tr '\n' ',' | rev | cut -c2- | rev

 

mm2270
Legendary Contributor III

That's true. I did see that, but I wasn't sure if that extra , at the end would cause any issues. I suppose the API may balk at seeing an extra comma but no ID after it though.

And the cleanup can be done with sed as well. Less pipes.

 

/usr/bin/tr '\n' ',' | /usr/bin/sed 's/,$//'

 

 

sdagley
Esteemed Contributor II

Putting all of the posts from @stevewood , @mm2270 , and myself into an example script (actual sending of the UnmanageDevice command wasn't tested, and you'd definitely want to add some error checking):

 

#!/bin/bash

# Quick and dirty script to query a JSS for a list of computer IDs in a group, then send
# an UnmanageDevice command to those computers
#
# Written by @sdagley with input from @mm2270 and @stevewood

jssURL="https://yourjss.company.com:8443"

apiID="$(osascript -e 'Tell application "System Events" to display dialog "Enter a Jamf Pro API ID:" default answer ""' -e 'text returned of result' 2>/dev/null)"
apiPassword="$(osascript -e 'Tell application "System Events" to display dialog "Enter the password for the Jamf Pro API ID:" default answer ""' -e 'text returned of result' 2>/dev/null)"
groupID="$(osascript -e 'Tell application "System Events" to display dialog "Enter the group number to extract computer IDs from:" default answer ""' -e 'text returned of result' 2>/dev/null)"

GetJamfProAPIToken() {
	apiToken=""
	
    # This function uses Basic Authentication to get a new bearer token for API authentication.
    # Use user account's username and password credentials with Basic Authorization to request a bearer token.

    if [[ $(/usr/bin/sw_vers -productVersion | awk -F . '{print $1}') -lt 12 ]]; then
        apiToken=$(/usr/bin/curl -X POST --silent -u "${apiID}:${apiPassword}" "${jssURL}/api/v1/auth/token" | python -c 'import sys, json; print json.load(sys.stdin)["token"]')
    else
        apiToken=$(/usr/bin/curl -X POST --silent -u "${apiID}:${apiPassword}" "${jssURL}/api/v1/auth/token" | plutil -extract token raw -)
    fi
}

APITokenValidCheck() {
    # Verify that API authentication is using a valid token by running an API command
    # which displays the authorization details associated with the current API user. 
    # The API call will only return the HTTP status code.

    api_authentication_check=$(/usr/bin/curl --write-out %{http_code} --silent --output /dev/null "${jssURL}/api/v1/auth" --request GET --header "Authorization: Bearer ${apiToken}")
}

InvalidateToken() {
    # Verify that API authentication is using a valid token by running an API command
    # which displays the authorization details associated with the current API user. 
    # The API call will only return the HTTP status code.

    APITokenValidCheck

    # If the api_authentication_check has a value of 200, that means that the current
    # bearer token is valid and can be used to authenticate an API call.

    if [[ ${api_authentication_check} == 200 ]]; then

        # If the current bearer token is valid, an API call is sent to invalidate the token.

        authToken=$(/usr/bin/curl "${jssURL}/api/v1/auth/invalidate-token" --silent  --header "Authorization: Bearer ${apiToken}" -X POST)
    fi
}

GetJamfProAPIToken

# Use the groupID provides to get the list of computer IDs in that group
apiURL="JSSResource/computergroups/id/$groupID"

idList=$(curl -s \
	--header "Authorization: Bearer ${apiToken}" --header "accept: text/xml" \
	--url "${jssURL}/${apiURL}" \
	--request GET | /usr/bin/xpath -e '/computer_group/computers/computer/id/text()' 2>/dev/null | /usr/bin/tr '\n' ',' | /usr/bin/sed 's/,$//')

# Send an UnmanageDevice comamnd to the list of IDs
apiURL="JSSResource/computercommands/command/UnmanageDevice/id/$idList"

curl -s \
	--header "Authorization: Bearer ${apiToken}" --header "accept: text/xml" \
	--url "${jssURL}/${apiURL}" \
	--request POST

InvalidateToken

exit 0