Home > iOS, Jamf Pro, Jamf Pro API, Mac administration, macOS, Scripting > Backing up smart and static groups from Jamf Pro

Backing up smart and static groups from Jamf Pro

When working with smart and static groups on Jamf Pro, especially more complex smart groups, I prefer to download then 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 groups
  2. I can track changes to the groups
  3. If needed, I can make a change to a smart group and upload via the API instead of having to edit in the web console.

Up until recently, I didn’t have a good process for handling this but I was able to develop a way as part of working with an engineer from Jamf. After some work, I was able to build two scripts which do the following:

  1. Use the Jamf Pro API to identify the Jamf Pro ID numbers of the smart and static groups.
  2. Download each group as an XML file using its Jamf Pro ID number.
  3. Format the downloaded XML.
  4. Identify the display name of the group.
  5. Identify if it was a smart or static group.
  6. Save the downloaded XML as Group Name Here.xml to a specified download directory, based on whether it was a smart or static group.

For more details, please see below the jump.

I’ve written two scripts for this purpose:

  • Jamf_Pro_Computer_Group_Download.sh – This script is designed to download and handle macOS smart and static groups
  • Jamf_Pro_Mobile_Device_Group_Download.sh – This script is designed to download and handle iOS and tvOS smart and static groups.

For authentication, the scripts 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

Both scripts run in similar ways, with the main difference being which kind of profiles are being downloaded.

To download macOS smart and static groups:

/path/to/Jamf_Pro_Computer_Group_Download.sh

To download iOS and tvOS smart and static groups:

/path/to/Jamf_Pro_Mobile_Device_Group_Download.sh

When run, you should see output similar to that shown below.

computername:~ username$ /path/to/Jamf_Pro_Computer_Group_Download.sh
A location to store downloaded groups has not been specified.
Downloaded groups will be stored in /var/folders/q6/z5m752w547sbrcjqwd0783340000kt/T/tmp.70KOogoR.
Please enter your Jamf Pro server URL : https://jamfpro.server.here:8443
Please enter your Jamf Pro user account : jamfproadmin
Please enter the password for the jamfproadmin account:
Downloading computer group from https://jamfpro.server.here:8443…
Downloaded computer group is named: 10.11.x Macs
10.11.x Macs is a Smart group.
Saving 10.11.x Macs.xml file to /var/folders/q6/z5m752w547sbrcjqwd0783340000kt/T/tmp.70KOogoR/Smart Groups.
Downloading computer group from https://jamfpro.server.here:8443…
Downloaded computer group is named: 10.12.x Macs
10.12.x Macs is a Smart group.
Saving 10.12.x Macs.xml file to /var/folders/q6/z5m752w547sbrcjqwd0783340000kt/T/tmp.70KOogoR/Smart Groups.
Downloading computer group from https://jamfpro.server.here:8443…
Downloaded computer group is named: 10.13.x Macs
10.13.x Macs is a Smart group.
Saving 10.13.x Macs.xml file to /var/folders/q6/z5m752w547sbrcjqwd0783340000kt/T/tmp.70KOogoR/Smart Groups.
Downloading computer group from https://jamfpro.server.here:8443…
Downloaded computer group is named: 10.14.x Macs
10.14.x Macs is a Smart group.
Saving 10.14.x Macs.xml file to /var/folders/q6/z5m752w547sbrcjqwd0783340000kt/T/tmp.70KOogoR/Smart Groups.
Downloading computer group from https://jamfpro.server.here:8443…
Downloaded computer group is named: All Managed Clients
All Managed Clients is a Smart group.
Saving All Managed Clients.xml file to /var/folders/q6/z5m752w547sbrcjqwd0783340000kt/T/tmp.70KOogoR/Smart Groups.
Downloading computer group from https://jamfpro.server.here:8443…
Downloaded computer group is named: All Managed Servers
All Managed Servers is a Smart group.
Saving All Managed Servers.xml file to /var/folders/q6/z5m752w547sbrcjqwd0783340000kt/T/tmp.70KOogoR/Smart Groups.
Downloading computer group from https://jamfpro.server.here:8443…
Downloaded computer group is named: Computers w\o Secure Token
Computers w\o Secure Token is a Smart group.
Saving Encrypted VMWare.xml file to /var/folders/q6/z5m752w547sbrcjqwd0783340000kt/T/tmp.70KOogoR/Smart Groups.
Downloading computer group from https://jamfpro.server.here:8443…
Downloaded computer group is named: FileVault 2 Encryption Status
FileVault 2 Encryption Status is a Smart group.
Saving FileVault 2 Encryption Status.xml file to /var/folders/q6/z5m752w547sbrcjqwd0783340000kt/T/tmp.70KOogoR/Smart Groups.
Downloading computer group from https://jamfpro.server.here:8443…
Downloaded computer group is named: LessThanMostRecent_VLC
LessThanMostRecent_VLC is a Static group.
Saving LessThanMostRecent_VLC.xml file to /var/folders/q6/z5m752w547sbrcjqwd0783340000kt/T/tmp.70KOogoR/Static Groups.
computername:~ username$

view raw
gistfile1.txt
hosted with ❤ by GitHub

Screen Shot 2018 11 23 at 3 07 21 PM

The groups themselves will be stored in either a user-specified directory or, if no directory is specified, a directory created by the script. They will be sorted by whether the individual group is a smart or static group.

Screen Shot 2018 11 23 at 2 53 29 PM

Screen Shot 2018 11 23 at 2 53 39 PM

The scripts are available below, and at the following addresses on GitHub:

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

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

Jamf_Pro_Computer_Group_Download.sh:

#!/bin/bash
# This script is designed to use the Jamf Pro API to identify the individual IDs of
# the computer groups stored on a Jamf Pro server then do the following:
#
# 1. Download the group information as XML
# 2. Remove the group membership from the downloaded XML
# 3. Identify the group name
# 4. Categorize the downloaded group as either a smart or static computer group
# 4. Save the XML to a specified directory
# If setting up a specific user account with limited rights, here are the required API privileges
# for the account on the Jamf Pro server:
#
# Jamf Pro Server Objects:
#
# Smart Computer Groups: Read
# Static Computer Groups: Read
# If you choose to specify a directory to save the downloaded groups into,
# please enter the complete directory path into the ComputerGroupDownloadDirectory
# variable below.
ComputerGroupDownloadDirectory=""
# If the ComputerGroupDownloadDirectory isn't specified above, a directory will be
# created and the complete directory path displayed by the script.
if [[ -z "$ComputerGroupDownloadDirectory" ]]; then
ComputerGroupDownloadDirectory=$(mktemp -d)
echo "A location to store downloaded groups has not been specified."
echo "Downloaded groups will be stored in $ComputerGroupDownloadDirectory."
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=""
# 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.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
#
# If the com.github.jamfpro-info.plist file is available, the script will read in the
# relevant information from the plist file.
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%%/}
# Remove the trailing slash from the ComputerGroupDownloadDirectory variable if needed.
ComputerGroupDownloadDirectory=${ComputerGroupDownloadDirectory%%/}
DownloadComputerGroup(){
# Download the group information as XML, then strip out
# the group membership and format it.
echo "Downloading computer group from $jamfpro_url"
FormattedComputerGroup=$(curl -su "${jamfpro_user}:${jamfpro_password}" -H "Accept: application/xml" "${jamfpro_url}/JSSResource/computergroups/id/${ID}" -X GET | tr $'\n' $'\t' | sed -E 's|<computers>.*</computers>||' | tr $'\t' $'\n' | xmllint –format – )
# Identify and display the group's name.
DisplayName=$(echo "$FormattedComputerGroup" | xpath "/computer_group/name/text()" 2>/dev/null | sed -e 's|:|(colon)|g' -e 's/\//\\/g')
echo "Downloaded computer group is named: $DisplayName"
# Identify if it's a smart or static group.
if [[ $(echo "$FormattedComputerGroup" | xpath "/computer_group/is_smart/text()" 2>/dev/null) == "true" ]]; then
GroupType="Smart"
else
GroupType="Static"
fi
# Save the downloaded computer group.
echo "$DisplayName is a $GroupType group."
echo "Saving ${DisplayName}.xml file to $ComputerGroupDownloadDirectory/$GroupType Groups."
if [[ "$GroupType" = "Smart" ]]; then
if [[ -d "$ComputerGroupDownloadDirectory/$GroupType Groups" ]]; then
echo "$FormattedComputerGroup" > "$ComputerGroupDownloadDirectory/$GroupType Groups/${DisplayName}.xml"
else
mkdir -p "$ComputerGroupDownloadDirectory/$GroupType Groups"
echo "$FormattedComputerGroup" > "$ComputerGroupDownloadDirectory/$GroupType Groups/${DisplayName}.xml"
fi
elif [[ "$GroupType" = "Static" ]]; then
if [[ -d "$ComputerGroupDownloadDirectory/$GroupType Groups" ]]; then
echo "$FormattedComputerGroup" > "$ComputerGroupDownloadDirectory/$GroupType Groups/${DisplayName}.xml"
else
mkdir -p "$ComputerGroupDownloadDirectory/$GroupType Groups"
echo "$FormattedComputerGroup" > "$ComputerGroupDownloadDirectory/$GroupType Groups/${DisplayName}.xml"
fi
fi
}
ComputerGroup_id_list=$(curl -su "${jamfpro_user}:${jamfpro_password}" -H "Accept: application/xml" "${jamfpro_url}/JSSResource/computergroups" | xpath "//id" 2>/dev/null)
ComputerGroup_id=$(echo "$ComputerGroup_id_list" | grep -Eo "[0-9]+")
for ID in ${ComputerGroup_id}; do
DownloadComputerGroup
done

Jamf_Pro_Mobile_Device_Group_Download.sh:

#!/bin/bash
# This script is designed to use the Jamf Pro API to identify the individual IDs of
# the mobile device groups stored on a Jamf Pro server then do the following:
#
# 1. Download the group information as XML
# 2. Remove the group membership from the downloaded XML
# 3. Identify the group name
# 4. Categorize the downloaded group as either a smart or static mobile device group
# 4. Save the XML to a specified directory
# If setting up a specific user account with limited rights, here are the required API privileges
# for the account on the Jamf Pro server:
#
# Jamf Pro Server Objects:
#
# Smart Mobile Device Groups: Read
# Static Mobile Device Groups: Read
# If you choose to specify a directory to save the downloaded groups into,
# please enter the complete directory path into the MobileDeviceGroupDownloadDirectory
# variable below.
MobileDeviceGroupDownloadDirectory=""
# If the MobileDeviceGroupDownloadDirectory isn't specified above, a directory will be
# created and the complete directory path displayed by the script.
if [[ -z "$MobileDeviceGroupDownloadDirectory" ]]; then
MobileDeviceGroupDownloadDirectory=$(mktemp -d)
echo "A location to store downloaded groups has not been specified."
echo "Downloaded groups will be stored in $MobileDeviceGroupDownloadDirectory."
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=""
# 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.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
#
# If the com.github.jamfpro-info.plist file is available, the script will read in the
# relevant information from the plist file.
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%%/}
# Remove the trailing slash from the MobileDeviceGroupDownloadDirectory variable if needed.
MobileDeviceGroupDownloadDirectory=${MobileDeviceGroupDownloadDirectory%%/}
DownloadMobileDeviceGroup(){
# Download the group information as XML, then strip out
# the group membership and format it.
echo "Downloading mobile device group from $jamfpro_url"
FormattedMobileDeviceGroup=$(curl -su "${jamfpro_user}:${jamfpro_password}" -H "Accept: application/xml" "${jamfpro_url}/JSSResource/mobiledevicegroups/id/${ID}" -X GET | tr $'\n' $'\t' | sed -E 's|<mobile_devices>.*</mobile_devices>||' | tr $'\t' $'\n' | xmllint –format – )
# Identify and display the group's name.
DisplayName=$(echo "$FormattedMobileDeviceGroup" | xpath "/mobile_device_group/name/text()" 2>/dev/null | sed -e 's|:|(colon)|g' -e 's/\//\\/g')
echo "Downloaded mobile device group is named: $DisplayName"
# Identify if it's a smart or static group.
if [[ $(echo "$FormattedMobileDeviceGroup" | xpath "/mobile_device_group/is_smart/text()" 2>/dev/null) == "true" ]]; then
GroupType="Smart"
else
GroupType="Static"
fi
# Save the downloaded mobile device group.
echo "$DisplayName is a $GroupType group."
echo "Saving ${DisplayName}.xml file to $MobileDeviceGroupDownloadDirectory/$GroupType Groups."
if [[ "$GroupType" = "Smart" ]]; then
if [[ -d "$MobileDeviceGroupDownloadDirectory/$GroupType Groups" ]]; then
echo "$FormattedMobileDeviceGroup" > "$MobileDeviceGroupDownloadDirectory/$GroupType Groups/${DisplayName}.xml"
else
mkdir -p "$MobileDeviceGroupDownloadDirectory/$GroupType Groups"
echo "$FormattedMobileDeviceGroup" > "$MobileDeviceGroupDownloadDirectory/$GroupType Groups/${DisplayName}.xml"
fi
elif [[ "$GroupType" = "Static" ]]; then
if [[ -d "$MobileDeviceGroupDownloadDirectory/$GroupType Groups" ]]; then
echo "$FormattedMobileDeviceGroup" > "$MobileDeviceGroupDownloadDirectory/$GroupType Groups/${DisplayName}.xml"
else
mkdir -p "$MobileDeviceGroupDownloadDirectory/$GroupType Groups"
echo "$FormattedMobileDeviceGroup" > "$MobileDeviceGroupDownloadDirectory/$GroupType Groups/${DisplayName}.xml"
fi
fi
}
MobileDeviceGroup_id_list=$(curl -su "${jamfpro_user}:${jamfpro_password}" -H "Accept: application/xml" "${jamfpro_url}/JSSResource/mobiledevicegroups" | xpath "//id" 2>/dev/null)
MobileDeviceGroup_id=$(echo "$MobileDeviceGroup_id_list" | grep -Eo "[0-9]+")
for ID in ${MobileDeviceGroup_id}; do
DownloadMobileDeviceGroup
done

  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 )

Google photo

You are commenting using your Google 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: