Home > Jamf Pro, Jamf Pro API, Jamf Pro Classic API, Scripting > Backing up Self Service icon graphic files from Jamf Pro

Backing up Self Service icon graphic files from Jamf Pro

While working with Self Service policies on Jamf Pro, I prefer to download the graphic files used for the Self Service icons and back them up to GitHub or a similar internal source control tool. The reasons I do this are the following:

  1. I have an off-server backup for the graphic files.
  2. I can track changes to the Self Service policy icons.

To help me manage this, I have a script which does the following:

  1. Use the Jamf Pro Classic API to identify which policies are Self Service policies with icons.
  2. Download each Self Service icon’s graphic file using the URI for each file.
  3. Save the downloaded graphics file to a specified download directory, using a filename format like shown below:

policy_name_here-jamf_pro_policy_id_here-graphics_file_name_here

As part of the download process, any spaces are removed from the graphic file’s file names and the policy names. Any colons ( : ) are likewise replaced with dashes ( ) to prevent problems for the macOS filesystem.

For more details, please see below the jump.

For authentication, the script can accept hard-coded values in the script, 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

When the script runs, you should see output similar to that shown below.


username@computername ~ % /Users/Shared/Jamf_Pro_Download_Self_Service_Icons.sh
A location to store downloaded scripts has not been specified.
Downloaded Self Service icons will be stored in /var/folders/j1/xv08602n6vs80zmnmxrzj7m80000ks/T/tmp.u2DUeALb.
Checking 14 policies for Self Service icons …
Downloading AmazonCorretto11-108-AmazonCorettoJDK11.png to /var/folders/j1/xv08602n6vs80zmnmxrzj7m80000ks/T/tmp.u2DUeALb.
Downloading Arq-109-Arq.png to /var/folders/j1/xv08602n6vs80zmnmxrzj7m80000ks/T/tmp.u2DUeALb.
Downloading MicrosoftOneNote-23-Microsoft_OneNote.png to /var/folders/j1/xv08602n6vs80zmnmxrzj7m80000ks/T/tmp.u2DUeALb.
Downloading MicrosoftOffice365-94-Office2016.png to /var/folders/j1/xv08602n6vs80zmnmxrzj7m80000ks/T/tmp.u2DUeALb.
Downloading GetLogs-107-Acme-corp.png to /var/folders/j1/xv08602n6vs80zmnmxrzj7m80000ks/T/tmp.u2DUeALb.
Downloading BoottomacOSRecoveryorDiagnostics-106-Screen Shot 2020-03-24 at 4.34.21 PM copy.png to /var/folders/j1/xv08602n6vs80zmnmxrzj7m80000ks/T/tmp.u2DUeALb.
Downloading EncryptMacs-6-FileVault.png to /var/folders/j1/xv08602n6vs80zmnmxrzj7m80000ks/T/tmp.u2DUeALb.
Downloading CheckforAppleSoftwareUpdates-105-install.png to /var/folders/j1/xv08602n6vs80zmnmxrzj7m80000ks/T/tmp.u2DUeALb.
Downloading MicrosoftRemoteDesktop-22-Microsoft_Remote_Desktop.png to /var/folders/j1/xv08602n6vs80zmnmxrzj7m80000ks/T/tmp.u2DUeALb.
Downloading Slack-104-Slack.png to /var/folders/j1/xv08602n6vs80zmnmxrzj7m80000ks/T/tmp.u2DUeALb.
10 Self Service icon files downloaded to /var/folders/j1/xv08602n6vs80zmnmxrzj7m80000ks/T/tmp.u2DUeALb.
username@computername ~ %

view raw

gistfile1.txt

hosted with ❤ by GitHub

Screen Shot 2022 01 12 at 3 02 30 PM

 

The graphic files themselves will be stored in either a user-specified directory or, if no directory is specified, a directory created by the script.

Screen Shot 2022 01 12 at 3 03 54 PM

I’ve also included support for using Bearer Tokens for authentication for the Jamf Pro Classic API, which is a feature available on Jamf Pro 10.35.0 and later. This is enabled by default, so the script will try to get a Bearer Token and use it for authentication.

If you’re using this script with Jamf Pro 10.34.2 and earlier, please set the NoBearerToken variable in the script as follows:

NoBearerToken="yes"

This will set the script to use Basic Authentication instead of Bearer Tokens for authentication to the Classic API.

The script is available below, and at the following addresses on GitHub:

https://github.com/rtrouton/rtrouton_scripts/tree/master/rtrouton_scripts/Casper_Scripts/Jamf_Pro_Download_Self_Service_Icons


#!/bin/bash
# This script uses the Jamf Pro Classic API to detect which Self Service policies
# have icons and downloads the icon graphic files to a download directory.
# Set default exit code
exitCode=0
# If you're on Jamf Pro 10.34.2 or earlier, which doesn't support using Bearer Tokens
# for Classic API authentication, set the NoBearerToken variable to the following value
# as shown below:
#
# yes
#
# NoBearerToken="yes"
#
# If you're on Jamf Pro 10.35.0 or later, which does support using Bearer Tokens
# for Classic API authentication, set the NoBearerToken variable to the following value
# as shown below:
#
# NoBearerToken=""
NoBearerToken=""
# If you choose to specify a directory to save the downloaded Self Service icons
# into, please enter the complete directory path into the SelfServiceIconDownloadDirectory
# variable below.
SelfServiceIconDownloadDirectory=""
# If the SelfServiceIconDownloadDirectory isn't specified above, a directory will be
# created and the complete directory path displayed by the script.
if [[ -z "$SelfServiceIconDownloadDirectory" ]]; then
SelfServiceIconDownloadDirectory=$(mktemp -d)
echo "A location to store downloaded scripts has not been specified."
echo "Downloaded Self Service icons will be stored in $SelfServiceIconDownloadDirectory."
fi
GetJamfProAPIToken() {
# This function uses Basic Authentication to get a new bearer token for API authentication.
# Use user account's username and password credentials with Basic Authorization to request a bearer token.
if [[ $(/usr/bin/sw_vers -productVersion | awk -F . '{print $1}') -lt 12 ]]; then
api_token=$(/usr/bin/curl -X POST –silent -u "${jamfpro_user}:${jamfpro_password}" "${jamfpro_url}/api/v1/auth/token" | python -c 'import sys, json; print json.load(sys.stdin)["token"]')
else
api_token=$(/usr/bin/curl -X POST –silent -u "${jamfpro_user}:${jamfpro_password}" "${jamfpro_url}/api/v1/auth/token" | plutil -extract token raw –)
fi
}
APITokenValidCheck() {
# Verify that API authentication is using a valid token by running an API command
# which displays the authorization details associated with the current API user.
# The API call will only return the HTTP status code.
api_authentication_check=$(/usr/bin/curl –write-out %{http_code} –silent –output /dev/null "${jamfpro_url}/api/v1/auth" –request GET –header "Authorization: Bearer ${api_token}")
}
CheckAndRenewAPIToken() {
# Verify that API authentication is using a valid token by running an API command
# which displays the authorization details associated with the current API user.
# The API call will only return the HTTP status code.
APITokenValidCheck
# If the api_authentication_check has a value of 200, that means that the current
# bearer token is valid and can be used to authenticate an API call.
if [[ ${api_authentication_check} == 200 ]]; then
# If the current bearer token is valid, it is used to connect to the keep-alive endpoint. This will
# trigger the issuing of a new bearer token and the invalidation of the previous one.
if [[ $(/usr/bin/sw_vers -productVersion | awk -F . '{print $1}') -lt 12 ]]; then
api_token=$(/usr/bin/curl "${jamfpro_url}/api/v1/auth/keep-alive" –silent –request POST –header "Authorization: Bearer ${api_token}" | python -c 'import sys, json; print json.load(sys.stdin)["token"]')
else
api_token=$(/usr/bin/curl "${jamfpro_url}/api/v1/auth/keep-alive" –silent –request POST –header "Authorization: Bearer ${api_token}" | plutil -extract token raw –)
fi
else
# If the current bearer token is not valid, this will trigger the issuing of a new bearer token
# using Basic Authentication.
GetJamfProAPIToken
fi
}
InvalidateToken() {
# Verify that API authentication is using a valid token by running an API command
# which displays the authorization details associated with the current API user.
# The API call will only return the HTTP status code.
APITokenValidCheck
# If the api_authentication_check has a value of 200, that means that the current
# bearer token is valid and can be used to authenticate an API call.
if [[ ${api_authentication_check} == 200 ]]; then
# If the current bearer token is valid, an API call is sent to invalidate the token.
authToken=$(/usr/bin/curl "${jamfpro_url}/api/v1/auth/invalidate-token" –silent –header "Authorization: Bearer ${api_token}" -X POST)
# Explicitly set value for the api_token variable to null.
api_token=""
fi
}
# 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=""
# Read the appropriate values from ~/Library/Preferences/com.github.jamfpro-info.plist
# if the file is available. To create the file, run the following commands:
#
# defaults write $HOME/Library/Preferences/com.github.jamfpro-info jamfpro_url https://jamf.pro.server.here
# defaults write $HOME/Library/Preferences/com.github.jamfpro-info jamfpro_user API_account_username_goes_here
# defaults write $HOME/Library/Preferences/com.github.jamfpro-info jamfpro_password API_account_password_goes_here
#
if [[ -f "$HOME/Library/Preferences/com.github.jamfpro-info.plist" ]]; then
if [[ -z "$jamfpro_url" ]]; then
jamfpro_url=$(defaults read $HOME/Library/Preferences/com.github.jamfpro-info jamfpro_url)
fi
if [[ -z "$jamfpro_user" ]]; then
jamfpro_user=$(defaults read $HOME/Library/Preferences/com.github.jamfpro-info jamfpro_user)
fi
if [[ -z "$jamfpro_password" ]]; then
jamfpro_password=$(defaults read $HOME/Library/Preferences/com.github.jamfpro-info 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%%/}
if [[ -z "$NoBearerToken" ]]; then
GetJamfProAPIToken
fi
# The following function downloads individual Jamf Pro policy as XML data
# then mines the policy data for the relevant information.
CheckSelfServicePolicyIcons(){
local PolicyId="$1"
if [[ -n "$PolicyId" ]]; then
if [[ -z "$NoBearerToken" ]]; then
CheckAndRenewAPIToken
local DownloadedXMLData=$(/usr/bin/curl -s –header "Authorization: Bearer ${api_token}" -H "Accept: application/xml" "${jamfpro_url}/JSSResource/policies/id/$PolicyId")
else
local DownloadedXMLData=$(/usr/bin/curl -su "${jamfpro_user}:${jamfpro_password}" -H "Accept: application/xml" "${jamfpro_url}/JSSResource/policies/id/$PolicyId")
fi
local PolicyName=$( echo "$DownloadedXMLData" | xmllint –xpath '/policy/general/name/text()'2>/dev/null)
local SelfServicePolicyCheck=$(echo "$DownloadedXMLData" | xmllint –xpath '/policy/self_service/use_for_self_service/text()'2>/dev/null)
local SelfServiceIcon=$(echo "$DownloadedXMLData" | xmllint –xpath '/policy/self_service/self_service_icon/id/text()'2>/dev/null)
local SelfServiceIconName=$(echo "$DownloadedXMLData" | xmllint –xpath '/policy/self_service/self_service_icon/filename/text()'2>/dev/null)
local SelfServiceIconURI=$(echo "$DownloadedXMLData" | xmllint –xpath '/policy/self_service/self_service_icon/uri/text()'2>/dev/null)
# If a policy is detected as being a Self Service policy with an icon where a download URL is also available,
# the icon is downloaded to the Self Service icon download directory. Spaces and colons will be removed from
# the policy names and icon filenames.
if [[ "$SelfServicePolicyCheck" = "true" ]] && [[ -n "$SelfServiceIcon" ]] && [[ -n "$SelfServiceIconURI" ]]; then
DownloadSafePolicyName=$(echo ${PolicyName} | sed -e 's/:/-/g' -e 's/ //g')
DownloadSafeIconName=$(echo ${SelfServiceIconName} | sed -e 's/:/-/g' -e 's/ //g')
echo "Downloading $DownloadSafePolicyName$PolicyId$SelfServiceIconName to $SelfServiceIconDownloadDirectory."
curl -s ${SelfServiceIconURI} -X GET > "${SelfServiceIconDownloadDirectory}"/"${DownloadSafePolicyName}""${PolicyId}""${DownloadSafeIconName}"
fi
fi
}
# Download all Jamf Pro policy ID numbers
if [[ -z "$NoBearerToken" ]]; then
CheckAndRenewAPIToken
PolicyIDList=$(/usr/bin/curl -s –header "Authorization: Bearer ${api_token}" -H "Accept: application/xml" "${jamfpro_url}/JSSResource/policies" | xmllint –xpath '//id'2>/dev/null)
else
PolicyIDList=$(/usr/bin/curl -su "${jamfpro_user}:${jamfpro_password}" -H "Accept: application/xml" "${jamfpro_url}/JSSResource/policies" | xmllint –xpath '//id'2>/dev/null)
fi
PolicyIDs=$(echo "$PolicyIDList" | grep -Eo "[0-9]+")
PoliciesCount=$(echo "$PolicyIDs" | grep -c ^)
echo "Checking $PoliciesCount policies for Self Service icons …"
echo
# Download latest version of all Self Service icon graphic files. For performance reasons, we parallelize the execution.
MaximumConcurrentJobs=10
ActiveJobs=0
for anID in ${PolicyIDs}; do
((ActiveJobs=ActiveJobs%MaximumConcurrentJobs)); ((ActiveJobs++==0)) && wait
CheckSelfServicePolicyIcons $anID &
done
# Wait for remaining concurrent jobs to finish
sleep 10
DirectoryCount=$(ls ${SelfServiceIconDownloadDirectory} | wc -l | awk '$1=$1')
# Display how many Self Service icon files were downloaded.
echo ""
echo "$DirectoryCount Self Service icon files downloaded to $SelfServiceIconDownloadDirectory."
if [[ -z "$NoBearerToken" ]]; then
InvalidateToken
fi
exit $exitCode

  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: