Skip to main content

Hi folks, struggling to find an answer for this.

We have a number of machines unable to run Big Sur, so I wish to deploy a script on all of these devices that remove these devices from support. I've achieved similar in the past where I can actually remove all the local jamf components, licensed apps etc.. and also delete the JSS record for the specific device using an API call. However, looking forward, I'd like to keep the JSS record available as they may contain encryption keys that we want to keep a hold of.

Basically, I'm looking for a way to "Unmanage" these devices by unticking the "Allow Jamf Pro to perform management tasks" checkbox for each machine through the API, as I believe this will free up licenses:

I've had a look online, and found some instances that I believe provide a resolution but I can't get anything to de-select this checkbox. For example :

https://community.jamf.com/t5/jamf-pro/script-to-remove-management-through-api/m-p/233611

https://community.jamf.com/t5/jamf-pro/help-sending-post-command-to-jss-api/td-p/192968

But the above are older posts and don't seem to be using tokens for authentication, and I just don't seem to be able to get the proper syntax when attempting a POST or PUT.

I can obtain the bearer tokens fine (using encrypted JSS variables with a dedicated API account) and send other GET API calls with no problems, so don't believe this to be an authorisation issue. The account I'm using for testing purposes has full access to perform all API calls.

The script I'm attempting to create, grabs the serial from the local device, uses the serial to grab the specific computer ID in the JSS using an API call (this also works fine), and then uses the ID to attempt to unmanage the device (this below is just a stand alone script for testing purposes):

 

#!/bin/bash echo "Enter JSS username:" read USERNAME echo "Enter JSS password:" read -s PASSWORD TOKEN_EXPIRATION_EPOCH="0" function getBearerToken() { RESPONSE=$(curl -s -u "$USERNAME":"$PASSWORD" "https://<our_server>.jamfcloud.com/api/v1/auth/token" -X POST) BEARER_TOKEN=$(echo "$RESPONSE" | plutil -extract token raw -) TOKEN_EXPIRATION=$(echo "$RESPONSE" | plutil -extract expires raw - | awk -F . '{print $1}') TOKEN_EXPIRATION_EPOCH=$(date -j -f "%Y-%m-%dT%T" "$TOKEN_EXPIRATION" +"%s") } function checkTokenExpiration() { NOW_EPOCH_UTC=$(date -j -f "%Y-%m-%dT%T" "$(date -u +"%Y-%m-%dT%T")" +"%s") if [[ TOKEN_EXPIRATION_EPOCH -gt NOW_EPOCH_UTC ]] then echo "Token valid until the following epoch time: " "$TOKEN_EXPIRATION_EPOCH" else echo "No valid token available, getting new token" getBearerToken fi } function invalidateToken() { RESPONSE_CODE=$(curl -w "%{http_code}" -H "Authorization: Bearer ${BEARER_TOKEN}" "https://<our_server>.jamfcloud.com/api/v1/auth/invalidate-token" -X POST -s -o /dev/null) if [[ ${RESPONSE_CODE} == 204 ]] then echo "Token successfully invalidated" BEARER_TOKEN="" TOKEN_EXPIRATION_EPOCH="0" elif [[ ${RESPONSE_CODE} == 401 ]] then echo "Token already invalid" else echo "An unknown error occurred invalidating the token" fi } echo "Getting API token..." checkTokenExpiration # Get serial number SERIAL=$(system_profiler SPHardwareDataType | awk '/Serial/ {print $4}') /bin/echo "Serial number is $SERIAL" # Get JAMF ID of device JAMF_ID=$(curl -X GET "https://<our_server>.jamfcloud.com/JSSResource/computers/serialnumber/$SERIAL" -H "accept: application/xml" -H "Authorization: Bearer $BEARER_TOKEN" | xmllint --xpath '/computer/general/id/text()' -) /bin/echo "JAMF ID for $SERIAL is $JAMF_ID" # Unmanage the device /bin/echo "Attempting to remove device from Jamf management..." curl -X POST "https://<our_server>.jamfcloud.com/JSSResource/computercommands/command/UnmanageDevice/id/$JAMF_ID" -H "accept: application/xml" -H "Authorization: Bearer $BEARER_TOKEN" # Bin the token /bin/echo "Invalidating API token..." invalidateToken /bin/echo "Done." exit 0;

 

Strangely, when I run the above, there does appear to be an "Unenroll" command sent to the JSS:

However, nothing seems to be changing.

Apologies if I'm missing something which is fairly straight forward, but I'm just going round in circles.

Anyone any ideas?

Many thanks

 

Guys,

Help me out with the below script. Trying to send unmanage command to machine. However, I'm getting: Syntax Error Unexpected end of file

#! /bin/sh




# server connection information

jamfProURL="XXXX"

username="XXXX"

password="XXXX"




renewToken() {




# renew auth token

authToken=$( /usr/bin/curl \\

--header "Accept: application/json" \\

--header "Authorization: Bearer $token" \\

--request POST \\

--silent \\

--url "$jamfProURL/api/v1/auth/keep-alive" )




# parse auth token

token=$( /usr/bin/plutil \\

-extract token raw - <<< "$authToken" )




tokenExpiration=$( /usr/bin/plutil \\

-extract expires raw - <<< "$authToken" )




localTokenExpirationEpoch=$( TZ=UTC /bin/date -j -f "%Y-%m-%dT%T" "$tokenExpiration" "+%s" 2> /dev/null )




# update the renewal time for another 25 minutes

renewalTime=$(( $localTokenExpirationEpoch - 300 ))




}




# request auth token

authToken=$( /usr/bin/curl \\

--request POST \\

--silent \\

--url "$jamfProURL/api/v1/auth/token" \\

--user "$username:$password" )




echo "$authToken"




# parse auth token

token=$( /usr/bin/plutil \\

-extract token raw - <<< "$authToken" )




tokenExpiration=$( /usr/bin/plutil \\

-extract expires raw - <<< "$authToken" )




localTokenExpirationEpoch=$( TZ=GMT /bin/date -j \\

-f "%Y-%m-%dT%T" "$tokenExpiration" \\

+"%s" 2> /dev/null )




echo Token: "$token"

echo Expiration: "$tokenExpiration"

echo Expiration epoch: "$localTokenExpirationEpoch"




# verify auth token is valid

checkToken=$( /usr/bin/curl \\

--header "Authorization: Bearer $token" \\

--silent \\

--url "$jamfProURL/api/v1/auth" \\

--write-out "%{http_code}" )




tokenStatus=${checkToken: -3}

echo Token status: "$tokenStatus"




# subtract five minutes (300 seconds) from localTokenExpirationEpoch

renewalTime=$(( $localTokenExpirationEpoch - 300 ))




while IFS= read aDevice

do

now=$( /bin/date +"%s" )




if [[ "$renewalTime" -lt "$now" ]]; then

renewToken

fi




 ## get unique identifier for machine

udid=$(system_profiler SPHardwareDataType | awk '/UUID/ { print $3; }')




## get computer ID from Jamf server

compId=$( /usr/bin/curl \\

--request GET \\

--url "$jamfProURL/JSSResource/computers/udid/${udid}/subset/general" \\

--header "Accept: application/xml" \\

--header "Authorization: Bearer $token" \\

--xpath '/computer/general/id/text()' )




echo "${compID}"




## send unmanage command to machine

/usr/bin/curl \\

--header "Authorization: Bearer $token" \\

--request POST \\

--url "$jamfProURL/JSSResource/computercommands/command/UnmanageDevice/id/${compId}"




# expire auth token

/usr/bin/curl \\

--header "Authorization: Bearer $token" \\

--request POST \\

--silent \\

--url "$jamfProURL/api/v1/auth/invalidate-token"


 


Guys,

Help me out with the below script. Trying to send unmanage command to machine. However, I'm getting: Syntax Error Unexpected end of file

#! /bin/sh




# server connection information

jamfProURL="XXXX"

username="XXXX"

password="XXXX"




renewToken() {




# renew auth token

authToken=$( /usr/bin/curl \\

--header "Accept: application/json" \\

--header "Authorization: Bearer $token" \\

--request POST \\

--silent \\

--url "$jamfProURL/api/v1/auth/keep-alive" )




# parse auth token

token=$( /usr/bin/plutil \\

-extract token raw - <<< "$authToken" )




tokenExpiration=$( /usr/bin/plutil \\

-extract expires raw - <<< "$authToken" )




localTokenExpirationEpoch=$( TZ=UTC /bin/date -j -f "%Y-%m-%dT%T" "$tokenExpiration" "+%s" 2> /dev/null )




# update the renewal time for another 25 minutes

renewalTime=$(( $localTokenExpirationEpoch - 300 ))




}




# request auth token

authToken=$( /usr/bin/curl \\

--request POST \\

--silent \\

--url "$jamfProURL/api/v1/auth/token" \\

--user "$username:$password" )




echo "$authToken"




# parse auth token

token=$( /usr/bin/plutil \\

-extract token raw - <<< "$authToken" )




tokenExpiration=$( /usr/bin/plutil \\

-extract expires raw - <<< "$authToken" )




localTokenExpirationEpoch=$( TZ=GMT /bin/date -j \\

-f "%Y-%m-%dT%T" "$tokenExpiration" \\

+"%s" 2> /dev/null )




echo Token: "$token"

echo Expiration: "$tokenExpiration"

echo Expiration epoch: "$localTokenExpirationEpoch"




# verify auth token is valid

checkToken=$( /usr/bin/curl \\

--header "Authorization: Bearer $token" \\

--silent \\

--url "$jamfProURL/api/v1/auth" \\

--write-out "%{http_code}" )




tokenStatus=${checkToken: -3}

echo Token status: "$tokenStatus"




# subtract five minutes (300 seconds) from localTokenExpirationEpoch

renewalTime=$(( $localTokenExpirationEpoch - 300 ))




while IFS= read aDevice

do

now=$( /bin/date +"%s" )




if [[ "$renewalTime" -lt "$now" ]]; then

renewToken

fi




 ## get unique identifier for machine

udid=$(system_profiler SPHardwareDataType | awk '/UUID/ { print $3; }')




## get computer ID from Jamf server

compId=$( /usr/bin/curl \\

--request GET \\

--url "$jamfProURL/JSSResource/computers/udid/${udid}/subset/general" \\

--header "Accept: application/xml" \\

--header "Authorization: Bearer $token" \\

--xpath '/computer/general/id/text()' )




echo "${compID}"




## send unmanage command to machine

/usr/bin/curl \\

--header "Authorization: Bearer $token" \\

--request POST \\

--url "$jamfProURL/JSSResource/computercommands/command/UnmanageDevice/id/${compId}"




# expire auth token

/usr/bin/curl \\

--header "Authorization: Bearer $token" \\

--request POST \\

--silent \\

--url "$jamfProURL/api/v1/auth/invalidate-token"


 


I'm really confused on what you're doing here....as it looks like two different possibilities:

  • There's a `while` loop, which isn't terminated, nor is there something it's iterating through
    • This could be what's causing the Syntax Error Unexpected end of file
  • Second, it seems you're unmanaging the device the script is running on.....so...that means the device has to be active to run it....
    • And you're saving credentials in a script, which is bad practice

 

It's also important to note that sending the Unmanage MDM Command to a device means the device must be active to receive it and become unmanaged.  In addition, on a Mac, this command only removes the MDM Profile (and related bits), it does not remove the Jamf Management Framework which consists of the `jamf` binary and other bits, which means the device will continue to check-in to the JPS.


I'm really confused on what you're doing here....as it looks like two different possibilities:

  • There's a `while` loop, which isn't terminated, nor is there something it's iterating through
    • This could be what's causing the Syntax Error Unexpected end of file
  • Second, it seems you're unmanaging the device the script is running on.....so...that means the device has to be active to run it....
    • And you're saving credentials in a script, which is bad practice

 

It's also important to note that sending the Unmanage MDM Command to a device means the device must be active to receive it and become unmanaged.  In addition, on a Mac, this command only removes the MDM Profile (and related bits), it does not remove the Jamf Management Framework which consists of the `jamf` binary and other bits, which means the device will continue to check-in to the JPS.


@MLBZ521 Using this same While loop i'm able to get the list of smart groups, but not sure why unable to send the unmanage command.

I'm passing the credential to bearer token so that no need to key in credentials each and every time.

Also, I'm running this script which already managed by the Jamf. And I would like to take your last point that it would check in back to Jamf server. Will work on it. Thanks, BTW.


@MLBZ521 Using this same While loop i'm able to get the list of smart groups, but not sure why unable to send the unmanage command.

I'm passing the credential to bearer token so that no need to key in credentials each and every time.

Also, I'm running this script which already managed by the Jamf. And I would like to take your last point that it would check in back to Jamf server. Will work on it. Thanks, BTW.


@MLBZ521 My apologies MLBZ521. After I removed the 'while' loop the script executed well. I mean without any issues profiles got removed. Thanks a lot. 


@MLBZ521 Using this same While loop i'm able to get the list of smart groups, but not sure why unable to send the unmanage command.

I'm passing the credential to bearer token so that no need to key in credentials each and every time.

Also, I'm running this script which already managed by the Jamf. And I would like to take your last point that it would check in back to Jamf server. Will work on it. Thanks, BTW.


Why are you using the `while` loop to get a list of Smart Groups?

But, as mentioned, the `while` loop is not terminated, so that is going to cause the script to fail.


@MLBZ521 My apologies MLBZ521. After I removed the 'while' loop the script executed well. I mean without any issues profiles got removed. Thanks a lot. 


As a mentioned previously, removing the MDM Profile does not remove the Jamf Management Framework which consists of the `jamf` binary and other bits, which means the device will continue to check-in to the JPS.


Guys, anyone explain me below when I execute the unmanage script via API and Bearer token renewal in terminal I'm getting this,

What's this? 

Also, I used below to delete the entry of the computer in Jamf via API, but getting the below error message and the Id having administrator privilege.

 

 


Guys, anyone explain me below when I execute the unmanage script via API and Bearer token renewal in terminal I'm getting this,

What's this? 

Also, I used below to delete the entry of the computer in Jamf via API, but getting the below error message and the Id having administrator privilege.

 

 


add:

set -x

to code after shebang, then you can see output to debug.


Guys, anyone explain me below when I execute the unmanage script via API and Bearer token renewal in terminal I'm getting this,

What's this? 

Also, I used below to delete the entry of the computer in Jamf via API, but getting the below error message and the Id having administrator privilege.

 

 


The first question:  The image indicates that `curl` is "downloading" something, for instance an ".html" file.  This is what `curl` natively does.  What it's downloading, you'd have to check.  You can add `--output ~/Downloads/file.html` to the end of your `curl` command and see what's being transmitted.

 

For the second question:  It's hard to know exactly without seeing the full `curl` command, but to me, it almost looks like the `curl` command is attempting to interact with a web server (aka host) named `DELETE`, which would obviously be incorrect.  That should be your HTTP method, not your host.  Be sure you're passing your values to the correct parameters.  e.g.

curl --url <https://jamf.pro.url:8443> --request [GET | PUT | POST | DELETE ] [...<remaining parameters>...]

That said, I don't think the code is doing what you think it's doing...  At least, the XML payload in that second image has nothing to do with deleting a computer record...


The first question:  The image indicates that `curl` is "downloading" something, for instance an ".html" file.  This is what `curl` natively does.  What it's downloading, you'd have to check.  You can add `--output ~/Downloads/file.html` to the end of your `curl` command and see what's being transmitted.

 

For the second question:  It's hard to know exactly without seeing the full `curl` command, but to me, it almost looks like the `curl` command is attempting to interact with a web server (aka host) named `DELETE`, which would obviously be incorrect.  That should be your HTTP method, not your host.  Be sure you're passing your values to the correct parameters.  e.g.

curl --url <https://jamf.pro.url:8443> --request [GET | PUT | POST | DELETE ] [...<remaining parameters>...]

That said, I don't think the code is doing what you think it's doing...  At least, the XML payload in that second image has nothing to do with deleting a computer record...


@MLBZ521 Below is the curl command for the deletion of the computer entry in Jamf.

/usr/bin/curl \\

--header "Authorization: Bearer $token"\\

--request DELETE \\

--url "$jamfProURL/JSSResource/computers/udid/${compId}"

Sure, will try add output parameter and check. Thanks.


@MLBZ521 Below is the curl command for the deletion of the computer entry in Jamf.

/usr/bin/curl \\

--header "Authorization: Bearer $token"\\

--request DELETE \\

--url "$jamfProURL/JSSResource/computers/udid/${compId}"

Sure, will try add output parameter and check. Thanks.


That looks correct for what I can see.  What's the value of your `$comdId` variable?

That said, that command and the screenshot for the results of that command do not match at all.


Guys, help me with the script,

Requirements:
1. Once the jamf unenroll script executed, I would like to let the customer must get notification "system is going to reboot in 2 mins" and after 2 mins should restart automatically.

2. Another script to remove the CA certificate profile from Profile tab in system preference.

Thanks in advance.


I believe you have a misunderstanding of how things work...

1.  Unless you're running this on the device that is being unenrolled...this isn't possible....and if you are doing that....that's a very bad idea...  Either way, why are you bothering with rebooting them?

2.  Not sure what you're referring to here...  This sounds like a custom Profile and you can't locally remove Profiles installed via MDM when the device is ADE Enrolled...


I believe you have a misunderstanding of how things work...

1.  Unless you're running this on the device that is being unenrolled...this isn't possible....and if you are doing that....that's a very bad idea...  Either way, why are you bothering with rebooting them?

2.  Not sure what you're referring to here...  This sounds like a custom Profile and you can't locally remove Profiles installed via MDM when the device is ADE Enrolled...


The reason to reboot the machine is our customer is moving out of jamf and getting the enrolled in Intune. After the Jamf profile removed, we were unable to enroll it intune unless we reboot the machine. 

2. As soon as we enroll the device in Jamf, unlike the other profiles, customer created a profile to CA certificate install. Normal script isn't remove the CA Profile.


I believe you have a misunderstanding of how things work...

1.  Unless you're running this on the device that is being unenrolled...this isn't possible....and if you are doing that....that's a very bad idea...  Either way, why are you bothering with rebooting them?

2.  Not sure what you're referring to here...  This sounds like a custom Profile and you can't locally remove Profiles installed via MDM when the device is ADE Enrolled...


Guys, Please find the below screenshot and let me know how to remove this profile.. It's not getting removed by running remove jamf framework command. 

Because of which unable to enroll it in another MDM solution. Kindly help. Thanks.

 


that CA is installed at user level..  so you can remove that by clicking on the minus button, or via terminal / script


It looks like this device was enrolled via UIE and not ADE.  If that the case, you don't even need the API script to unmanage the device.  Simply running `jamf removeFramework` would remove the MDM Profile and the Jamf Pro management Framework.

If that Profile isn't being removed with the MDM Profile, then, as jamf-42 eluded to, you can remove it via the `profiles` command.  You'll just need to identify which Profile it is to remove it.


It looks like this device was enrolled via UIE and not ADE.  If that the case, you don't even need the API script to unmanage the device.  Simply running `jamf removeFramework` would remove the MDM Profile and the Jamf Pro management Framework.

If that Profile isn't being removed with the MDM Profile, then, as jamf-42 eluded to, you can remove it via the `profiles` command.  You'll just need to identify which Profile it is to remove it.


The reason why I've API is to unmanage machine from Jamf side thatsy.. 


The reason why I've API is to unmanage machine from Jamf side thatsy.. 


Are you wanting to unmanage the device in Jamf Pro when it is being "unmanaged" (Framework and such) on the device, in other words, at the same time?

If so, I have a little project I wrote years ago to migrate devices from one Jamf Pro instance to another.  It could adapt the code from it for your needs:  https://github.com/MLBZ521/jamfMigrator 


@rcoleman , very nice script! Worked for me. We've got a couple hundred Macs on stock shelves so it's not practical to fire each one up to run the script locally. Neither is it all that practical to deselect "Allow Jamf Pro to perform management tasks" for each record individually. I'd like to make a smart group of Macs not checked in in, say, 60 days and listed as unassigned and have those each pulled out of management by having this script run on their JSS records.

I can't figure out how to trigger that. Without those shelved Macs checking in, how would I prompt this policy to run? As they hit the 60 day mark or if someone marks their inventory record as "unassigned" I'd like the script to run. 

Any ideas to make this happen?

Thanks,

- Scott


@rcoleman , very nice script! Worked for me. We've got a couple hundred Macs on stock shelves so it's not practical to fire each one up to run the script locally. Neither is it all that practical to deselect "Allow Jamf Pro to perform management tasks" for each record individually. I'd like to make a smart group of Macs not checked in in, say, 60 days and listed as unassigned and have those each pulled out of management by having this script run on their JSS records.

I can't figure out how to trigger that. Without those shelved Macs checking in, how would I prompt this policy to run? As they hit the 60 day mark or if someone marks their inventory record as "unassigned" I'd like the script to run. 

Any ideas to make this happen?

Thanks,

- Scott


Glad it helps! Sorry, I'm not exactly sure what you mean when you say 'unassigned'? If I'm understanding correctly, you want to create a smart group for machines that have not checked in within 60 days, and then have this script execute and disable the 'Allow Jamf Pro to perform management tasks' checkbox for all devices in the smart group?

I'm certain there would be a better way to go about this but all I can think of at the moment is to create the smart group, then use an API call to obtain a list of all the devices in the smart group and then iterate through them and disable the option. You would still need to manually run the script once every day though, unless you create a LaunchDaemon to run the script every day using the 'StartCalendarInterval' option. Performing it this way though would require passwords to be entered into the script (needed for the API call), either in plain text or obfuscated, which of course is not ideal.


Yes, that was it. "Unassigned" means not currently attached to a user. On a stock room shelf.

I opted to just export the contents of a smarlist periodically (two or three times a year maybe) and copy paste those SNs into your script as an array and run that locally from my Mac. Works very nicely. Thanks again for it!

- Scott

Looks like this:

 

#!/bin/bash
 
# This can't be run from Jamf. We're just storing it here.
# Download it to your Mac and run it in Terminal.
 
echo "Enter JSS username:"
read USERNAME
echo "Enter JSS password:"
read -s PASSWORD
 
TOKEN_EXPIRATION_EPOCH="0"
 
function getBearerToken() {
    RESPONSE=$(curl -s -u "$USERNAME":"$PASSWORD" "https://jssurl:8443/api/v1/auth/token" -X POST)
    OS_MAJOR_VERSION=$(sw_vers -buildVersion | cut -c 1-2)
    echo "OS Major Version: $OS_MAJOR_VERSION"
    if [ "$OS_MAJOR_VERSION" -lt 21 ]; then
        # Get the token info
        BEARER_TOKEN=$(echo $RESPONSE | python -c 'import json,sys;obj=json.load(sys.stdin);print obj["token"]')
        # Get the expiration date
        TOKEN_EXPIRATION=$(echo $RESPONSE | python -c 'import json,sys;obj=json.load(sys.stdin);print obj["expires"]')
    # If we are running Monterey or later then we can use plutil to parse json
    else    
        # Get the token info
        BEARER_TOKEN=$(echo "$RESPONSE" | plutil -extract token raw -)    
        # Get the token expiration date
        TOKEN_EXPIRATION=$(echo "$RESPONSE" | plutil -extract expires raw - | awk -F . '{print $1}')
    fi
TOKEN_EXPIRATION_EPOCH=$(date -j -f "%Y-%m-%dT%T" "$TOKEN_EXPIRATION" +"%s")
}
 
function checkTokenExpiration() {
    NOW_EPOCH_UTC=$(date -j -f "%Y-%m-%dT%T" "$(date -u +"%Y-%m-%dT%T")" +"%s")
    if [[ TOKEN_EXPIRATION_EPOCH -gt NOW_EPOCH_UTC ]]
    then
        echo "Token valid until the following epoch time: " "$TOKEN_EXPIRATION_EPOCH"
    else
        echo "No valid token available, getting new token"
        getBearerToken
    fi
}
 
function invalidateToken() {
RESPONSE_CODE=$(curl -w "%{http_code}" -H "Authorization: Bearer ${BEARER_TOKEN}" "https://rcimac.rci.rogers.com:8443/api/v1/auth/invalidate-token" -X POST -s -o /dev/null)
if [[ ${RESPONSE_CODE} == 204 ]]
then
echo "Token successfully invalidated"
BEARER_TOKEN=""
TOKEN_EXPIRATION_EPOCH="0"
elif [[ ${RESPONSE_CODE} == 401 ]]
then
echo "Token already invalid"
else
echo "An unknown error occurred invalidating the token"
fi
}
 
echo "Getting API token..."
checkTokenExpiration
 
# Paste in a list of Mac SNs to be removed from management:
 
unmanage=(
SN#####
SN#####
SN#####
)
for SERIAL in ${unmanage[@]}
do
 
# This next commented code is to get the serial number of the Mac from which the script 
# is running in the case of performing the script on this local Mac to remove it from management.
# I've turned it off in favour of using an array of provided SNs of other Macs. See above.
# to remove from management.
 
# Get local serial number:
 
# SERIAL=$(system_profiler SPHardwareDataType | awk '/Serial/ {print $4}')
# /bin/echo "Serial number is $SERIAL"
 
# Get JAMF ID of device from API looked by SN found locally or provided in
# $unmanage array:
JAMF_ID=$(curl -X GET "https://rcimac.rci.rogers.com:8443/JSSResource/computers/serialnumber/$SERIAL" -H "accept: application/xml" -H "Authorization: Bearer $BEARER_TOKEN" | xmllint --xpath '/computer/general/id/text()' -)
 
# API call to de-select "Allow Jamf Pro to perform management tasks" in the JSS for this device:
curl --request PUT --url "https://rcimac.rci.rogers.com:8443/JSSResource/computers/id/$JAMF_ID" -H "Content-Type: application/xml" -H "Accept: application/xml" -H "Authorization: Bearer $BEARER_TOKEN" -d '<computer><general><remote_management><managed>false</managed></remote_management></general></computer>'
 
/bin/echo "JAMF ID for $SERIAL is $JAMF_ID and it is now unmanaged in the JSS"
done
 
# Bin the token
/bin/echo "Invalidating API token..."
invalidateToken
 
/bin/echo "Done."
 
exit 0;