Mass Icon Upload

Contributor III

Would anyone know if there exists a way to mass-upload icons to the JSS, as in the ones you select during policy creation? I'd like to populate the JSS with common ones, versus creating a policy and selecting a new icon every time.

As a follow up, where are icons you upload during policy creation stored? Thanks...



I am also interested in this. I have a lot of test icons we uploaded that I would like to remove

New Contributor III

Does this answer?

Legendary Contributor III

So, technically speaking, there is a way to do this using the JSS API. There is a fileuploads resource that can be used to do this. However, it requires a policy as a target. You can't just upload a bunch of icons into nothing. They need a target, but it can be done.

If you can give me a little while, I can probably come up with a script that can take a folder as a source of the icons to upload and loop over them uploading them to the JSS to a target temp policy, which I assume will add each icon in to the db one at a time.

As for removing the icons, that's a different ball of wax. Do some searches in the Feature Requests section. There are several requests I believe (certainly one) that ask for the ability to manage the icons in the database. Yes, they get stored in the database and there is no easy way to manage them other that thru direct MySQL commands. Some of the FR threads have some commands that may help with removing or purging out old icons.
FWIW, I totally agree with those requests. We really need a way to manage those icons. I've got so many duplicate icons its just ridiculous at this point.

Legendary Contributor III

@steve.summers As a quick follow up, below is a script I put together and did some minimal testing on for the purpose of uploading icons within a folder to the JSS.

It of course uses the API for this, and you will need to use an account that can at least create and edit policies, though deleting them would also be helpful. Why delete privileges? Because as I mentioned above, to upload Self Service icons requires needing a policy to target. The script will create a quick temp policy, disabled and scoped to nothing (so no danger of it ever doing anything) to use as a target for the file uploads. At the end, it will try to then delete that policy, since it was only there as a temporary placeholder. All the uploaded icons remain in the JSS db.


## Script:    
## Author:              Mike Morales (mm2270)
## Last Modification:   2017-Mar-02
## Description:
##      This script can be used to upload a folder of icons in .png or .gif format to your JSS
## Usage:
##      /path/to/ <path/to/folder/with/icons/>

## JSS API information goes in these variables
## Edit these to your full JSS URL and an account that has read/write privileges for policies

## Sanity check to make sure a path to a folder was passed in parameter 1 to the script
if [ "$1" == "" ]; then
    echo -e "A path to a folder of icons was not passed to the script.
Please drag in a folder to Terminal or copy/paste/type in a path when running this script"
    exit 0

## Clean up any trailing slash from the JSS URL

## Function to cleanup temp files and policies after completion
function CLEANUP ()

## Attempt to delete the temp policy from the JSS
/usr/bin/curl -sfku "${APIUSER}:${APIPASS}" "${JSSURL}/JSSResource/policies/id/$NEWPOLICYID" -X DELETE

if [ "$?" == "0" ]; then
    echo "Policy $NEWPOLICYID removed"
    echo "Error removing policy id: $NEWPOLICYID. You may need to manually remove the policy"

## Attempt to delete the tmp xml file
rm -f "$FILE"

if [ "$?" == "0" ]; then
    echo "Temp policy xml file removed"
    echo "Error removing temp policy xml file: ${FILE}. You may need to manually remove the file"

exit 0


## Function to upload the icons located in the source path
function UPLOAD_ICONS ()

while read ICONFILE; do
    ICONNAME=$(basename "$ICONFILE")
    /usr/bin/curl -sfku "${APIUSER}:${APIPASS}" "${JSSURL}/JSSResource/fileuploads/policies/id/$NEWPOLICYID" -F name=@"${ICONFILE}" -X POST
    if [ "$?" == 0 ]; then
        echo "$ICONNAME successfully uploaded"
        echo "$ICONNAME errored when attempting to upload it. Continuing..."
done < <(printf '%s

## Run the cleanup function


## Function to ask for confirmation of uploads before continuing

## Get a list of icons from the source dir
SOURCEICONS=$(find "$ICONFILESPATH" -name *.png -o -name *.gif)

if [ ! -z "$SOURCEICONS" ]; then
    echo "The following icons were found:
    printf '%s

    echo -e "
Proceed with uploading these icons? (y/n)"

    read userResponse

    case "$userResponse" in
        echo "Canceling uploads and cleaning up"
        echo "Invalid response. Please enter 'y' or 'n' to confirm or cancel the uploads"
    echo "No valid icons were located in the source directory"
    exit 0


## Function to make a temp policy in the JSS as a target for the icon uploads
function MAKE_TEMP_POLICY ()

## Create temp xml for policy creation
cat << EOF > /tmp/temp_icon_policy.xml
<?xml version="1.0" encoding="UTF-8"?>


## Check for the new xml file
if [ $? == 0 ]; then
    echo "Error creating temp xml for policy. Exiting"
    exit 1

# Upload xml to create new policy
NEWPOLICYID=$(/usr/bin/curl -sfku "${APIUSER}:${APIPASS}" "${JSSURL}/JSSResource/policies/id/0" -X POST -T "$FILE" 2>&1 | xmllint --format - | awk -F'>|<' '/<id>/{print $3}')

if [ "$NEWPOLICYID" != "" ]; then
    ## Check that we got a valid ID back
    if [[ $((NEWPOLICYID/NEWPOLICYID)) == "1" ]]; then
        echo "Policy created with ID $NEWPOLICYID"
        echo "May have been a problem creating the policy"
        exit 1
    echo "No policy ID was returned"
    exit 1

## Run the confirm uploads function


## Start here. Create a new temp policy as a target for the icon uploads

Quick usage on the script.

  • Copy/paste the script into an editor like TextWrangler, BBEdit, Xcode, etc (all preferable over TextEdit), and save it with a name ending in .sh somewhere on your Mac.
  • If you used one of the preferred apps above, there's no need for this step, but if you used a plain text editor like TextEdit, it might be. Open Terminal and run chmod +x /path/to/ where /path/to/ is the full path to the file.
  • Open Terminal (if needed) and drag the script you just saved into it. It should populate the full path.
  • Now drag in a folder that contains the icons you want to upload. Again, Terminal will fill in the full path. There should be no need to edit or change anything, though I haven't tested this with odd characters in paths, so I'm not sure how it would handle all cases.
  • Press Return and the script will run. At some point, it will print out all the icons it located in the folder and ask you to confirm if you want to proceed. You need to type in a 'y' or 'n' for Yes or No respectively.
  • If you typed y, it loops over all the icons and attempts to upload each one, reporting on the status for each.
  • When done, it attempts to clean up, removing the temp policy and the temp xml created for making the policy.

As an aside, this could work well in conjunction with my Self Service Icon Maker app that you can find on my github page: Self Service Icon Maker. As a workflow for setting up a brand new JSS, you could grab anywhere from 1 to hundreds of applications, drop them onto my Self Service Icon Maker app and it will quickly create a whole mess of Self Service ready 128 x 128 pixel .png icons into a folder on your Desktop. Then run the above script and drag that same folder into it as the source. Within a couple of minutes, you can have hundreds of icons populated in your JSS, without so much as needing to log into it!

Finally, as I mentioned, while I did test this on my JSS, it was only basic testing. Use it cautiously at first since its creating objects and uploading files, and deleting the policy at the end. I also can't be sure how it will handle strange file names. I know the icons my app creates should work since those are the ones I tested and had no issues with any of them. Outside of that, I don't really know, but feel free to let me know if you see any issues with it.

This script isn't posted to my github page for the moment, since I don't know how much interest there is in it yet.

Contributor III

Awesome!!!! Loving this...I'll give it a whirl and respond! :-D. sweet..!

Contributor III

@mm2270 Hey, I was able to get around to testing this script. It didn't exactly work. Here is what it did:
-Found the icons I supplied
-Prompted me for verification
-Error'd while attempting to upload

Is there something on the JSS i need to look at, something maybe not set right?
I supplied a screenshot of the script output.
Thanks again. If I can try another version, I'll be glad to. c18438cb999b478d8124a4fdb50e3173

Legendary Contributor III

Hey @steve.summers the only thing that comes to mind is that the API account may not have policy edit privileges on your JSS? It seems like it's able to create the policy though, and delete it at the end. So I'm not sure why it would fail to upload the images. Uploading the icons uses the edit privilege I believe.

What size (dimensions) are the icons? And they are definitely PNG files right? The JSS can only take a few different image formats for upload. I think just png and gif if I'm not mistaken.


@mm2270 thanks for the tip! You're awesome!

New Contributor III

@mm2270 my attempts to run this only output "folder is a directory" Tried to create a new empty folder and put a few png files but no luck.

I'm trying to make custom wallpaper lock screens for iPad with qr codes that are the serial numbers. I'm able to upload single files using the F name=@ syntax but when I put a variable for the file path I get a curl (26) error that can't open the file. Found some info about CurlFile being needed but I'm not sure the syntax.

I was feeding the API a csv file that had the full file path listed. I'd much rather drag a folder into terminal.

Legendary Contributor III

@estes So, the script in question is a couple of years old at this point, and it's possible some aspects of the API have changed. I'd have to run it through tests on current Jamf Pro versions to see. I'm not sure when I'll be able to get to that exactly, but once I do I'll post back with any results or changes needed.