Every so often, it may be necessary to generate a report from Jamf Pro on which computers are assigned to a particular person. To assist with this task, I’ve written a script which uses the Jamf Pro Classic API to search through the computer inventory records and generate a report in .tsv format.
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
Computer inventory records
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
This script imports a list of usernames from a plaintext file and uses that information to generate a report about the computers assigned to that username.
Usage:
./Generate_Assigned_Mac_Report_From_Jamf_Pro_Usernames.sh usernames.txt
Plaintext file format should look like this:
The script can also accept one username as input, if a plaintext file containing usernames
is not available.
Usage:
./Generate_Assigned_Mac_Report_From_Jamf_Pro_Usernames.sh
Once the username(s) are read from in from the plaintext file or from manual input, the script takes the following actions:
1. Uses the Jamf Pro API to download all information about the matching computer inventory record in XML format.
2. Pulls the following information out of the inventory entry:
3. Create a report in tab-separated value (.tsv) format which contains the following information about the deleted Macs
This script will generate a report in .tsv format with information similar to what’s shown below:
One user:
Multiple users:
This script is available below and also from GitHub at the following location:
#!/bin/bash | |
# This script imports a list of usernames from a plaintext file | |
# and uses that information to generate a report about the computers | |
# assigned to that username. | |
# | |
# ./Generate_Assigned_Mac_Report_From_Jamf_Pro_Usernames.sh usernames.txt | |
# | |
# The script can also accept one username as input, if a plaintext file containing usernames | |
# is not available. | |
# | |
# Usage: ./Generate_Assigned_Mac_Report_From_Jamf_Pro_Usernames.sh | |
# | |
# Plaintext file format should look like this: | |
# | |
# first_username_goes_here | |
# second_username_goes_here | |
# third_username_goes_here | |
# fourth_username_goes_here | |
# | |
# Once the username(s) are read from in from the plaintext file or from manual input, the script takes the following actions: | |
# | |
# 1. Uses the Jamf Pro API to download all information about the matching computer inventory record in XML format. | |
# 2. Pulls the following information out of the inventory entry: | |
# | |
# Jamf Pro ID | |
# Assigned user's username | |
# Assigned user's email | |
# Manufacturer | |
# Model | |
# Serial Number | |
# Hardware UDID | |
# | |
# 3. Create a report in tab-separated value (.tsv) format which contains the following information | |
# about the deleted Macs | |
# | |
# Jamf Pro ID | |
# Assigned user's username | |
# Assigned user's email | |
# Manufacturer | |
# Model | |
# Serial Number | |
# Hardware UDID | |
# Jamf Pro URL for the computer inventory record | |
report_file="$(mktemp).tsv" | |
# 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.githubjamfpro-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.githubjamfpro-info jamfpro_user account_username_goes_here | |
# | |
# To store the account password in the plist file: | |
# defaults write com.githubjamfpro-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. | |
jamf_plist="$HOME/Library/Preferences/com.github.jamfpro-info.plist" | |
if [[ -r "$jamf_plist" ]]; then | |
if [[ -z "$jamfpro_url" ]]; then | |
jamfpro_url=$(defaults read "${jamf_plist%.*}" jamfpro_url) | |
fi | |
if [[ -z "$jamfpro_user" ]]; then | |
jamfpro_user=$(defaults read "${jamf_plist%.*}" jamfpro_user) | |
fi | |
if [[ -z "$jamfpro_password" ]]; then | |
jamfpro_password=$(defaults read "${jamf_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 "" | |
# Set initial status for exit | |
error=0 | |
filename="$1" | |
# If a text file with usernames has not been provided, the script | |
# will prompt for a single username. | |
if [[ -z "$filename" ]]; then | |
read -p "Please enter the relevant username : " assigned_user | |
assigned_user_filename=$(mktemp) | |
/usr/bin/touch "$assigned_user_filename" | |
echo "$assigned_user" > "$assigned_user_filename" | |
fi | |
if [[ -z "$filename" ]] && [[ -r "$assigned_user_filename" ]]; then | |
filename="$assigned_user_filename" | |
fi | |
# Remove the trailing slash from the Jamf Pro URL if needed. | |
jamfpro_url=${jamfpro_url%%/} | |
progress_indicator() { | |
spinner="⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏" | |
while : | |
do | |
for i in $(seq 0 7) | |
do | |
echo -n "${spinner:$i:1}" | |
echo -en "\010" | |
/bin/sleep 0.10 | |
done | |
done | |
} | |
echo "Report being generated. File location will appear below once ready." | |
progress_indicator & | |
SPIN_PID=$! | |
trap "kill -9 $SPIN_PID" $(seq 0 15) | |
# Create temp files for data | |
idtempfile=$(mktemp) | |
xmltempfile=$(mktemp) | |
/usr/bin/touch "$xmltempfile" | |
# Get all computers that are associated with username | |
while read -r UserToMatch; do | |
# Get all computers associated with usernames | |
/usr/bin/curl -sfu "$jamfpro_user:$jamfpro_password" "${jamfpro_url}/JSSResource/computers/match/${UserToMatch}" -H "Accept: application/xml" | xmllint –format – >> "$xmltempfile" | |
done < "$filename" | |
# Extract the Jamf Pro computer IDs | |
/bin/cat "$xmltempfile" | sed -n 's:.*<id>\(.*\)</id>.*:\1:p' > "$idtempfile" | |
while read -r ID; do | |
if [[ "$ID" =~ ^[0-9]+$ ]]; then | |
ComputerRecord=$(/usr/bin/curl -sfu "$jamfpro_user:$jamfpro_password" "${jamfpro_url}/JSSResource/computers/id/$ID" -H "Accept: application/xml" 2>/dev/null) | |
if [[ ! -f "$report_file" ]]; then | |
/usr/bin/touch "$report_file" | |
printf "Jamf Pro ID Number\tAssigned User\tAssigned User Email\tMake\tModel\tSerial Number\tUDID\tJamf Pro URL\n" > "$report_file" | |
fi | |
Make=$(echo "$ComputerRecord" | xmllint –xpath '//computer/hardware/make/text()' – 2>/dev/null) | |
AssignedUser=$(echo "$ComputerRecord" | xmllint –xpath '//computer/location/username/text()' – 2>/dev/null) | |
AssignedUserEmail=$(echo "$ComputerRecord" | xmllint –xpath '//computer/location/email_address/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) | |
JamfProID=$(echo "$ComputerRecord" | xmllint –xpath '//computer/general/id/text()' – 2>/dev/null) | |
UDIDIdentifier=$(echo "$ComputerRecord" | xmllint –xpath '//computer/general/udid/text()' – 2>/dev/null) | |
JamfProURL=$(echo "$jamfpro_url"/computers.html?id="$JamfProID") | |
if [[ $? -eq 0 ]]; then | |
printf "$JamfProID\t$AssignedUser\t$AssignedUserEmail\t$Make\t$MachineModel\t$SerialNumber\t$UDIDIdentifier\t${JamfProURL}\n" >> "$report_file" | |
else | |
echo "ERROR! Failed to read computer record with id $JamfProID" | |
error=1 | |
fi | |
fi | |
done < "$idtempfile" | |
# Clean up temp files | |
if [[ -f "$assigned_user_filename" ]]; then | |
rm -rf "$assigned_user_filename" | |
fi | |
if [[ -f "$xmltempfile" ]]; then | |
rm -rf "$xmltempfile" | |
fi | |
if [[ -f "$idtempfile" ]]; then | |
rm -rf "$idtempfile" | |
fi | |
kill -9 "$SPIN_PID" 2>/dev/null | |
if [[ -f "$report_file" ]]; then | |
echo "Report on Macs available here: $report_file" | |
fi | |
exit "$error" |