Use Jamf Pro API to remove attachments from inventory records

howie_isaacks
Valued Contributor III

I was recently working on performing some testing to find out why we are having problems with policies that install apps using an install package. We noticed that the packages would fail to download successfully. I created a policy that runs a packet capture while an application install policy that contains a package payload is running. The packet capture along with the Jamf log, and some other data all get zipped up and uploaded to each computer's inventory as an attachment. This enabled me to get the data I needed without having to ask the user to provide the data to me. I got the logs and other data that I needed to get help finding out what is causing the failed package downloads. This process created another problem. Over 100 Mac inventory records had multiple attachments from the multiple tests I ran. Jamf Pro does not provide an easy and automated way to delete the attachments. The API does provide a delete function. To run this function, we need to know the computer's Jamf ID and the individual attachment IDs. I tested the delete function in a script using CodeRunner on my own Mac. It worked exactly as expected. Of course, I knew my own Mac's Jamf ID and I was able to get the attachment IDs by viewing them in the inventory. I needed an automated way of automatically collecting the Jamf ID and attachment IDs. Once I have that information, I can run the delete function. The script below performs all the steps. First, it gets the serial number of the Mac. Next, it uses the serial number to find the Jamf Pro ID. Once the ID is obtained, it can be used to check if there are any attachments in the inventory for the Mac. The script compiles a list of the attachment IDs. The last step is to run the delete function. As I write this, 41 out of 130 Macs have run the policy with this script. I see in the policy log that they all had attachments, and the attachments were deleted. I wanted to share this to help others who may be in the same situation. I have myself to blame. I should have stayed on top of this and removed the attachments after running my test policy and downloading the files I needed. I hope this helps others! If anyone has recommendations on how to improve this script, I would appreciate that. I have only been using the API for about a year. As you will see noted at the top of my script a Jamf employee named Joshua Roskos provided the secret sauce that enabled me to find out if a computer's inventory has attachements. He posted an extension attribute for this. I used some of his code in my script.

 

#!/bin/bash

:<<ABOUT_THIS_SCRIPT
---------------------------------------------------------------------------------------------------
Finds attachments in a computer's Jamf Pro inventory and deletes them.

Inspired by https://github.com/kc9wwh/logCollection/blob/master/EA-NumAttachments.sh
Written by: Joshua Roskos | Jamf

3/12/25 - Howie Canterbury | Mac Admins Slack: HowieIsaacks
---------------------------------------------------------------------------------------------------
ABOUT_THIS_SCRIPT

# Jamf Pro API login
url="https://YourServer.jamfcloud.com"
client_id="xxxxxxxxxxxx" # Use Jamf parameter 4 instead of entering client ID here
client_secret="xxxxxxxxxxxxxxxxxx" # Use Jamf parameter 5 instead of entering client secret here

jamfAPI_auth() {
	response=$(curl --silent --location --request POST "${url}/api/oauth/token" \
		--header "Content-Type: application/x-www-form-urlencoded" \
		--data-urlencode "client_id=${client_id}" \
		--data-urlencode "grant_type=client_credentials" \
		--data-urlencode "client_secret=${client_secret}")
	token=$(echo "$response" | plutil -extract access_token raw -)
	token_expires_in=$(echo "$response" | plutil -extract expires_in raw -)
	token_expiration_epoch=$(($current_epoch + $token_expires_in - 1))
}

# Jamf Pro API authentication
jamfAPI_auth

## Validate API login (comment out when not needed)
#echo $token
#echo $token_expires_in
#echo $token_expiration_epoch

# Computer serial number
serialNumber=$( system_profiler SPHardwareDataType | grep Serial |  awk '{print $NF}' )

# Jamf Pro device ID
jamfProID=$(curl -s -H "Accept: text/xml" -H "Authorization: Bearer ${token}" ${url}/JSSResource/computers/serialnumber/"$serialNumber" | xmllint --xpath '/computer/general/id/text()' -)

# Find if there are any attachments, report their IDs, and delete them
attachmentIDs=$(curl -X GET -H "Authorization: Bearer ${token}" ${url}/JSSResource/computers/id/$jamfProID | xmllint -format - | xpath -e '/computer/purchasing/attachments' | grep "<id>" )

echo "Attachments found ${attachmentIDs}"
id_array=($(echo "$attachmentIDs" | grep -oE '[0-9]+'))

for i in "${!id_array[@]}"; do
	echo "Deleting attachment ${id_array[$i]}"
	$(curl --request DELETE \
	--url "${url}"/api/v1/computers-inventory/$jamfProID/attachments/${id_array[$i]} \
	-H "Authorization: Bearer ${token}")
done

 

4 REPLIES 4

jamf-42
Valued Contributor III

Rather than upload a blob to the device (which has always been “a bad idea”) output the data to a file, then capture with an EA. You can do that temporarily to report on such, then bin the EA and the data. 

the functionality to upload a blob to the device record still exists is historic leftover, but really should never be used.. nice cleanup script 🤓

howie_isaacks
Valued Contributor III

I think this feature of Jamf Pro is a good one. We just need to make sure we keep it cleaned up. In my case, it got seriously out of control. I blame myself for that. Upon deploying this policy and a modified version of Josh Roskos' EA, I discovered about 100 more Macs with attachments than there should have been. I think the guy who held my position before me likely used this function but didn't clean it up. Oh well. The EA made all of the Macs with an attachment get added to the smart group that I scoped the removal policy to. In total, 243 Macs were found to have attachments in their inventory and all of them got the attachments removed. If Jamf keeps this feature, they should make it possible to mass delete the attachments and also make it possible to quickly find Macs with attachments. I was happy to learn more API functionality but there is no way to find Macs with attachments without using the API.

jamf-42
Valued Contributor III

ill say it again.. uploading blobs of data to a device record, while it exists.. has never been a good idea.. and its not only me that says this: 

https://github.com/zpropheter/Jamf-Log-Grabber

howie_isaacks
Valued Contributor III

Noted 😁 Thanks for the link. This looks like a good solution so I will try it out. This whole situation made me want to work on improving the log collection process that I already have.