Home > Jamf Pro, Jamf Pro API, Mac administration, macOS, Mobile Device Management, Scripting > Using the Jamf Pro API to send device lock commands via MDM to multiple Macs

Using the Jamf Pro API to send device lock commands via MDM to multiple Macs

Most Mac admins have had this conversation at one point or another over the course of their careers:

“$Very Important Person left their Mac behind in a cab! What do we do?”
“OK, no worries. We can send a command to lock the computer or have it erase itself. Do you want it locked or wiped?”

At that point, the admin pulls up their MDM admin console and depending on what the response was (lock or wipe), send out the appropriate MDM command accompanied by a PIN code. Once received, the Mac will then turn itself into a paperweight which does or doesn’t erase itself.

Doing these one at a time is a pretty straightforward process. For example, here’s how it looks in Jamf Pro to send a device lock command via MDM:

1. Log into Jamf Pro using an account which can send lock commands via MDM.
2. Go to the appropriate computer inventory record.

Screen Shot 2021 05 28 at 2 48 00 PM

3. Select the Management tab.

Screen Shot 2021 05 28 at 2 48 01 PM

4. In the Management Commands section of the Management tab, click the Lock Computer button.

Screen Shot 2021 05 28 at 1 57 43 PM

5. Enter the PIN code which will later be used to unlock the Mac. If desired, you can also enter a message which will appear on the lock screen.

Screen Shot 2021 05 28 at 1 58 56 PM

6. Click the Lock Computer button.

Screen Shot 2021 05 28 at 1 58 57 PM

7. Click the OK button in the confirmation window.

Screen Shot 2021 05 28 at 1 59 42 PM

 

Once the device lock command has been sent, the Lock Computer button’s text should temporarily change to Command Sent.

Screen Shot 2021 05 28 at 1 59 49 PM

 

For a small number of machines (10 or less), the method outlined above works fine. But once you get beyond that number, this process gets time-consuming and unwieldy. Fortunately, there is also a way to use the Jamf Pro Classic API to send device lock commands. For more details, please see below the jump.

Pre-requisites:

If setting up a specific Jamf Pro user account for this purpose with limited rights, here are the required API privileges for the account on the Jamf Pro server:

Jamf Pro Server Objects:

Computers: Create

Jamf Pro Server Action:

Send Computer Remote Lock Command

Once you have your Jamf Pro account credentials handled, you can use an API command similar to the one shown below to send a device lock command (referred to in Apple’s MDM documentation as DeviceLock.)

 

/usr/bin/curl -su username_here:password_here https://jamf.pro.server.address.here:port_here/JSSResource/computercommands/command/DeviceLock/passcode/PIN_code_goes_here/id/Jamf_Pro_Computer_ID_goes_here -H "Content-Type: application/xml" -X POST

For example, here’s the command used to lock a Jamf Pro-enrolled Mac with the following Jamf Pro server, Jamf Pro account with the necessary privileges, Jamf Pro computer ID and desired PIN code.

 

/usr/bin/curl -su mdmlock:correct_horse_Battery_Staple https://jamfpro.company.com:8443/JSSResource/computercommands/command/DeviceLock/passcode/123456/id/9345 -H "Content-Type: application/xml" -X POST

 

Note: Using the API to send lock commands does have a limitation, where it is not possible to include a message to appear on the lock screen. If a message must appear on the lock screen, I recommend using the method described earlier for sending lock commands from the computer inventory record in the Jamf Pro admin console.

To help make the task of sending MDM lock commands easier, I’ve written a script which uses the API command above to read input from a .csv file and use that information to send device lock commands to multiple Macs. This script reads a .csv file formatted as follows:

Jamf Pro ID, PIN Code” as the first line

Subsequent lines:
Column 1: A Mac’s Jamf Pro ID
Column 2: Device Lock PIN code



Jamf Pro ID PIN Code
26 165234
52 197898
1226 201145

view raw

mdmlock.csv

hosted with ❤ by GitHub

For authentication, the script can accept manual input or values stored in a ~/Library/Preferences/com.github.jamfpro-info.plist file.

The plist file can be created by running the following commands and substituting your own values where appropriate:

To store the Jamf Pro URL in the plist file:

defaults write com.github.jamfpro-info jamfpro_url https://jamf.pro.server.goes.here:port_number_goes_here

To store the account username in the plist file:

defaults write com.github.jamfpro-info jamfpro_user account_username_goes_here

To store the account password in the plist file:

defaults write com.github.jamfpro-info jamfpro_password account_password_goes_here

Once you have authentication handled, the script is designed to run as shown below:

/path/to/Jamf_Pro_MDM_Device_Lock.sh /path/to/filename_goes_here.csv

Once executed, the script will then do the following:

  1. Skip the first line of the .csv file (this is the “Jamf Pro ID, PIN Code” line.)
  2. Read each subsequent line of the .csv one at a time and assign the values of column 1 and column 2 to separate variables.
  3. Use the variables in an API POST call to identify a Jamf Pro computer inventory record using the Jamf Pro ID listed in the .csv file and lock the Mac in question using the PIN code listed in the .csv file.

A successful MDM lock should produce output similar to that shown below:

 


Attempting to send MDM lock to Jamf Pro ID 2935 with PIN code 348202.
<?xml version="1.0" encoding="UTF-8"?><computer_command><command><name>DeviceLock</name><command_uuid>98d915a4-6132-4535-b474-c8381e48425a</command_uuid><computer_id>2935</computer_id></command></computer_command>
Successfully locked computer with Jamf Pro ID 1925 with PIN code 348202.

view raw

gistfile1.txt

hosted with ❤ by GitHub

Failures should look similar to this:

Attempting to send MDM lock to Jamf Pro ID 1234567890 with PIN code 348201.

ERROR! MDM lock of computer with Jamf Pro ID 1234567890 failed.
Attempting to send MDM lock to Jamf Pro ID 29352935 with PIN code 12345.

Invalid PIN code data provided: 12345
Attempting to send MDM lock to Jamf Pro ID AA2319 with PIN code 348206.

Invalid Jamf Pro ID data provided: AA2319

 


username@computername ~ % /path/to/Jamf_Pro_MDM_Device_Lock.sh filename_goes_here.csv
Attempting to send MDM lock to Jamf Pro ID 1234567890 with PIN code 348201.
ERROR! MDM lock of computer with Jamf Pro ID 1234567890 failed.
Attempting to send MDM lock to Jamf Pro ID 2935 with PIN code 348202.
<?xml version="1.0" encoding="UTF-8"?><computer_command><command><name>DeviceLock</name><command_uuid>98d915a4-6132-4535-b474-c8381e48425a</command_uuid><computer_id>2935</computer_id></command></computer_command>
Successfully locked computer with Jamf Pro ID 1925 with PIN code 348202.
Attempting to send MDM lock to Jamf Pro ID 29352935 with PIN code 12345.
Invalid PIN code data provided: 12345
Attempting to send MDM lock to Jamf Pro ID AA2319 with PIN code 348206.
Invalid Jamf Pro ID data provided: AA2319
username@computername ~ %

view raw

gistfile1.txt

hosted with ❤ by GitHub

 

This script is available below and also from GitHub at the following location:

https://github.com/rtrouton/rtrouton_scripts/tree/main/rtrouton_scripts/Casper_Scripts/Jamf_Pro_MDM_Device_Lock


#!/bin/bash
# Sends MDM lock commands using Jamf Pro's Classic API.
#
# This script reads a .csv file formatted as follows:
#
# "Jamf Pro ID, PIN Code" as the first line
#
# Subsequent lines:
# Column 1: A Mac's Jamf Pro ID
# Column 2: Device Lock PIN code
#
# Example:
#
# Jamf Pro ID, PIN Code
# 26,165234
# 52,197898
# 1226,201145
#
# This script is designed to run as shown below:
#
# /path/to/Jamf_Pro_MDM_Device_Lock.sh filename_goes_here.csv
#
# Once executed, the script will then do the following:
#
# Skip the first line of the .csv file (this is the "Jamf Pro ID, PIN Code" line.)
# Read each subsequent line of the .csv one at a time and assign the values of column 1
# and column 2 to separate variables.
#
# Use the variables in an API PUT call to identify a Jamf Pro computer inventory record
# using the Jamf Pro ID listed in the .csv file and lock the Mac in question using the
# the PIN code listed in the .csv file.
#
# A successful MDM lock should produce output similar to that shown below:
#
# Attempting to send MDM lock to Jamf Pro ID 1925 with PIN code 348202.
# <?xml version="1.0" encoding="UTF-8"?><computer_command><command><name>DeviceLock</name><command_uuid>98d915a4-6132-4535-b474-c8381e48425a</command_uuid><computer_id>1925</computer_id></command></computer_command>
# Successfully locked computer with Jamf Pro ID 1925 with PIN code 348202.
#
# Failures should look similar to this:
#
# Attempting to send MDM lock to Jamf Pro ID 1234567890 with PIN code 348201.
#
# ERROR! MDM lock of computer with Jamf Pro ID 1234567890 failed.
#
# Attempting to send MDM lock to Jamf Pro ID 19251925 with PIN code 12345.
#
# Invalid PIN code data provided: 12345
#
# Attempting to send MDM lock to Jamf Pro ID AA2319 with PIN code 348206.
#
# Invalid Jamf Pro ID data provided: AA2319
#
# If setting up a specific user account with limited rights, here are the required API privileges
# for the account on the Jamf Pro server:
#
# Jamf Pro Server Objects:
#
# Computers: Create
#
# Jamf Pro Server Action:
#
# Send Computer Remote Lock Command
# If you choose to hardcode API information into the script, set one or more of the following values:
#
# The username for an account on the Jamf Pro server with sufficient API privileges
# The password for the account
# The Jamf Pro URL
# Set the Jamf Pro URL here if you want it hardcoded.
jamfpro_url=""
# Set the username here if you want it hardcoded.
jamfpro_user=""
# Set the password here if you want it hardcoded.
jamfpro_password=""
# If you do not want to hardcode API information into the script, you can also store
# these values in a ~/Library/Preferences/com.github.jamfpro-info.plist file.
#
# To create the file and set the values, run the following commands and substitute
# your own values where appropriate:
#
# To store the Jamf Pro URL in the plist file:
# defaults write com.github.jamfpro-info jamfpro_url https://jamf.pro.server.goes.here:port_number_goes_here
#
# To store the account username in the plist file:
# defaults write com.github.jamfpro-info jamfpro_user account_username_goes_here
#
# To store the account password in the plist file:
# defaults write com.github.jamfpro-info jamfpro_password account_password_goes_here
#
# If the com.github.jamfpro-info.plist file is available, the script will read in the
# relevant information from the plist file.
jamfpro_plist="$HOME/Library/Preferences/com.github.jamfpro-info.plist"
filename="$1"
exitCode=0
if [[ -r "$jamfpro_plist" ]]; then
if [[ -z "$jamfpro_url" ]]; then
jamfpro_url=$(defaults read "${jamfpro_plist%.*}" jamfpro_url)
fi
if [[ -z "$jamfpro_user" ]]; then
jamfpro_user=$(defaults read "${jamfpro_plist%.*}" jamfpro_user)
fi
if [[ -z "$jamfpro_password" ]]; then
jamfpro_password=$(defaults read "${jamfpro_plist%.*}" jamfpro_password)
fi
fi
# If the Jamf Pro URL, the account username or the account password aren't available
# otherwise, you will be prompted to enter the requested URL or account credentials.
if [[ -z "$jamfpro_url" ]]; then
read -p "Please enter your Jamf Pro server URL : " jamfpro_url
fi
if [[ -z "$jamfpro_user" ]]; then
read -p "Please enter your Jamf Pro user account : " jamfpro_user
fi
if [[ -z "$jamfpro_password" ]]; then
read -p "Please enter the password for the $jamfpro_user account: " -s jamfpro_password
fi
echo
# Remove the trailing slash from the Jamf Pro URL if needed.
jamfpro_url=${jamfpro_url%%/}
# Verify that the file exists and is readable
if [[ -r $filename ]]; then
# Set IFS to read the .csv file by setting commas as the character
# which separates fields in the .csv file
while IFS=, read jamf_pro_id pin_code || [ -n "$jamf_pro_id" ]; do
echo "Attempting to send MDM lock to Jamf Pro ID $jamf_pro_id with PIN code $pin_code."
# All Jamf Pro IDs should be positive numbers and
# PIN codes should be all positive numbers that are
# exactly six digits, so we check for those conditions
# before proceeding.
if [[ "$jamf_pro_id" =~ ^[0-9]+$ ]]; then
if [[ "$pin_code" =~ ^[0-9]{6} ]]; then
# Due to IFS redefining field separation, the $pin_code
# value has a carriage return included. The next check
# below trims that off before it can cause problems for curl.
pin_code=$(echo $pin_code | tr -d '\r')
# If the previous checks succeeded, the curl command below
# sends the DeviceLock command, which will then be sent out
# by the Jamf Pro server. The curl command uses the "–fail"
# function to enable curl to send out an exit code, which we
# use to test if the API call was successful.
/usr/bin/curl –fail -su ${jamfpro_user}:${jamfpro_password} "$jamfpro_url/JSSResource/computercommands/command/DeviceLock/passcode/$pin_code/id/$jamf_pro_id" -H "Content-Type: application/xml" -X POST
# curl's exit status is checked below. If curl has an exit status of zero,
# the API call was sent and received successfully. If curl has a non-zero
# exit status, a warning message is displayed which indicates that the API call
# has failed.
if [[ $? -eq 0 ]]; then
echo -e "\nSuccessfully locked computer with Jamf Pro ID $jamf_pro_id with PIN code $pin_code."
else
echo -e "\nERROR! MDM lock of computer with Jamf Pro ID $jamf_pro_id failed."
fi
# If the PIN code is not all positive numbers
# and exactly six digits, a warning message is
# displayed that an invalid PIN code has been
# provided.
else
echo -e "\nInvalid PIN code provided: $pin_code"
fi
# If the Jamf Pro ID number is not all positive numbers,
# a warning message is displayed that an invalid Jamf Pro ID number
# has been provided.
else
echo -e "\nInvalid Jamf Pro ID provided: $jamf_pro_id"
fi
echo ""
done < <(tail -n +2 "$filename")
else
# If the provided .csv is not readable, a warning message
# is displayed that the file does not exist or is not readable.
echo "Input file does not exist or is not readable"
exitCode=1
fi
exit "$exitCode"

  1. September 8, 2021 at 10:05 pm

    Just stooping by to say: It’s a dang shame Jamf doesn’t provide a way to include any MESSAGE TEXT with the Lock command like it does in the GUI. (?!) There’s no reason why it couldn’t. It would be very useful for cases where you actually want the device back (i.e. Please return to X, for a shipping label: return_label@mycompany.com). Perhaps this is a Feature Request I just can’t bear to look though…

  2. November 3, 2021 at 7:32 pm

    Thanks for providing this script. I’m trying to implement it but keep getting a syntax error:

    /LockDevice.sh: line 198: syntax error near unexpected token `(‘
    /LockDevice.sh: line 198: ` done < (tail -n +2 "$filename")'

    I'm using the hardcoded URL/username/password. Not using plists. The CSV is formatted correctly.

    Did I miss a step? Am I supposed to alter line 99 to point the script to the csv filename?

  3. June 7, 2023 at 6:07 pm

    Thank you, this got us 90% there (maybe 98%) But we also figured out how to send the message too….
    We used creds save locally in plist to test, but now have this as a Self Service Policy scoped to a very small number of technicians. We feed a CSV and it locks Macs telling user why and how to get unlocked…
    curl -s -o /dev/null -w “%{http_code}” -X POST \
    -H “Authorization: Bearer $token” \
    -H “Content-Type: application/xml” \
    -d “${pin_code}${message}${jamf_id}” \
    “$jssURL/JSSResource/computercommands/command/DeviceLock”

  4. June 7, 2023 at 6:09 pm

    curl -s -o /dev/null -w “%{http_code}” -X POST \
    -H “Authorization: Bearer $token” \
    -H “Content-Type: application/xml” \
    -d “${pin_code}${message}${jamf_id}” \
    “$jssURL/JSSResource/computercommands/command/DeviceLock”

  1. No trackbacks yet.

Leave a comment