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
- Computers: Read
Computer inventory records
- In Jamf Pro, the username field must be populated in the User and Location section of the computer inventory record.
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:
username | |
otheruser |
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:
- 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
This script will generate a report in .tsv format with information similar to what’s shown below:
One user:
Jamf Pro ID Number | Assigned User | Assigned User Email | Make | Model | Serial Number | UDID | Jamf Pro URL | |
---|---|---|---|---|---|---|---|---|
13 | username | username@pretendco.com | Apple | Mac mini (Mid 2011) | C07GM01TDJD0 | 00BC7701-6791-573D-B461-470B44D16DF6 | https://jamfpro.pretendco.com:8443/computers.html?id=13 | |
86 | username | username@pretendco.com | Apple | iMac Pro Intel (Retina 5k, 27-inch, Late 2017) | VM0N0WRc4EjC | 564D33BC-AF4C-86CF-1DFB-AF6EDFC395A3 | https://jamfpro.pretendco.com:8443/computers.html?id=86 | |
87 | username | username@pretendco.com | Apple | iMac Pro Intel (Retina 5k, 27-inch, Late 2017) | VMWmmR2FJqk3 | 564D4A6F-280F-1EC0-5E66-178DB2D45A8A | https://jamfpro.pretendco.com:8443/computers.html?id=87 |
Multiple users:
Jamf Pro ID Number | Assigned User | Assigned User Email | Make | Model | Serial Number | UDID | Jamf Pro URL | |
---|---|---|---|---|---|---|---|---|
13 | username | username@pretendco.com | Apple | Mac mini (Mid 2011) | C07GM01TDJD0 | 00BC7701-6791-573D-B461-470B44D16DF6 | https://jamfpro.pretendco.com:8443/computers.html?id=13 | |
86 | username | username@pretendco.com | Apple | iMac Pro Intel (Retina 5k, 27-inch, Late 2017) | VM0N0WRc4EjC | 564D33BC-AF4C-86CF-1DFB-AF6EDFC395A3 | https://jamfpro.pretendco.com:8443/computers.html?id=86 | |
87 | username | username@pretendco.com | Apple | iMac Pro Intel (Retina 5k, 27-inch, Late 2017) | VMWmmR2FJqk3 | 564D4A6F-280F-1EC0-5E66-178DB2D45A8A | https://jamfpro.pretendco.com:8443/computers.html?id=87 | |
85 | otheruser | otheruser@pretendco.com | Apple | VMware Virtual Platform | VMD4TkB2CNtn | 564D6125-8B99-47F1-9867-F92CD80BF0C9 | https://jamfpro.pretendco.com:8443/computers.html?id=85 |
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" |