|
#!/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" |