Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Jamf_Pro_MDM_Device_Lock_with_Report script
#!/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_with_Report.sh /path/to/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 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 2935 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 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
#
# This script will also generate a report in .tsv format with information similar to what's shown below:
#
#
# |Jamf Pro ID Number|Make |Model |Serial Number|UDID |Jamf Pro URL |MDM Lock Successful|
# |------------------|-----|---------------------------|-------------|------------------------------------|---------------------------------------------------------|-------------------|
# |10734 |Apple|MacBook Pro (13-inch, 2018)|C02TW0WAHX874|C66B7C82-9CAB-4C89-85BE-7271121592A8|https://jamf.pro.server.here/computers.html?id=10734 |Yes |
# |858 |Apple|MacBook Pro (13-inch, 2018)|C027251024N23|159C6524-5069-41EC-9EDE-81158843F2EC|https://jamf.pro.server.here/computers.html?id=858 |No |
# |421 |Apple|MacBook Pro (13-inch, 2018)|Q027251024R23|A5C73F1F-35BD-4E27-BE63-E5760F886A1A|https://jamf.pro.server.here/computers.html?id=421 |Yes |
# |1217 |Apple|MacBook Pro (13-inch, 2018)|C02F0U5WAHX54|D59F50C3-3559-4B6A-AE04-81FF6BF25349|https://jamf.pro.server.here/computers.html?id=1217 |Yes |
#
# 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
report_file="$(mktemp).tsv"
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
# 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 both
# curl and the echo message immediately below.
pin_code=$(echo $pin_code | tr -d '\r')
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
ComputerRecord=$(curl -sfu "$jamfpro_user:$jamfpro_password" "${jamfpro_url}/JSSResource/computers/id/$jamf_pro_id" -H "Accept: application/xml" 2>/dev/null)
Make=$(echo "$ComputerRecord" | xmllint --xpath '//computer/hardware/make/text()' - 2>/dev/null)
MachineModel=$(echo "$ComputerRecord" | xmllint --xpath '//computer/hardware/model/text()' - 2>/dev/null)
SerialNumber=$(echo "$ComputerRecord" | xmllint --xpath '//computer/general/serial_number/text()' - 2>/dev/null)
UDIDIdentifier=$(echo "$ComputerRecord" | xmllint --xpath '//computer/general/udid/text()' - 2>/dev/null)
jamfproURL=$(echo "$jamfpro_url"/computers.html?id="$jamf_pro_id")
if [[ ! -f "$report_file" ]]; then
touch "$report_file"
printf "Jamf Pro ID Number\tMake\tModel\tSerial Number\tUDID\tJamf Pro URL\tMDM Lock Successful\n" > "$report_file"
fi
# 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."
if [[ $? -eq 0 ]]; then
printf "$jamf_pro_id\t$Make\t$MachineModel\t$SerialNumber\t$UDIDIdentifier\t${jamfproURL}\tYes\n" >> "$report_file"
else
echo "ERROR! Failed to read computer record with id $jamf_pro_id"
fi
else
echo -e "\nERROR! MDM lock of computer with Jamf Pro ID $jamf_pro_id failed."
printf "$jamf_pro_id\t$Make\t$MachineModel\t$SerialNumber\t$UDIDIdentifier\t${jamfproURL}\tNo\n" >> "$report_file"
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 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
if [[ -f "$report_file" ]]; then
echo "Report on Macs available here: $report_file"
fi
exit "$exitCode"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment