Enable Lost Mode - API Question

jbisgett
Contributor II

I’m trying to enable lost mode and play sound on a group of iPads. I’ve found a way to enable lost mode, but I can’t figure out how to also send play sound command.

xmlData="<mobile_device_command>
<general>
<command>EnableLostMode</command>
<lost_mode_message>$lostModeMsg</lost_mode_message>
<lost_mode_phone>$lostModePhone</lost_mode_phone> 
</general>
<mobile_devices> 
   <mobile_device>
      <id>$i</id> 
   </mobile_device>
</mobile_devices>
</mobile_device_command>

See here for full script: https://gist.github.com/talkingmoose/f44d0d87d08b48daa0e887a6239c1766

1 ACCEPTED SOLUTION

jbisgett
Contributor II

For those in need or interested, JAMF support responded to my ticket regarding this and provided this information to make it work:

Update the xml <general> section of the script I was using with the information below.

<general>
        <command>EnableLostMode</command>
        <lost_mode_message>$lostModeMsg</lost_mode_message>
        <lost_mode_phone>$lostModePhone</lost_mode_phone>
        <lost_mode_footnote>$lostModeFootnote</lost_mode_footnote>
        <always_enforce_lost_mode>true</always_enforce_lost_mode>
        <lost_mode_with_sound>true</lost_mode_with_sound>
    </general>

Info from support:
It appears the enforce lost mode and play lost mode sound options are actually parameters of the EnableLostMode command. These two options are detailed in the API page at the same level as the message, phone number, and footnote which is why we place them where they are and their corresponding descriptions are below:

always_enforce_lost_mode - 'false' if the lost mode is NOT to be re-enabled after the device is wiped and re-enrolled. Defaults to 'true'.
lost_mode_with_sound - 'true' if the device is to play a loud sound while the lost mode is enabled. Defaults to 'false'.

View solution in original post

8 REPLIES 8

jbisgett
Contributor II

I would also like to know how to include the Always Force Lost Mode command.

jbisgett
Contributor II

For those in need or interested, JAMF support responded to my ticket regarding this and provided this information to make it work:

Update the xml <general> section of the script I was using with the information below.

<general>
        <command>EnableLostMode</command>
        <lost_mode_message>$lostModeMsg</lost_mode_message>
        <lost_mode_phone>$lostModePhone</lost_mode_phone>
        <lost_mode_footnote>$lostModeFootnote</lost_mode_footnote>
        <always_enforce_lost_mode>true</always_enforce_lost_mode>
        <lost_mode_with_sound>true</lost_mode_with_sound>
    </general>

Info from support:
It appears the enforce lost mode and play lost mode sound options are actually parameters of the EnableLostMode command. These two options are detailed in the API page at the same level as the message, phone number, and footnote which is why we place them where they are and their corresponding descriptions are below:

always_enforce_lost_mode - 'false' if the lost mode is NOT to be re-enabled after the device is wiped and re-enrolled. Defaults to 'true'.
lost_mode_with_sound - 'true' if the device is to play a loud sound while the lost mode is enabled. Defaults to 'false'.

jbastean
New Contributor

To follow up on this, Big Sur changed the xpath version, which breaks the script linked above. There are a few possible fixes. I chose to follow Armin Briegel's example and just declare a local function named xpath that checks the OS version and parses as needed.

Here's my update that works as of Big Sur 11.1: gist. Note that I did not include the play sound option, nor the enforce lost mode (because it defaults to true) but you can obviously add them if desired.

palmna
Contributor

I've been playing around with this script and it seems promising.  I'm using this script with no changes made other than the "EDIT ME" section where you specify the lostModeMsg, lostModePhone, and lostModeFootnote.  

The issue I'm running into is with the device list.  I have a list of serial numbers where each serial is on a new line, no space, no commas.  When I run the script I get the error:

no element found at line 1, column 0, byte 0:

^
 at /System/Library/Perl/Extras/5.18/darwin-thread-multi-2level/XML/Parser.pm line 187.

 

If I edit the device list and remove all but 1 serial number it works great.  As soon as I add more than 1 serial I'm back to the error above.  I've tested this on Catalina, Big Sur, and Monterey...what am I missing? 

palmna
Contributor

I figured out the issue:  the original script is using the wrong header information.

Instead of

    --header "Accept: text/xml" \
and
    --header "Content-Type: text/xml" \

both headers should read:

    --header "Accept: application/xml" \
and
    --header "Content-Type: application/xml" \

 

jbisgett
Contributor II

I've updated this script to use bearer tokens, Jamf Policy variables, and pull device ids from a Mobile Device group instead of a csv. The api user will need read access to Mobile Device Smart Groups and Mobile Device Static groups, depending on which type of group the devices are in.

 

#!/bin/bash
# Based on script written by talkingmoose
# https://gist.github.com/talkingmoose/f44d0d87d08b48daa0e887a6239c1766

###############################
## Declare Variables
###############################

# Server connection information
jssURL=${4}
jssUser=${5}
jssPass=${6}

# Mobile Device groupID
deviceGroupID=${7}

# Lost Mode messaging
lostModeMsg=${8}
lostModePhone=${9}
lostModeFootnote=${10}

###############################
## Don't Edit Below Here
###############################

# Request Auth Token - valid for 30 minutes
authToken=$( /usr/bin/curl \
--request POST \
--silent \
--url "$jssURL/api/v1/auth/token" \
--user "$jssUser:$jssPass" )

# 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 )

# Subtract five minutes (300 seconds) from localTokenExpirationEpoch
renewalTime=$(( $localTokenExpirationEpoch - 300 ))

renewToken()	{

	# renew auth token
	authToken=$( /usr/bin/curl \
	--header "Accept: application/json" \
	--header "Authorization: Bearer $token" \
	--request POST \
	--silent \
	--url "$jssURL/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=GMT /bin/date -j \
	-f "%Y-%m-%dT%T" "$tokenExpiration" \
	+"%s" 2> /dev/null )
	
	# update the renewal time for another 25 minutes
	renewalTime=$(( $localTokenExpirationEpoch - 300 ))

}

# Make an API call to retrieve a list of device IDs from the group
deviceList=$( /usr/bin/curl \
--header "Accept: application/xml" \
--header "Authorization: Bearer $token" \
--request GET \
--silent \
--url "$jssURL/JSSResource/mobiledevicegroups/id/$deviceGroupID" | xmllint --format - 2>/dev/null | awk -F'>|<' '/<id>/{print $3}' | sed 1,2d )

# Loop through the device IDs and send an EnableLostMode command to Jamf via the API
 for deviceID in $deviceList; do
	
	# If renewaltime is less than current time, renew auth token
 	now=$( /bin/date +"%s" )

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

	# Log command execution
	logTime=$(date "+%Y-%m-%d - %H:%M:%S:")
 	echo "$logTime Sending EnableLostMode command to device $deviceID..."

 	# Construct EnableLostMode API command
 	xmlData="<mobile_device_command>
 	<general>
 		<command>EnableLostMode</command>
 		<lost_mode_message>$lostModeMsg</lost_mode_message>
 		<lost_mode_phone>$lostModePhone</lost_mode_phone>
 		<lost_mode_footnote>$lostModeFootnote</lost_mode_footnote>
 		<always_enforce_lost_mode>true</always_enforce_lost_mode>
 		<lost_mode_with_sound>true</lost_mode_with_sound>
 	</general>
 	<mobile_devices>
 		<mobile_device>
 			<id>$deviceID</id>
 		</mobile_device>
 	</mobile_devices>
 	</mobile_device_command>"
	
 	# flattened XML
 	flatXML=$( /usr/bin/xmllint --noblanks - <<< "$xmlData" )
	
	# Send EnableLostMode command
 	/usr/bin/curl \
     --header "Authorization: Bearer $token" \
     --request POST \
     --silent \
     --header "Content-Type: application/xml" \
     --url "$jssURL/JSSResource/mobiledevicecommands/command/EnableLostMode" -d "$flatXML"

 done

# expire auth token
/usr/bin/curl \
--header "Authorization: Bearer $token" \
--request POST \
--silent \
--url "$jssURL/api/v1/auth/invalidate-token"

exit 0

obi-k
Valued Contributor III

Hi @jbisgett 

 

Trying to give this a shot. New to API stuff. Once you declare your variables, how do you execute this API script? Probably a dumb question, but I'm learning.

obi-k
Valued Contributor III

For others in need, the script below worked. Make sure the jss api user account permissions are correct. Ended up needing 5 boxes checked off.

https://github.com/robjschroeder/Jamf-API-Scripts/blob/main/api-EnableLostMode-MobileDeviceGroup.sh

Thank you Jamf and shout out to Kristen B!